[Lazarus] XPath expression with Namespaces

Simon Ameis SAmeis.fpc at web.de
Mon Nov 2 23:18:27 CET 2020


Hello all,

could somebody help me with using XML namespaces in an XPath expression?

I constantly get an EDOMNamespace exception with message
'TXPathScanner.ParseStep', even if I provide an TXPathNSResolver
instance. The exception only disappears if I use an own TXPathNSResolver
descendant class which resolves the namespace prefix 'D' to any URI.
However, then the resultset is still empty. The Wiki page about xpath
doesn't mention namespaces at all.

program Project1;
{$mode objfpc}{$H+}

uses
  SysUtils, Classes,
  Laz2_DOM, laz2_XMLRead, laz2_xpath;

// example document
const
  XML = '<?xml version="1.0" encoding="utf-8"?>'
+'<D:multistatus xmlns:D="DAV:">'
+'<D:response xmlns:lp2="http://apache.org/dav/props/"
xmlns:lp4="http://calendarserver.org/ns/"
xmlns:lp3="urn:ietf:params:xml:ns:caldav" xmlns:lp1="DAV:">'
+'<D:href>/</D:href>'
+'</D:response>'
+'</D:multistatus>';

var
  s: TStringStream = nil;
  doc: TXMLDocument = nil;
  ResponseList: TXPathVariable = nil;
  ResponseNode: TDOMElement;
  Resolver: TXPathNSResolver = nil;
begin
  try
    s := TStringStream.Create(XML);
    ReadXMLFile(doc, s);
    Resolver := TXPathNSResolver.Create(doc.DocumentElement);
    // this call raises EDOMNamespace exception with message
'TXPathScanner.ParseStep'
    ResponseList := EvaluateXPathExpression('//D:Response',
doc.DocumentElement, Resolver);
    for Pointer(ResponseNode) in ResponseList.AsNodeSet do
      WriteLn(ResponseNode.TextContent);
  finally
    FreeAndNil(ResponseList);
    FreeAndNil(Resolver);
    FreeAndNil(doc);
    FreeAndNil(s);
  end;
  WriteLn('End');
  readLn;
end.



More information about the lazarus mailing list