How to use XPath on TXMLDocument which has namespace prefixes?

前端 未结 5 2045
猫巷女王i
猫巷女王i 2021-01-03 07:35

I have an XML packet received from a third-party web server:




        
5条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-03 07:40

    When I tried this a couple of years ago, I found namespace lookup in XPath was different between xml providers.

    If I remember correctly, the Msxml lets you just use the namespace prefixes as they are defined in the xml file.

    The ADOM 4 provider requires that you resolve namespace prefixes used in your XPath query to the actual namespaces, independent of the namespace mapping used in the xml file. There is a method pointer for that purpose, OnOx4XPathLookupNamespaceURI. Then you can have a name lookup function like this:

    procedure TTestXmlUtil.EventLookupNamespaceURI(
      const AContextNode: IDomNode; const APrefix: WideString;
      var ANamespaceURI: WideString);
    begin
      if APrefix = 'soap' then
        ANamespaceURI := 'http://schemas.xmlsoap.org/soap/envelope/'
      else if APrefix = 'some' then
        ANamespaceURI := 'http://someurl'
    end;
    

    Using this lookup function, and the selectNode function (which looks like something I may have once posted in a Delphi forum, taken from https://github.com/Midiar/adomxmldom/blob/master/xmldocxpath.pas), I could do the following test (using your xml in a string constant):

    procedure TTestXmlUtil.SetUp;
    begin
      inherited;
      DefaultDOMVendor := sAdom4XmlVendor;
      docFull := LoadXmlData(csSoapXml);
    
      OnOx4XPathLookupNamespaceURI := EventLookupNamespaceURI;
    end;
    
    procedure TTestXmlUtil.Test_selectNode;
    var
      xn: IXmlNode;
    begin
      xn := selectNode(docFull.DocumentElement, '/soap:Envelope/soap:Body/some:SomeResponse/some:SomeResult');
      CheckNotNull(xn, 'selectNode returned nil');
    end;
    

    I had to modify you XPath query a little for the default namespace.

提交回复
热议问题