Copyright (c) 2000 by Charlie Calvert
This paper shows how to iterate through an XML document.
var
FDoc: TDOMDocument;
FRoot: TDomElement;
begin
FDoc := TDomDocument.Create;
// Create XML root
FRoot := Fdoc.createElement('RootElement');
FDoc.appendChild(FRoot);
end;
var
FChild11, FChild12, FChild13: TDomElement;
begin
FChild11 := Fdoc.createElement('Child_One');
FRoot.appendChild(FChild11);
FChild12 := Fdoc.createElement('Child_Two');
FRoot.appendChild(FChild12);
FChild13 := Fdoc.createElement('Child_Three');
FRoot.appendChild(FChild13);
var
FGrandChild_111: TDomElement;
begin
FGrandChild_111 := FDoc.createElement('GrandChild_111');
FChild11.appendChild(FGrandChild_111);
var
attr01, Attr02: TDomAttr;
textNode1, textNode2: TDomText;
begin
attr02 := Fdoc.createAttribute('Attr01');
FChild12.setAttributeNode(attr02);
textNode2 := Fdoc.createText('Text Two');
FChild12.appendChild(textNode2);
NewElement := FDoc.CreateElement('Foo');
TextNode := FDoc.CreateText(#13#10#32#32);
Game.AppendChild(TextNode);
NewElement.AppendChild(FDoc.CreateText('Foo Text'));
Game.AppendChild(NewElement);
TextNode := FDoc.CreateText(#13#10);
Game.AppendChild(TextNode);
type
TMyDomNodeFilter = class(TDomNodeFilter)
FNodeType: TDOMWhatToShow;
FReject: Boolean;
public
constructor Create(nodeType: TDomWhatToShow; reject: Boolean=false);
function acceptNode(const node: TdomNode): TdomFilterResult; override;
end;
implementation
// ... Code ommitted here
function TMyDomNodeFilter.acceptNode(const node: TdomNode): TdomFilterResult;
begin
if (Node.NodeType = TDomNodeType(0)) then
Result := FILTER_ACCEPT;
if node.NodeType in fNodeType then begin
Result := FILTER_Accept;
end else begin
if FReject then
Result := FILTER_REJECT
else
Result := FILTER_SKIP;
end;
end;
var ANode: TDomNode; Iter: TDomNodeIterator; WhatToShow: TDomWhatToShow; Filter: TMyDomNodeFilter; begin whatToShow := SHOW_ALL; Filter := TMyDomNodeFilter.Create(SHOW_ALL); iter := FDoc.createNodeIterator(FRoot, whatToShow, filter, true); Assert(iter.WhatToShow = SHOW_ALL); //ASSERT(iter.ExpandEntityReferences = True); ANode := iter.nextNode(); ASSERT (ANode = FRoot); ListBox1.Items.Add(ANode.Code); ANode := iter.nextNode(); ASSERT (ANode = FChild11); ListBox1.Items.Add(ANode.Code); ... // Code ommitted here ANode := iter.previousNode(); ASSERT(ANode = FGrandChild_131); ListBox1.Items.Add(ANode.Code); end;
Listing 1: Code for creating and traversing an XML document.
unit Main;
interface
{$ASSERTIONS ON}
uses
Windows, Messages, SysUtils,
Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls,
OleServer, XDOM, ExtCtrls;
type
TForm1 = class(TForm)
DomImplementation1: TDomImplementation;
XmlToDomParser1: TXmlToDomParser;
ListBox1: TListBox;
Panel1: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
FDoc: TDOMDocument;
FRoot: TDomElement;
FChild11, FChild12, FChild13: TDomElement;
FGrandChild_111, FGrandChild_112: TDomElement;
FGrandChild_121, FGrandChild_122: TDomElement;
FGrandChild_131: TDOMElement;
attr01, Attr02: TDomAttr;
textNode1, textNode2: TDomText;
Comment: TDomComment;
cDataSec: TDOMCDataSection;
docPi: TDOMProcessingInstruction;
procedure Traverse;
procedure CreateDocument;
public
{ Public declarations }
end;
TMyDomNodeFilter = class(TDomNodeFilter)
FNodeType: TDOMWhatToShow;
FReject: Boolean;
public
constructor Create(nodeType: TDomWhatToShow; reject: Boolean=false);
function acceptNode(const node: TdomNode): TdomFilterResult; override;
end;
var
Form1: TForm1;
implementation
uses
CodeBox, ComObj;
{$R *.DFM}
procedure TForm1.CreateDocument;
var
Stream: TFileStream;
S: string;
begin
FDoc := TDomDocument.Create;
// Create XML root
FRoot := Fdoc.createElement('RootElement');
FDoc.appendChild(FRoot);
// Create Top Tier Children
FChild11 := Fdoc.createElement('Child_One');
FRoot.appendChild(FChild11);
FChild12 := Fdoc.createElement('Child_Two');
FRoot.appendChild(FChild12);
FChild13 := Fdoc.createElement('Child_Three');
FRoot.appendChild(FChild13);
// Attach some text
textNode1 := Fdoc.createText('Text One');
FChild11.appendChild(textNode1);
textNode2 := Fdoc.createText('Text Two');
FChild12.appendChild(textNode2);
//Create GrandChildren
FGrandChild_111 := FDoc.CreateElement('GrandChild_111');
FChild11.appendChild(FGrandChild_111);
attr01 := Fdoc.CreateAttribute('Attr01');
FChild11.setAttributeNode(attr01);
FGrandChild_112 := Fdoc.createElement('GrandChild_112');
FChild11.appendChild(FGrandChild_112);
FGrandChild_121 := Fdoc.createElement('GrandChild_121');
FChild12.appendChild(FGrandChild_121);
attr02 := Fdoc.createAttribute('Attr01');
FChild12.setAttributeNode(attr02);
FGrandChild_122 := Fdoc.createElement('GrandChild_122');
FChild12.appendChild(FGrandChild_122);
FGrandChild_131 := FDoc.createElement('GrandChild_131');
FChild13.appendChild(FGrandChild_131);
Comment := FDoc.createComment('DocComment');
FRoot.appendChild(Comment);
cdataSec := Fdoc.createCDATASection('DocCDataSection');
FChild11.appendChild(cdataSec);
docPI := Fdoc.createProcessingInstruction('DocPI', 'DocTarget');
FChild13.appendChild(docPI);
S := FDoc.Code;
Stream := TFileStream.Create(GetStartDir + 'sammy.xml', fmCreate or fmOpenWrite);
Stream.Write(PChar(S)^, Length(S));
Stream.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
CreateDocument;
Traverse;
end;
procedure TForm1.Traverse;
var
ANode: TDomNode;
Iter: TDomNodeIterator;
WhatToShow: TDomWhatToShow;
Filter: TMyDomNodeFilter;
begin
whatToShow := SHOW_ALL;
Filter := TMyDomNodeFilter.Create(SHOW_ALL);
iter := FDoc.createNodeIterator(FRoot, whatToShow, filter, true);
Assert(iter.WhatToShow = SHOW_ALL);
//ASSERT(iter.ExpandEntityReferences = True);
ANode := iter.nextNode();
ASSERT (ANode = FRoot);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT (ANode = FChild11);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = textNode1);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = FGrandChild_111);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = FGrandChild_112);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = cdataSec);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = FChild12);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = textNode2);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = FGrandChild_121);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = FGrandChild_122);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = FChild13);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = FGrandChild_131);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = docPI);
ListBox1.Items.Add(ANode.Code);
ANode := iter.nextNode();
ASSERT(ANode = comment);
ListBox1.Items.Add(ANode.Code);
ANode := iter.previousNode();
ASSERT(ANode = comment);
ListBox1.Items.Add(ANode.Code);
ANode := iter.previousNode();
ASSERT(ANode = docPI);
ListBox1.Items.Add(ANode.Code);
ANode := iter.previousNode();
ASSERT(ANode = FGrandChild_131);
ListBox1.Items.Add(ANode.Code);
end;
{ TMyDomNodeFilter }
constructor TMyDomNodeFilter.Create(nodeType: TDomWhatToShow;
reject: Boolean);
begin
FReject := reject;
FNodeType := NodeType;
end;
function TMyDomNodeFilter.acceptNode(const node: TdomNode): TdomFilterResult;
begin
if (Node.NodeType = TDomNodeType(0)) then
Result := FILTER_ACCEPT;
if node.NodeType in fNodeType then begin
Result := FILTER_ACCEPT;
end else begin
if FReject then
Result := FILTER_REJECT
else
Result := FILTER_SKIP;
end;
end;
end.