Excel VBA получает конкретный узел из XML

У меня есть XML-файл из API URL (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

Пример 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>

Я хочу вывести текст в каждом <ID> (т.е. 111 а также 112) и каждый <Title>, Это только пример, в зависимости от того, какой API я использую, я захочу выбрать, какую информацию я получу.

2 ответа

Решение

Попробуйте это - вы можете изменить приведенный ниже код, чтобы получить любой дочерний узел

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

Редактировать из вопроса автора:

Это сработало отлично. Для любых читателей я использовал приведенный выше ответ для адаптации своего кода (поскольку я загружаю XML из URL, а не из файла):

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

Вот немного другой подход, основанный на ответе Панкаджа Джаджу выше.

Заметки:

  • использует пространство имен 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
Другие вопросы по тегам