Excel VBA从XML获取特定节点

yoz*_*234 9 xml excel vba ixmldomnode

我有一个来自URL API的XML文件(我没有共享的URL,因为它允许访问安全信息).从这个文件我想得到一些信息.我的问题是,一旦我在父节点(eventNode),我想简单地能够从特定的子节点获取数据.

例如,如果是eventNode <event><ID>1</ID>...<title>event 1</title></event>,我将如何1知道节点名称ID(或我想要提取的任何其他值)?

我通过论坛看了很多,但.SelectSingleNode没给我运气.也.selectNodes不会像XML字符串中的正常节点列表那样行事.我不知道这是否是由于我用来解析我的XML文件的方法.

Sub ListEvents()

Dim strPath As String

strPath = getAPI("GetEvents", "filter=&orderBy=")

Dim xmlDocument As MSXML2.DOMDocument60
Set xmlDocument = New DOMDocument60

With CreateObject("MSXML2.XMLHTTP")
    .Open "GET", strPath, False
    .send
    xmlDocument.LoadXML .responseText
End With

Dim lvl1 As IXMLDOMNode: Dim lvl2 As IXMLDOMNode
Dim eventNode As IXMLDOMNode: Dim isNode As IXMLDOMNode

For Each lvl1 In xmlDocument.ChildNodes
    For Each lvl2 In lvl1.ChildNodes
        For Each eventNode In lvl2.ChildNodes
            If eventNode.HasChildNodes Then
                'Here is where I want code to find specific child node
                'without having to look at every node.
            End If
        Next
    Next
Next

End Sub
Run Code Online (Sandbox Code Playgroud)

示例XML:

<?xml version="1.0" encoding="utf-8" ?> 
<ResultsOfListOfEvent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.regonline.com/api">
  <Success>true</Success> 
  <Data>
    <APIEvent>
      <ID>111</ID> 
      <CustomerID>222</CustomerID> 
      <ParentID>0</ParentID> 
      <Status>Testing</Status> 
      <Title>Event Name</Title> 
      <ClientEventID /> 
      <TypeID>9</TypeID> 
      <TimeZone>GMT</TimeZone> 
      <CurrencyCode>GBP</CurrencyCode> 
      <AddDate>2013-12-18T02:34:09.357</AddDate> 
      <Channel>Running</Channel> 
      <IsWaitlisted>false</IsWaitlisted> 
    </APIEvent>
    <APIEvent>
      <ID>112</ID> 
      <CustomerID>223</CustomerID> 
      <ParentID>0</ParentID> 
      <Status>Testing</Status> 
      <Title>Event Name</Title> 
      <ClientEventID /> 
      <TypeID>9</TypeID> 
      <TimeZone>GMT</TimeZone> 
      <CurrencyCode>GBP</CurrencyCode> 
      <AddDate>2013-12-18T02:34:09.357</AddDate> 
      <Channel>Running</Channel> 
      <IsWaitlisted>false</IsWaitlisted> 
    </APIEvent>
  </Data>
</ResultsOfListOfEvent>
Run Code Online (Sandbox Code Playgroud)

我想在每个<ID>(即111112)和每个中输出文本<Title>.这只是一个例子,取决于我运行的API,我希望能够选择和选择我提取的信息.

Pan*_*aju 9

试试这个 - 你可以修改下面的代码来获取任何子节点

Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.SetProperty "SelectionLanguage", "XPath"
xmlDoc.Async = False
xmlDoc.Load("C:\Users\pankaj.jaju\Desktop\Test.xml")

Set nodeXML = xmlDoc.getElementsByTagName("ID")
For i = 0 To nodeXML.Length - 1
    MsgBox nodeXML(i).Text
Next
Run Code Online (Sandbox Code Playgroud)

来自问题作者的编辑:

这很有效.对于任何读者来说,这就是我如何使用上面的答案来调整我的代码(因为我从URL加载XML - 而不是文件):

Sub ListEvents()
Dim myURL As String

myURL = getAPI("GetEvents", "filter=&orderBy=")

Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.setProperty "SelectionLanguage", "XPath"
xmlDoc.async = False

With CreateObject("MSXML2.XMLHTTP")
    .Open "GET", myURL, False
    .send
    xmlDoc.LoadXML .responseText
End With

Set nodeXML = xmlDoc.getElementsByTagName("ID")
For i = 0 To nodeXML.Length - 1
    MsgBox nodeXML(i).Text
Next
End Sub
Run Code Online (Sandbox Code Playgroud)


bar*_*owc 9

这是一个略有不同的方法,建立在Pankaj Jaju上面的答案之上.

笔记:

  • 使用MSXML2命名空间作为旧的Microsoft.XMLDOM,只为传统支持维护 - 请参阅此处
  • 当文档具有默认命名空间时,使用"SelectionNamespaces"属性来修复MSXML2与XPath的问题 - 请参阅此处.我们创建一个名为r(任何名称都可以)的名称空间,它与文档中的默认名称空间具有相同的URI引用(http://www.regonline.com/api在本例中)
  • 在XPath中使用该新命名空间作为任何具有无前缀名称的元素的前缀.这是一种复杂的说法,而不是寻找/ID,我们会寻找/r:ID

这是代码:

Sub foo()

Dim xmlDoc As Object
Dim xmlNodeList As Object
Dim xmlNode As Object

Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
xmlDoc.setProperty "SelectionNamespaces", "xmlns:r='http://www.regonline.com/api'"
xmlDoc.async = False
xmlDoc.Load "C:\Users\colin\Desktop\yoz1234.xml"

Set xmlNodeList = xmlDoc.selectNodes("/r:ResultsOfListOfEvent/r:Data/r:APIEvent/r:ID")

For Each xmlNode In xmlNodeList
    MsgBox xmlNode.Text
Next xmlNode

End Sub
Run Code Online (Sandbox Code Playgroud)