Я пытаюсь использовать макрос VBA для анализа файла XML. Дано со следующей структурой:
<bookstore>
<book category = "children">
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category = "web">
<title>Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
Как я могу перечислить вывод с тегами элементов с соответствующими значениями, как показано ниже?
book | category | children
title | harry potter
author | J K. Rowling
...
Мой код выглядит следующим образом:
Set xmlFile = CreateObject("Microsoft.XMLDOM")
xmlFile.Load (file)
Set qXML = xmlFile.SelectNodes("/bookstore")
For i = 0 To qXML.Length - 1
Debug.Print CStr(qXML(i).Text)
Next i
Спасибо за ваш ответ. Да, небольшое изменение для ясности, но никаких изменений в коде. Я попытался запустить с предоставленным вами решением, и он показывает ошибку времени выполнения «91», переменная объекта или переменная блока не установлена.
Я ожидал, что ваш код работает до сих пор. Но, кажется, это не так. Я использовал раннее связывание в своем проекте и другой код для создания экземпляра объекта. Я редактирую свой ответ сейчас.
Я предлагаю использовать раннее связывание.
Итак, в вашем проекте в VBE добавьте ссылку (меню tools/references
) на Microsoft XML, v6.0
.
Чтобы определить атрибут и значения, вы можете использовать это:
Dim xmlFile As MSXML2.DOMDocument60
Set xmlFile = New MSXML2.DOMDocument60
xmlFile.Load file
Dim qXML As MSXML2.IXMLDOMNodeList
Set qXML = xmlFile.SelectNodes("/bookstore/book")
Dim index As Long
For index = 0 To qXML.Length - 1
Debug.Print qXML(index).SelectSingleNode("@category").Text
Debug.Print qXML(index).SelectSingleNode("title").Text
Debug.Print qXML(index).SelectSingleNode("author").Text
Next index
Дружественный совет: неизменное выражение XPath из OP пытается обратиться к одному элементу, то есть к возможному documentElement
, а не к NodeList: вместо этого попробуйте Set qXML = xmlFile.SelectNodes("//book")
:-)
@T.M.: Спасибо за подсказку, но, к сожалению, я не понимаю, что ты пытаешься мне сказать. Не могли бы вы быть так добры и быть более описательным?
Посмотрите на один уровень иерархии глубже: ваш код вызывает Run time error 91
(переменная объекта или с переменной блока не установлена), поскольку ваш выбор узла проходит через несуществующие запросы пути в bookstore
объекте qXML
(который также является документом/верхним уровнем) и вместо этого через book
элементы, которые ОП хочет проанализировать. Поэтому элемент bookstore
не может отображать подузлы/атрибуты, такие как @category
, title
или author
, а только последующие узлы book
:-)
О, черт, я пропустил это. Должно быть, это произошло во время редактирования ответа. Мой тестовый код работал здесь. Спасибо за информацию. Я исправил это сейчас.
Как получить имена тегов
«Какой синтаксис XPath для получения имен тегов?»
Строго говоря, это синтаксис (XML)DOM для получения свойств .Name
и/или .NodeName
;
XMLDOM (объектная модель документа) — это кросс-платформенный и независимый от языка интерфейс, рассматривающий документ как древовидную структуру и обеспечивающий программный доступ к дереву.
Однако вы можете использовать специальный синтаксис выражений XPath (например, "/bookstore/book/title"
) для обращения к любой логической части в иерархической структуре XML-документа.
Таким образом, решение, близкое к вашему OP, будет:
Option Explicit ' declaration head of your code module
Sub ExampleCall()
Dim file As String: file = ThisWorkbook.Path & "\xml\bookstore.xml"
Dim xmlFile As Object
Set xmlFile = CreateObject("Microsoft.XMLDOM")
If xmlFile.Load(file) Then
Dim qXML As Object
Set qXML = xmlFile.DocumentElement.SelectNodes("book")
Dim q As Object
For Each q In qXML
Dim cnt As Long: cnt = cnt + 1
Debug.Print Format(cnt, "--- 000 ---")
Debug.Print q.Attributes(0).Name, "|" & q.Attributes(0).Text
Dim i As Long
For i = 0 To q.ChildNodes.Length - 1
Debug.Print q.ChildNodes(i).nodeName, "|" & q.ChildNodes(i).Text
Next
Next
End If
End Sub
Результаты в непосредственном окне VBE
--- 01 ---
category |children
title |Harry Potter
author |J K. Rowling
year |2005
price |29.99
--- 02 ---
category |web
title |Learning XML
author |Erik T. Ray
year |2003
price |39.95
Примечание
Поскольку Microsoft.XMLDOM
устарела в течение многих лет,
Я бы предпочел привязку к ►MSXML2
в самой последней версии xml Microsoft XML,v6.0
, например. с помощью
I. ПОЗДНЕЕ связывание (как в OP)
Dim xDoc As Object
Set xDoc = CreateObject("MSXML2.DOMDocument.6.0")
II. РАННЕЕ связывание
Dim xDoc As MSXML2.DOMDocument60 ' *) whereas MSXML2.DOMDocument (=old version 3.0)
Set xDoc = New MSXML2.DOMDocument60 ' mind the missing point in digits
Примечание: OP использует объектную переменную XMLFile
вместо xDoc
Обратите внимание, что ссылка на DOMDocument
без очевидной версии будет по умолчанию привязана к версии 3.0.
(последняя стабильная версия перед 6.0, любые другие версии устарели).
Дополнительные ссылки
Что делать, если есть вложенные узлы?
@onlineCake ... затем примените код, показанный в первой ссылке; ответ выше пытается быть как можно ближе к ОП :-)
Вы отредактировали свой вопрос после того, как я ответил на него. Вы уже прочитали это? Должен ответить на ваш вопрос.