VBA中的LoadXML没有将字符串解析为可用的DOMDocument60

问题描述 投票:3回答:1

很长时间的读者,但首先发布在这里。任何和所有帮助非常感谢!

我正在研究数据抓取器以从网格运算符获取客户的市场结果,并且需要一系列xml查询来执行此操作。我能够使用SOAP模式(网格运算符所需)连接,验证和接收对我的查询的响应。但是,当我尝试使用LoadXML函数将我从服务器接收的xml字符串加载到DOMDocument60对象时,它会从响应中删除所有节点,并生成一个xml文档,其中只有一个节点中的标题和一个连接存储在第二个节点中字符串的所有节点中的所有值。

因此,我无法提取我需要的值。它们有不同的长度,我无法知道一个值何时结束而下一个值开始。此外,由于节点名称已被剥离,当我尝试获取名为“DSRSRREGAwardHourly”的所有节点的节点列表时,我得到一个空列表。

查询后从服务器收到的XML(我只留下一个每小时节点来简化)

<?xml version='1.0' encoding='UTF-8'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <QueryResponse xmlns="http://emkt.pjm.com/emkt/xml">
      <DSRSRREGAwardSet>
        <DSRSRREGAward day="2018-12-01" location="1960147390">
          <DSRSRREGAwardHourly hour="1">
            <SynchOfferMW>0.5</SynchOfferMW>
            <RegOfferMW>0</RegOfferMW>
            <SelfScheduledMW>0</SelfScheduledMW>
            <SynchAwardedMW>0</SynchAwardedMW>
            <RegAwardedMW>0</RegAwardedMW>
            <RegOfferPriceUsed>0</RegOfferPriceUsed>
            <RegdOfferMW>0</RegdOfferMW>
            <RegdMW>0</RegdMW>
          </DSRSRREGAwardHourly>
        </DSRSRREGAward>
      </DSRSRREGAwardSet>
    </QueryResponse>
  </Body>
</Envelope>

我正在使用的相关VBA代码

'Variable definition
Dim oWinhttp As WinHttpRequest
Dim ReturnXML As MSXML2.DOMDocument60
Dim ItemList As IXMLDOMNodeList
Dim XMLItem As IXMLDOMNode

'Variable initialization
Set oWinhttp = New WinHttpRequest
Set ReturnXML = New MSXML2.DOMDocument60

'Run the query against the server
With oWinhttp
  Call .Open("POST", WebURL)
  Call .SetRequestHeader("Cookie", "pjmauth=" & tokenStr)
  Call .SetRequestHeader("Content-Type", "text/xml")
  Call .SetRequestHeader("Content-Length", Len(xmlSubmittal))
  Call .Send(xmlSubmittal)
  Call .WaitForResponse

  'Store the return XML into DOM Document
  ReturnXML.async = False
  ReturnXML.validateOnParse = False
  ReturnXML.LoadXML (.ResponseText)

  'Terminate connection
  Call oWinhttp.abort
End With

'Extract nodes we are going to need
Set ItemList = ReturnXML.SelectNodes("//DSRSRREGAwardHourly")
excel xml vba xml-parsing
1个回答
0
投票

使用名称空间进行简单的XML解析

请尝试以下代码行

  • [1]通过设置名称空间定义 ReturnXML.setProperty“SelectionNamespaces”,xmlNameSpaces

其中xmlNameSpaces只是一个字符串变量,复制xmlns节点中的先前命名空间(<QueryResponse>)属性。

  • [2]通过节点结构执行非常基本的循环。显然,每个节点中只有子节点具有文​​本条目,此代码示例不检查空节点(考虑使用更详细的XPath解析和/或使用特殊 - 平台独立 - 查询语言XSLT)。

相关的代码段

' ...
'[1] Store the return XML into DOM Document using name spaces defining a leading "d:" prefix
ReturnXML.async = False
ReturnXML.validateOnParse = False

Dim xmlNameSpaces$
xmlNameSpaces = "xmlns:d=""http://emkt.pjm.com/emkt/xml"""      ' define namespaces
ReturnXML.setProperty "SelectionNamespaces", xmlNameSpaces      ' set namespace prop

ReturnXML.LoadXML (.ResponseText)                   ' get content

'[2] Loop through node lists (attention to the chosen namespace prefix)
Dim ItemList As MSXML2.IXMLDOMNodeList, ItemList2 As MSXML2.IXMLDOMNodeList
Dim item As MSXML2.IXMLDOMNode, item2 As MSXML2.IXMLDOMNode
Set ItemList = ReturnXML.SelectNodes("//d:DSRSRREGAwardHourly") ' <~~ leading "d:" :-)

For Each item In ItemList
     Debug.Print "Day:  " & item.SelectSingleNode("../@day").Text, _
                 "Hour: " & item.SelectSingleNode("./@hour").Text
     Set ItemList2 = item.SelectNodes("d:*")
     For Each item2 In ItemList2
        Debug.Print vbTab & item2.nodeName, item2.Text
     Next item2
Next item

相关链接

C.F. Obtain attribute names from XML using VBA

附录由于评论

“我现在好奇,问题是该字符串定义了2个不同的命名空间,因此忽略了第二个?”

基本上是的;层次结构中的后一个声明在xml数据示例中超过前一个声明(除了显式前缀的元素名称)。

  • a)具体示例中的整个XML结构仅显示“normal”=未加前缀的元素名称,例如<SynchOfferMW>(而不是可能的<extra:SynchOfferMW>,它将基于先前名称空间声明xmlns:extra="http://..."中的附加显式前缀赋值)。使用无前缀的命名空间,您将声明两个默认命名空间,一个用于<Envelope>元素,第二个用于<QueryResponse>元素。
  • b)由于w3.org definition of namespaces/6.2 “►默认命名空间声明的范围从它出现的start-tag的开头延伸到相应的end-tag的末尾,不包括任何内部默认命名空间声明的范围。默认的名称空间声明适用于其范围内所有未加前缀的元素名称。“所以<QueryResponse>元素及其所有(未加前缀的)后代都属于第二个默认命名空间。
© www.soinside.com 2019 - 2024. All rights reserved.