
上QQ阅读APP看书,第一时间看更新
How to do it...
Let's have a look at the following steps:
- Create a new VCL application and drop three TButton and a TMemo. Align all the buttons as a toolbar at the top of the form and the memo on the remaining form client area.
- From left to right, name the buttons btnGenerateXML, btnModifyXML, btnParseXML, and btnTransformXML.
- The real work on the XML will be done by the TXMLDocument component. So, drop one instance of the form and set its DOMVendor property to Omni XML.
- We will use static data as our data source. A simple matrix is enough for this recipe. Just after the implementation section of the unit, write the code that follows:
type TCarInfo = ( Manufacturer = 1, Name = 2, Currency = 3, Price = 4); var Cars: array [1 .. 4] of
array [Manufacturer .. Price] of string = ( ( 'Ferrari','360 Modena','EUR', '250,000' ), ( 'Ford', 'Mustang', 'USD', '80,000' ), ( 'Lamborghini', 'Countach', 'EUR','300,000' ), ( 'Chevrolet', 'Corvette', 'USD', '100,000' ) );
- We will use a TMemo to display the XML and the data. To keep things clear, create a public property called Xml on the form and map its setter and getter to the Memo1.Lines.Text property. Use the following code:
//...other form methods declaration private procedure SetXML(const Value: String); function GetXML: String; public property Xml: String read GetXML write SetXML; end; //...then in the implementation section function TMainForm.GetXML: String; begin Result := Memo1.Lines.Text; end; procedure TMainForm.SetXML(const Value: String); begin Memo1.Lines.Text := Value; end;
- Now, create event handlers for each button. For btnGenerateXML, write the following code:
procedure TMainForm.btnGenerateXMLClick(Sender: TObject); var RootNode, Car, CarPrice: IXMLNode; i: Integer; s: String; begin XMLDocument1.Active := True; try XMLDocument1.Version := '1.0'; RootNode := XMLDocument1.AddChild('cars'); for i := Low(Cars) to High(Cars) do begin Car := XMLDocument1.CreateNode('car'); Car.AddChild('manufacturer').Text :=
Cars[i][TCarInfo.Manufacturer]; Car.AddChild('name').Text :=
Cars[i][TCarInfo.Name]; CarPrice := Car.AddChild('price'); CarPrice.Attributes['currency'] :=
Cars[i][TCarInfo.Currency]; CarPrice.Text := Cars[i][TCarInfo.Price]; RootNode.ChildNodes.Add(Car); end; XMLDocument1.SaveToXML(s); Xml := s; finally XMLDocument1.Active := False; end; end;
- Now, we have to write the code to change the XML. In the btnModifyXML click event handler, write the following code:
procedure TMainForm.btnModifyXMLClick(Sender: TObject); var Car, CarPrice: IXMLNode; s: string; begin XMLDocument1.LoadFromXML(Xml); try Xml := ''; Car := XMLDocument1.CreateNode('car'); Car.AddChild('manufacturer').Text := 'Hennessey'; Car.AddChild('name').Text := 'Venom GT'; CarPrice := Car.AddChild('price'); CarPrice.Attributes['currency'] := 'USD'; CarPrice.Text := '600,000'; XMLDocument1.DocumentElement.ChildNodes.Add(Car); XMLDocument1.SaveToXML(s); Xml := s; finally XMLDocument1.Active := False; end; end;
- Write the following code under the btnParseXML click event handler:
procedure TMainForm.btnParseXMLClick(Sender: TObject); var CarsList: IDOMNodeList; CurrNode: IDOMNode; childidx, i: Integer; CarName, CarManufacturer, CarPrice, CarCurrencyType:
string; begin XMLDocument1.LoadFromXML(Xml); try Xml := ''; CarsList := XMLDocument1.
DOMDocument.getElementsByTagName('car'); for i := 0 to CarsList.length - 1 do begin CarName := ''; CarManufacturer := ''; CarPrice := ''; CarCurrencyType := ''; for childidx := 0 to
CarsList[i].ChildNodes.length - 1 do begin CurrNode := CarsList[i].ChildNodes[childidx]; if CurrNode.nodeName.Equals('name') then CarName := CurrNode.firstChild.nodeValue; if CurrNode.nodeName.Equals('manufacturer') then CarManufacturer := CurrNode.firstChild.nodeValue; if CurrNode.nodeName.Equals('price') then begin CarPrice := CurrNode.firstChild.nodeValue; CarCurrencyType :=
CurrNode.Attributes.
getNamedItem('currency').nodeValue; end; end; Xml := Xml +
'Name = ' + CarName + sLineBreak +
'Manufacturer = ' + CarManufacturer + sLineBreak +
'Price = ' +
CarPrice + CarCurrencyType + sLineBreak +
'-----' + sLineBreak; end; finally XMLDocument1.Active := False; end; end;
- Write the following code under the btnTransformXML click event handler:
procedure TMainForm.btnTransformClick(Sender: TObject); var LXML, LXSL: string; LOutput: string; begin LXML := TFile.ReadAllText('..\..\..\cars.xml'); LXSL := TFile.ReadAllText('..\..\..\cars.xslt'); LOutput := Transform(LXML, LXSL); TFile.WriteAllText('..\..\..\cars.html', LOutput); ShellExecute(0, PChar('open'),
PChar('file:///' +
TPath.GetFullPath('..\..\..\cars.html')), nil,
nil, SW_SHOW); end;
- Now, add the following function in your form implementation section:
function Transform(XMLData: string; XSLT: string): String; var LXML, LXSL: IXMLDocument; LOutput: WideString; begin LXML := LoadXMLData(XMLData); LXSL := LoadXMLData(XSLT); LXML.DocumentElement.TransformNode(LXSL.DocumentElement,
LOutput); Result := String(LOutput); end;
- Run the application by hitting F9 (or by going to Run | Run).
- Click on the btnGenerateXML button, and you should see some XML data in the memo.
- Click on the btnModifyXML button, and you should see some more XML in the memo.
- Click on btnParseXML, and you should see the same data as before, but with normal text representation.
- After the third click, you should see something similar to the following screenshot:

Figure 1.14: Text representation of the XML data generated and modified
- Now, copy the cars.xml and cars.xslt files from the respective recipe folder to the parent folder of your project folder and click on the btnTransformXML button.
- The system default browser should appear, showing something like the following screenshot:

Fig. 1.15 XML data transformed into HTML using an XSLT transformation