Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to use XPath with IXMLDOMDocument2 and XMLWriter to control indent

880 views
Skip to first unread message

pa...@bookwith.com

unread,
Dec 6, 2005, 4:50:25 PM12/6/05
to
For once and for all I decided to get XML processing sorted out with
Delphi. OpenXML to be is seriously over engineered and way too hard to
use so I decided to go back to MSXML parsers.

This post is intended for those who wish to find out how to use MSXML
parsers effectively with Delphi. The information presented is based on
experiences with Delphi 6 so I don't know what has been done around the
XML component in later versions.

Note:

The XML component included is Delphi 6 is seriously outdated. Don't use
it! On the Internet tab you can find the XML component called
TXMLDocument this component is based on the old and outdated MSXML
parser version 3. MSXML parsers of later date are more capable.

Step 1
First make sure you have installed a more recent version of MSXML Try
http://www.microsoft.com/downloads/details.aspx?FamilyID=3144b72b-b4f2-46da-b4b6-c5d7485f2b42&DisplayLang=en
or search Google for MSXML Parser


Step 2
Open Delphi and Import the type library of MSXML4.dll or later. You can
allow it to create the VCL components but you will be inundated with a
large number of components on your palette. I choose to just create the
unit.

Step 3
Put the MSXML2_TLB.pas unit in the uses clause where you want to use
the XML parser.

Now you are ready to use it.

Declare a variable for the interface like:

FDoc: IXMLDOMDocument2;

and create the interface object like:

FDoc := CoDOMDocument.Create;
FDoc.async := false;
FDoc.setProperty('SelectionNamespaces',
'xmlns:tm="http://www.topicmaps.org/xtm/1.0/"');
FDoc.setProperty('SelectionLanguage', 'XPath');

There is no need to free it later since it is an interface.

Now you are ready to call the methods from IXMLDOMDocument2

for example:

FDoc.preserveWhiteSpace := False;
FDoc.load('MyXML.xml');

Now you can access data in FDoc using XPath methods like:

FDoc.selectSingleNode(XPathExpression);
FDoc.selectNodes(XPathExpression);

The results of these functions are respectively IXMLDOMNode and
IXMLDOMNodeList.
The XPath expression is an XML query language. You can find out more
about XPath expressions here:
http://www.w3schools.com/xpath/xpath_syntax.asp. For instance to change
the value of an element using XPath you simply call:

FDoc.selectSingleNode(XPathExpression).text := 'MyNewValue';

You can read or modify the value of IXMLDOMNode nodes by setting their
Text property like:

lNode.text := 'MyValue';
lNodes.item[i].text := 'MyValue';

It is also easy to create new elements in your document. To create a
root element call:

FDoc.appendChild(FDoc.CreateElement('MyfirstTag')).text := 'MyValue';

A document only allows one root element. you can check to see if there
is one root element by looking to see if FDoc.documentElement is
assigned (not nil)

You can create a child element like this:

FDoc.documentElement.appendChild(FDoc.CreateElement('MychildTag')).text
:= 'CoolValue';

Now you have created or changed XML content and it is time to save it.
IXMLDOMDocument2 provides a save method that you can use to save the
XML to a text file. However, you may be disappointed when you look at
the data because the whole thing is written to a single line without
indents.

It is not the job of the document object to apply formatting. Instead
this can be done using the IMXWriter interface objects. MSDN provides
an example here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/a3d4644b-7198-4a17-a300-c54bb395cfa4.asp
on how to use IMXWriter. I translated this into pascal with an example
below:

uses MSXML2_TLB;

procedure SaveXMLToFile(FileName: TFileName);
var
lStringList: TStringList;
Writer: IMXWriter;
Reader: IVBSAXXMLReader;
begin
Writer := CoMXXMLWriter.Create;
Reader := CoSAXXMLReader.Create;

Writer.byteOrderMark := True;
Writer.omitXMLDeclaration := False;
Writer.indent := True;

Reader.contentHandler := Writer as IVBSAXContentHandler;
Reader.dtdHandler := Writer as IVBSAXDTDHandler;
Reader.errorHandler := Writer as IVBSAXErrorHandler;
Reader.putProperty('http://xml.org/sax/properties/lexical-handler',
Writer);
Reader.putProperty('http://xml.org/sax/properties/declaration-handler',
Writer);

Reader.parse(FDoc);

lStringList := TStringlist.Create;
lStringList.Text := Writer.output;
lStringList.SaveToFile(FileName);
end;

Have a play with the writer properties. It can do lot's of stuff. Omit
XMLDeclaration is a good one as it includes or excludes the XML header
that is required at the top of your XML file like:

<?xml version="1.0" encoding="UTF-16" standalone="no"?>

Indenting is only done if you turn Indent on like:

Writer.indent := True;

The thus produced file will contain tab based indents.

Well that's it so far from me. I just thought I'd post this info for
someone else to find since I had a hard time finding this stuff myself.
Google is your friend.

Cheers

Paul van Dinther

bruce

unread,
Aug 14, 2008, 6:03:14 AM8/14/08
to

If you use your SaveToFile with
Writer.omitXMLDeclaration := False;
Then
Node := FDoc.selectSingleNode(XPath);
does not find the node


Provided by TopXML
http://www.topxml.com

0 new messages