Nodes in XML does not appear to be identified/utilizable

前提是你 提交于 2021-02-11 15:01:20

问题


I am probably making some kind of stupid mistake here, but I'm stuck, so hopefully some of you can help me out.

I Have loaded an XML to xmlDoc through post, using DOMDocument and XMLHTTP

Set xmlhtp = CreateObject("MSXML2.XMLHTTP.6.0")
Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")

When I recieve the response from the API I write it to a cell to check the response, and it loads there. I find my Nodes and my information. I write it to a cell with

With xmlhtp
.Open "post", sURL, False
.setRequestHeader "Host", "Host-name"
.setRequestHeader "Content-Type", "text/xml;charset=UTF-8"
.setRequestHeader "soapAction", "action-ID"
.send sEnv
xmlDoc.LoadXML .responseText
Worksheets("Ark1").Range("A11").Value = .responseText
MsgBox (xmlDoc.SelectSingleNode("//ExternalReference"))

In my dump to A11 I find the node ExternalReference, and it has info in it, see screenshot

But even though everything seems fine, the MsgBox does not find the Node. I get the "Object Variable or With block variable not set"-error message.

I tried to add all xmlns-URLs from the response I get in SoapUI, but that did not help with anything.

I have also tried to loop through the parent node of this node (case) with a sequence I know works in another code I have (after some help yesterday here (not the same script or XML this time though):

How to loop through XML-nodes and validate if values exists?)

The loop I tried to run, it does not produce any content either (seems like it cannot find the nodes in the XML)

Const MAX_AR As Long = 3
Dim Casep, Casec, c As Range, i As Long 
Set c = Worksheets("Ark1").Range("J1")
Set Casep = xmlDoc.getElementsByTagName("Case") 
For Each Casec In Casep                                   
    c.Offset(0, i) = Casec.getElementsByTagName("AccountName")(0).Text 
    c.Offset(1, i) = Casec.getElementsByTagName("ContractName")(0).Text
    c.Offset(2, i) = Casec.getElementsByTagName("ExternalReference")(0).Text
    i = i + 1
    If i >= MAX_AR Then Exit For 'Hopp ut ved oppnådd Max År
Next Casec

It it helps, here is a scrubbed part of the XML:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Header>
      <h:ResponseHeader xmlns:h="URL to schema" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
         <QueueId i:nil="true" xmlns="URL to schema"/>
         <SessionId xmlns="URL to schema">123456789</SessionId>
      </h:ResponseHeader>
   </s:Header>
   <s:Body>
      <CaseGetResponse xmlns="URL to schema">
         <Case xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <AccountName>123456</AccountName>
            <ContractName>123456</ContractName>
            <ExternalReference>extref</ExternalReference>
            <ExternalReference2 i:nil="true"/>
            <ExternalReferences/>
            <ExternalSystemReference i:nil="true"/>
            <Sequence>654321</Sequence>

回答1:


Adding namespaces fixes the xpath query (but I'm not sure the getElementsByTagName cares about them)

    Dim xmlDoc As New MSXML2.DOMDocument
    Dim cases, cs
    
    'need these next two....
    xmlDoc.setProperty "SelectionLanguage", "XPath"
    xmlDoc.setProperty "SelectionNamespaces", _
                          "xmlns:s='http://schemas.xmlsoap.org/soap/envelope/' " & _
                          "xmlns:i='http://www.w3.org/2001/XMLSchema-instance' " & _
                          "xmlns:xx='http://URL/to/schema' "
    
    xmlDoc.LoadXML Range("A1").Value 'loading from a worksheet...
    
    'this works with the dummy namespace reference
    Debug.Print xmlDoc.DocumentElement.SelectNodes("//xx:ExternalReference")(0).Text '>>extref
    
    'also works
    Set cases = xmlDoc.getElementsByTagName("Case")
    For Each cs In cases
        Debug.Print cs.getElementsByTagName("AccountName")(0).Text
        Debug.Print cs.getElementsByTagName("ContractName")(0).Text
        Debug.Print cs.getElementsByTagName("ExternalReference")(0).Text
    Next cs

As for why the inherited namespace prefix on <ExternalReference> is xx and not i, see the accepted response here: XML: do child nodes inherit parent's namespace prefix?. Basically prefixed namespaces are not inherited but un-prefixed ones ("default namespaces", declared using xmlns="...") are: in this case <ExternalReference> gets its namespace from <CaseGetResponse> not <Case>

FYI I was using this XML (note I adjusted your dummy namespace URL):

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Header>
      <h:ResponseHeader xmlns:h="URL to schema" 
                        xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
         <QueueId i:nil="true" xmlns="URL to schema"/>
         <SessionId xmlns="URL to schema">123456789</SessionId>
      </h:ResponseHeader>
   </s:Header>
   <s:Body>
      <CaseGetResponse xmlns="http://URL/to/schema">
         <Case xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <AccountName>123456</AccountName>
            <ContractName>123456</ContractName>
            <ExternalReference>extref</ExternalReference>
            <ExternalReference2 i:nil="true"/>
            <ExternalReferences/>
            <ExternalSystemReference i:nil="true"/>
            <Sequence>654321</Sequence>
        </Case>
      </CaseGetResponse>
   </s:Body>
</s:Envelope>


来源:https://stackoverflow.com/questions/64901392/nodes-in-xml-does-not-appear-to-be-identified-utilizable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!