Monday, April 21, 2008

Enumerating XML nodes

I just submitted an update to OmniXmlUtils.pas - a helper library for the Delphi implementation of the XML DOM model, the OmniXML. It allows you to walk over child nodes with a simple enumerator (but you already saw that coming, huh?).

In OmniXML (and in MS XML on which the OmniXML interface is based), you access child nodes via IXMLNodeList interface. Actually, when you access any subset of nodes (for example, when you call SelectNodes and pass it an XPath expression), you are using IXMLNodeList. More and more I was using it, more I hated its stupid interface.

  IXMLCustomList = interface
function GetLength: Integer;
function GetItem(const Index: Integer): IXMLNode;
property Item[const Index: Integer]: IXMLNode read GetItem;
property Length: Integer read GetLength;

IXMLNodeList = interface(IXMLCustomList)
procedure Reset;
function NextNode: IXMLNode;
[I removed declarations of all functions that are not used when walking over the list.]

Basically, I have two options with the current design. I can use a standard for loop using Length and Item[] or I can use NextNode and while loop.

Or, of course, I can write an enumerator - and that's what I did. XMLEnumNodes takes an IXMLNodeList and wraps it in an enumerator. Even better - it takes an xml node or document and an XPath expression and runs SelectNodes automatically for me so I can write code like this:

for nodePassword in XMLEnumNodes(xmlConfig, '//*/PasswordHash') do
SetTextChild(nodePassword, '(removed)');

Now that's what I call a nice code!

If you can't wait for tomorrow update to the OmniXML daily snapshot, you can download OmniXMLUtils 1.25 here.

No comments:

Post a Comment