Перечисление в XMLDOM отличается от XPath
XMLDOM синтаксис перечисляет nodes
как элементы, основанные на нуле элементов в NodeList
, то есть начиная с 0
, тогда как выражения XPath , идентифицирующие начало подузлов с 1
(например, вызов имени элемента "//name[1]"
). Это ошибка при рассмотрении 2
в качестве последнего индекса элемента вместо циклического перехода от .Item(0)
до .Item(1)
в вашем примере кода. Вы получаете количество найденных элементов с помощью метода .Length
списка узлов (2 минус 1 приводит к тому, что 1 является последним индексом, что дает серии имен узла от 0 до 1).
Кроме того, рекомендуется ссылаться на MSXML2 версии 6.0 (MSXML2.DOMDocument
относится к последней стабильной версии 3.0, используемой только в целях совместимости) .
Дополнительные подсказки, предполагающие, что вы хотите пройтись по всем лицам в вашем XML-документе (список узлов в OP доставляет только один элемент, поскольку узел name
существует только один раз):
- Выражения
xDoc.SelectNodes("//Document/person")
или //person
будут искать определенный набор узлов на любом уровне иерархии в рамках данной структуры узлов. Таким образом, использование однозначно Set toFields = xDoc.DocumentElement.SelectNodes("person")
в вашем случае занимает меньше времени.
- В следующем примере кода не будет показан случай
Nothing
, поскольку в списке узлов отображаются только два узла name
(For i = 0 To toFields.Length - 1
). Просто для того, чтобы проверить свою первоначальную попытку, вы можете перечислить до трех элементов, намеренно изменив значение на For i = 0 To toFields.Length
(т.е. 0 to 2
).
Дополнительная ссылка
Анализ вашей XML-структуры с помощью рекурсивных вызовов; рабочую функцию можно найти на Синтаксический анализ XML с использованием XMLDOM .
Пример кода
Dim xDoc As Object, toFields As Object
Dim myName As String, i As Long
Set xDoc = CreateObject("MSXML2.DOMDocument.6.0") ' recommended version 6.0 (if late bound MSXML2)
xDoc.async = False: xDoc.validateOnParse = False
' ...
Set toFields = xDoc.DocumentElement.SelectNodes("person")
For i = 0 To toFields.Length - 1
If Not toFields.Item(i) Is Nothing Then
If toFields.Item(i).HasChildNodes Then
myName = toFields.Item(i).SelectSingleNode("name").Text
Debug.Print i, IIf(Len(Trim(myName)) = 0, "**Empty name", myName)
Else
Debug.Print i, "**No name node**"
End If
Else
Debug.Print i, "**Nothing**" ' shouldn't be needed from 0 to .Length-1 items :-)
End If
Next i