XmlDocument Component
The XmlDocument component (TCnXmlDocument) is a .Net component in Delphi which represents an XML document. You can use this component to load,
validate, edit, add, and position XML in a document.
The TCnXmlDocument compoonent is an in-memory representation of an XML document. It implements the W3C XML Document Object Model (DOM) Level 1 Core and
the Core DOM Level 2. DOM stands for document object model.
You can load XML into the DOM by using this component, and then programmatically read, modify, and remove XML in the document.
Tasks:
- Load XML into the document object model
- Navigate the document tree
- Find nodes
- Edit nodes
- Add nodes
- Remove nodes
- Position nodes
Load XML into the document object model
Start with an XML document like this one. it's just a few books in a collection. But it does contain the basic things that you'd find in any XML document;
a namespace, elements that represent data and attributes that describe the data.
XML Data saved as booksData.xml
<?xml version="1.0" encoding="utf-8"?>
<books xmlns="http://www.contoso.com/books">
<book genre="novel" ISBN="1-861001-57-8" publicationdate="1823-01-28">
<title>Pride And Prejudice</title>
<price>24.95</price>
</book>
<book genre="novel" ISBN="1-861002-30-1" publicationdate="1985-01-01">
<title>The Handmaid's Tale</title>
<price>29.95</price>
</book>
<book genre="novel" ISBN="1-861001-45-3" publicationdate="1811-01-01">
<title>Sense and Sensibility</title>
<price>19.95</price>
</book>
</books>
</pre>
Next, load this data into the DOM so that you can work with it in memory. The most popular way to do this is refer to a file on your local computer or on a network.
This example loads XML from a file.
var
doc: TCnXmlDocument;
begin
doc := TCnXmlDocument.Create(nil);
try
try
doc.PreserveWhitespace := True;
doc.Load('booksData.xml');
except
on E: Exception do
Writeln('The following exception was raised : ', E.Message);
end;
finally
doc.Free;
end;
end.
Navigate the document tree
You can use properties to navigate around an XML document. But before you use any of them, let's quickly review a few terms.
Your document is composed of nodes. Each node has as single parent node directly above it. The only node that does not have
a parent node is the document root, as it is the top-level node. Most nodes can have child nodes, which are nodes directly
below them. Nodes that are at the same level are siblings.
The following examples, show you how to obtain the root node, jump to the first child node of the root node, access any of its child nodes,
get back out to the parent node, and then navigate across sibling nodes.
Start with the root node
This example gets the root node and then uses that node to output the contents of the document to the console.
program Sample;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
CNClrlib.Component.XmlDocument;
var
doc: TCnXmlDocument;
begin
doc := TCnXmlDocument.Create(nil);
try
try
doc.PreserveWhitespace := True;
doc.LoadXml('<?xml version=''1.0'' ?>' +
'<book genre=''novel'' ISBN=''1-861001-57-5''>' +
'<title>Pride And Prejudice</title>' +
'</book>');
//Display the document element.
Writeln(doc.DocumentElement.OuterXml);
except
on E: Exception do
Writeln('The following exception was raised : ', E.Message);
end;
finally
doc.Free;
end;
end.
Get child nodes
This example jumps to the first child node of the root node and then iterates through the child nodes of that node if any exist.
program Sample;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
CNClrlib.Component.XmlDocument;
var
doc: TCnXmlDocument;
root: _XmlNode;
i: Integer;
begin
doc := TCnXmlDocument.Create(nil);
try
try
doc.PreserveWhitespace := True;
doc.LoadXml('<book ISBN=''1-861001-57-5''>' +
'<title>Pride And Prejudice</title>' +
'<price>19.95</price>' +
'</book>');
root := doc.FirstChild;
//Display the contents of the child nodes.
if root.HasChildNodes then
begin
for i := 0 to root.ChildNodes.Count - 1 do
begin
Writeln(root.ChildNodes[i].InnerText);
end;
end;
except
on E: Exception do
Writeln('The following exception was raised : ', E.Message);
end;
finally
doc.Free;
end;
end.
Refer to the last child node
This example writes the price of a book to the console (which is the last child node of a book node).
program Sample;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
CNClrlib.Component.XmlDocument;
var
doc: TCnXmlDocument;
root: _XmlNode;
begin
doc := TCnXmlDocument.Create(nil);
try
try
doc.PreserveWhitespace := True;
doc.LoadXml('<book ISBN=''1-861001-57-5''>' +
'<title>Pride And Prejudice</title>' +
'<price>19.95</price>' +
'</book>');
root := doc.FirstChild;
Writeln('Display the price element...');
Writeln(root.LastChild.OuterXml);
except
on E: Exception do
Writeln('The following exception was raised : ', E.Message);
end;
finally
doc.Free;
end;
end.
Navigate forward across siblings
This example moves forward from book to book. Book nodes are siblings to one another.
program Sample;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
CNClrlib.Component.XmlDocument;
var
doc: TCnXmlDocument;
currNode: _XmlNode;
nextNode: _XmlNode;
begin
doc := TCnXmlDocument.Create(nil);
try
try
doc.PreserveWhitespace := True;
doc.Load('books.xml');
currNode := doc.DocumentElement.FirstChild;
writeln('First book...');
writeln(currNode.OuterXml);
nextNode := currNode.NextSibling;
writeln(#13#10+'Second book...');
writeln(nextNode.OuterXml);
except
on E: Exception do
Writeln('The following exception was raised : ', E.Message);
end;
finally
doc.Free;
end;
end.
Navigate backwards across siblings
This example moves backwards from book to book.
program Sample;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
CNClrlib.Component.XmlDocument;
var
doc: TCnXmlDocument;
lastNode: _XmlNode;
prevNode: _XmlNode;
begin
doc := TCnXmlDocument.Create(nil);
try
try
doc.PreserveWhitespace := True;
doc.Load('books.xml');
lastNode := doc.DocumentElement.LastChild;
writeln('Last book...');
writeln(lastNode.OuterXml);
prevNode := lastNode.PreviousSibling;
writeln(#13#10+'nPrevious book...');
writeln(prevNode.OuterXml);
except
on E: Exception do
Writeln('The following exception was raised : ', E.Message);
end;
finally
doc.Free;
end;
end.
Find nodes
The most popular way to find one or more nodes of data is to use an XPath query string, but there are also methods that don't require one.
Get a single node
This example locates a book by using the ISBN number.
function GetBook(uniqueAttribute: string; doc: TCnXmlDocument): _XmlNode;
var
nsmgr: _XmlNamespaceManager;
xPathString: String;
begin
nsmgr := TXmlNamespaceManagerActivator.CreateInstance(doc.NameTable);
nsmgr.AddNamespace('bk', 'http://www.contoso.com/books');
xPathString := '//bk:books/bk:book[@ISBN=''' + uniqueAttribute + ''']';
Result := doc.DocumentElement.SelectSingleNode_1(xPathString, nsmgr);
end;
The string used in this example is an Xpath query.
You can also use the GetElementById to retrieve nodes. To use this approach, you'll have to define ID's in the document type definition declarations of your XML file.
After you get a node, you get the value of attributes or child nodes. This example does that with a book node.
procedure GetBookInformation(var title, ISBN, publicationDate, price, genre: string; book: _XmlNode);
var
bookElement: _XmlElement;
attr: _XmlAttribute;
begin
bookElement := TXmlElementActivator.Wrap(book);
// Get the attributes of a book.
attr := bookElement.GetAttributeNode('ISBN');
ISBN := attr.InnerXml;
attr := bookElement.GetAttributeNode('genre');
genre := attr.InnerXml;
attr := bookElement.GetAttributeNode('publicationdate');
publicationDate := attr.InnerXml;
// Get the values of child elements of a book.
title := bookElement['title'].InnerText;
price := bookElement['price'].InnerText;
end;