Bascy
Bascy

Reputation: 2089

How to use XMLs SelectNodes() using namespaces in OmniXML

I have an XML document which contains elements with namespaces. I want to select nodes from that XML based on a certain namespace and a certain element. When using the MSXML Vendor you can accomplish that with the SetProperty('SelectionNameSpaces', 'nn:mmmm') statement. But because our current project will be multiplatform I cannot use the MSXML vendor. I'm trying the OmniXML vender but I cannot find how to use namespaces in a SelectNodes() statement.

In the code below I tried using DeclareNameSpace() but that does not work. The SelectNodes statement does not find any nodes and the List stays empty.

How can I solve this?

program Project1;
{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  XML.XMLDom,
  XML.XMLDoc,
  XML.omnixmldom,
  XML.XMLIntf
  ;

const
  cXML = '<?xml version="1.0"?>' +
         '<catalog xmlns:xs12=''http://www.w3.org/2001/XMLSchema-instance''>' +
         '   <xs12:book id="bk101">' +
         '     <xs12:author>Gambardella, Matthew</xs12:author>' +
         '      <xs12:title>XML Developers Guide</xs12:title>' +
         '    <xs12:genre>Computer</xs12:genre>' +
         '    <xs12:price>44.95</xs12:price>' +
         '    <xs12:publish_date>2000-10-01</xs12:publish_date>' +
         '    <xs12:description>An in-depth look at creating applications with  XML.</xs12:description>' +
         '</xs12:book>'
          + '</catalog>'
         ;
var
  lDoc: IXMLDocument;
  lList: IDOMNodeList;
  lSelectNode: IdomNodeSelect;
begin

  DefaultDOMVendor := sOmniXmlVendor;
  try
    try
      lDoc := LoadXMLData(cXML);

      lDoc.DocumentElement.DeclareNamespace('a', 'http://www.w3.org/2001/XMLSchema-instance');

      if supports(lDoc.DOMDocument, IDomNodeSelect, lSelectNode) then
      begin
        lList := lSelectNode.selectNodes('a:book');
        Writeln(Format( '%d nodes', [lList.length]));
      end;

    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;
  finally
  end;
end.

Upvotes: 2

Views: 949

Answers (1)

Bascy
Bascy

Reputation: 2089

Seems that OmniXML does not support that. All posts I found on the subject never provide an answer to this question.

I did manage to solve the problem by using another XML implementation: OXML This implementation has a SelectNodesNS() function which precisely does what I was looking for. Its available via subversion. more info here: http://www.kluug.net/oxml.php

Sample project using OXML:

program Project1;
{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  OXMLPDOM
  ;

const
  cXML = '<?xml version="1.0"?>' +
         '<catalog xmlns:xs12=''http://www.w3.org/2001/XMLSchema-instance''>' +
         '   <xs12:book id="bk101">' +
         '     <xs12:author>Gambardella, Matthew</xs12:author>' +
         '      <xs12:title>XML Developers Guide</xs12:title>' +
         '    <xs12:genre>Computer</xs12:genre>' +
         '    <xs12:price>44.95</xs12:price>' +
         '    <xs12:publish_date>2000-10-01</xs12:publish_date>' +
         '    <xs12:description>An in-depth look at creating applications with  XML.</xs12:description>' +
         '</xs12:book>'
          + '</catalog>'
         ;
var
  doc: IXMLDocument;
  list: IXMLNodeList;
begin

  try
    try
      doc := CreateXMLDoc;
      Doc.LoadFromXML(cXML);

      doc.DocumentElement.SelectNodesNS('http://www.w3.org/2001/XMLSchema-instance', 'book', list);
      Writeln(Format( '%d nodes', [List.count]));

    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;
  finally
  end;
end.

Upvotes: 1

Related Questions