很长时间的读者,但首先发布在这里。任何和所有帮助非常感谢!
我正在研究数据抓取器以从网格运算符获取客户的市场结果,并且需要一系列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")
使用名称空间进行简单的XML解析
请尝试以下代码行
其中xmlNameSpaces
只是一个字符串变量,复制xmlns
节点中的先前命名空间(<QueryResponse>
)属性。
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数据示例中超过前一个声明(除了显式前缀的元素名称)。
<SynchOfferMW>
(而不是可能的<extra:SynchOfferMW>
,它将基于先前名称空间声明xmlns:extra="http://..."
中的附加显式前缀赋值)。使用无前缀的命名空间,您将声明两个默认命名空间,一个用于<Envelope>
元素,第二个用于<QueryResponse>
元素。<QueryResponse>
元素及其所有(未加前缀的)后代都属于第二个默认命名空间。