Delphi Cookbook
上QQ阅读APP看书,第一时间看更新

How to do it...

Let's have a look at the following steps:

  1. 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.
  2. From left to right, name the buttons btnGenerateXML, btnModifyXML, btnParseXML, and btnTransformXML.
  3. 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.
  4. 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' ) );
  1. 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; 

  1. 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;
  1. 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; 
  1. 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;
  1. 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;
  1. 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;
  1. Run the application by hitting F9 (or by going to Run | Run).
  2. Click on the btnGenerateXML button, and you should see some XML data in the memo.
  3. Click on the btnModifyXML button, and you should see some more XML in the memo.
  1. Click on btnParseXML, and you should see the same data as before, but with normal text representation.
  2. 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
  1. 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.
  1. The system default browser should appear, showing something like the following screenshot:
Fig. 1.15 XML data transformed into HTML using an XSLT transformation