WebDAV-Rückgabe mit XML-Namespaces per XPath auswerten

Alle Fragen zur Netzwerkkommunikation
Antworten
Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

WebDAV-Rückgabe mit XML-Namespaces per XPath auswerten

Beitrag von Socke »

Hallo zusammen,
inspiriert durch den Thread Via ssh Dateien auf / von Server kopieren / verschieben habe ich versucht, mit meiner Synology-NAS per WebDAV zu kommunizieren.
Dabei scheitere ich an der Auswertung der PROPFIND-Antwort (Auflistung eines Verzeichnisinhalts). Dieses ist ein XML-Dokument mit Namespaces.

Aus der Funktion EvaluateXPathExpression erhalte ich die nichtssagende Exception EDOMNamespace mit der Nachricht 'TXPathScanner.ParseStep'. Soweit ich das im Quelltext nachvollziehen kann, kommt der Fehler beim Parsen des XPath-Ausdrucks - nur warum?!

Code: Alles auswählen

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

uses
  SysUtils, Classes, Laz2_DOM, laz2_XMLRead, laz2_xpath;

// Antwort auf PROPFIND https://server:port/
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:propstat>'
+'<D:prop>'
+'<lp1:resourcetype><D:collection/></lp1:resourcetype>'
+'<lp1:creationdate>2016-09-15T20:02:52Z</lp1:creationdate>'
+'<lp1:getlastmodified>Tue, 15 Sep 2020 17:09:05 GMT</lp1:getlastmodified>'
+'<lp1:getetag>"5af5d35591c48"</lp1:getetag>'
+'<D:supportedlock>'
+'<D:lockentry>'
+'<D:lockscope><D:exclusive/></D:lockscope>'
+'<D:locktype><D:write/></D:locktype>'
+'</D:lockentry>'
+'<D:lockentry>'
+'<D:lockscope><D:shared/></D:lockscope>'
+'<D:locktype><D:write/></D:locktype>'
+'</D:lockentry>'
+'</D:supportedlock>'
+'<D:lockdiscovery/>'
+'<D:getcontenttype>httpd/unix-directory</D:getcontenttype>'
+'</D:prop>'
+'<D:status>HTTP/1.1 200 OK</D:status>'
+'</D:propstat>'
+'</D:response>' // hier folgen die weiteren "Geteilten Verzeichnisse"
+'</D:multistatus>';


var
  s: TStringStream = nil;
  doc: TXMLDocument = nil;
  ResponseList: TXPathVariable = nil;
  ResponseNode: TDOMElement;
  Resolver: TXPathNSResolver;
begin
  try
    s := TStringStream.Create(XML);
    ReadXMLFile(doc, s);
    Resolver := TXPathNSResolver.Create(doc.DocumentElement);
    // hier kommt die Exception EDOMNamespace mit der Nachricht 'TXPathScanner.ParseStep'
    ResponseList := EvaluateXPathExpression('//D:Response', doc.DocumentElement, Resolver);
    for Pointer(ResponseNode) in ResponseList.AsNodeSet do
    begin
      // hier kommt vermutlich noch kein sinnvoller Inhalt raus
      WriteLn(ResponseNode.TextContent);
    end;
  finally
    FreeAndNil(ResponseList);
    FreeAndNil(Resolver);
    FreeAndNil(doc);
    FreeAndNil(s);
  end;
  WriteLn('Ende');
  readLn;
end.
Hier nochmal den XML-Text zum kopieren; Den Ausdruck //D:Response

Code: Alles auswählen

<?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:propstat>
<D:prop>
<lp1:resourcetype><D:collection/></lp1:resourcetype>
<lp1:creationdate>2016-09-15T20:02:52Z</lp1:creationdate>
<lp1:getlastmodified>Tue, 15 Sep 2020 17:09:05 GMT</lp1:getlastmodified>
<lp1:getetag>"5af5d35591c48"</lp1:getetag>
<D:supportedlock>
<D:lockentry>
<D:lockscope><D:exclusive/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
<D:lockentry>
<D:lockscope><D:shared/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
</D:supportedlock>
<D:lockdiscovery/>
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: WebDAV-Rückgabe mit XML-Namespaces per XPath auswerten

Beitrag von Socke »

Ich bin einen Schritt weiter. Die Ursache scheint irgendwo im Namespace-Resolver begraben zu sein.
Ein eigener Resolver, der alle im XPath-Ausdruck verwendeten Namensräume auflöst, führt zumindest zu keiner Exception mehr - aber zu einer leeren Ergebnismenge.

Code: Alles auswählen

type
  TMyResovler = class(TXPathNSResolver)
  public
    function LookupNamespaceURI(const aPrefix: DOMString): DOMString; override;
  end;

{ TMyResovler }

function TMyResovler.LookupNamespaceURI(const aPrefix: DOMString): DOMString;
begin
  case aPrefix of
    'D': Result := 'DAV:';
  else
    Result := '';
  end;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten