Excel VBA получение определенного узла из XML
у меня есть XML-файл из URL API (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 one поддерживается только для устаревшей поддержки-см. здесь
- использует свойство "SelectionNamespaces" для устранения проблемы, которую MSXML2 имеет с XPath, когда документ имеет пространство имен по умолчанию - см. здесь. Мы создаем пространство имен
r
(любое имя будет делать хотя), который имеет ту же ссылку URI, что и namesepace по умолчанию в документе (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