VBA - SelectSingleNode извлекает только первый узел из списка

Я использую VBA для работы с XML-файлом. MS Offfice - 2013. Я добавил библиотеку - Microsoft XML Version6.0. Пожалуйста, найдите ниже xml, а также код. Я пытаюсь получить все TID в XML и написать на листе. Но selectsinglenode() извлекает только первый узел. Что я делаю неправильно? Есть ли способ использовать selectsinglenode для возврата каждого TID? Пожалуйста, предложите. Дайте мне знать, если вам нужна дополнительная информация.

<NDA xmlns="http://www.example.com">
  <FileHeader>
    <Form>7</Form>
    <SID>1521</SID> 
  </FileHeader>
  <Subdivision>
    <SID>1521</SID>
    <CID>200</CID>
    <Version>1</Version>
  </Subdivision>
  <BC>
    <BF>
        <BElem>
            <BFountain>
                <BFeature>
                  <Start>0</Start>
                  <End>279</End>
                  <TType>2</TType>
                  <SLimit>25</SLimit>
                  <SIT>3</SIT>
                  <RBTField>0</RBTField>
                  <RType>1</RType>
                  <RParam>0</RParam>
                  <RParamOp>5</RParamOp>
                  <TID>4015100639</TID>
                </BFeature>
                <BFeature>
                  <Start>0</Start>
                  <End>279</End>
                  <TType>1</TType>
                  <SLimit>50</SLimit>
                  <SIT>3</SIT>
                  <RBTField>0</RBTField>
                  <RType>2</RType>
                  <RParam>0</RParam>
                  <RParamOp>5</RParamOp>
                  <TID>2850474662</TID>
                </BFeature>
                <BFeature>
                  <Start>0</Start>
                  <End>279</End>
                  <TType>1</TType>
                  <SLimit>25</SLimit>
                  <SIT>3</SIT>
                  <RBTField>0</RBTField>
                  <RType>1</RType>
                  <RParam>0</RParam>
                  <RParamOp>5</RParamOp>
                  <TID>2563719215</TID>
                </BFeature>
                <BFeature>
                  <Start>0</Start>
                  <End>279</End>
                  <TType>3</TType>
                  <SLimit>25</SLimit>
                  <SIT>3</SIT>
                  <RBTField>0</RBTField>
                  <RType>1</RType>
                  <RParam>0</RParam>
                  <RParamOp>5</RParamOp>
                  <TID>1962204848</TID>
            </BFeature>
          </BFountain>
        </BElem>
    </BF>
    </BC>  
</NDA>

Ниже приведен код:

Dim xDoc1 As MSXML2.DOMDocument60
Dim xNodeList1 As MSXML2.IXMLDOMNodeList
Dim xNode1 As MSXML2.IXMLDOMNode
Dim xChildNode1 As MSXML2.IXMLDOMNode
Dim xpathToExtractRow1 As String, XMLNamespaces1 As String
Dim wCompareWorksheet As Excel.Worksheet
Dim sFoundNode As MSXML2.IXMLDOMNode

Set xDoc1 = New MSXML2.DOMDocument60
xDoc1.async = False
xDoc1.validateOnParse = False
XMLNamespaces1 = "xmlns:r='http://www.example.com"

xDoc1.Load ("ABCD.xml")
xDoc1.setProperty "SelectionNamespaces", XMLNamespaces1
xDoc1.setProperty "SelectionLanguage", "XPath"

If xDoc1.parseError.ErrorCode <> 0 Then
  Set oErr1 = xDoc1.parseError
  Debug.Print oErr1.reason
End If

Set xNodeList1 = xDoc1.SelectNodes("/r:NDA/r:BC/r:BF/r:BElem/r:BFountain/r:BFeature")

z=1
For x = 0 To xNodeList1.Length - 1
    bFirstChild = True
    If xNodeList1.Item(x).HasChildNodes Then
        For i = 0 To xNodeList1.Item(x).ChildNodes.Length - 1
            Set sFoundNode = xNodeList1.Item(x).ChildNodes(i).SelectSingleNode("/r:NDA/r:BC/r:BF/r:BElem/r:BFountain/r:BFeature/r:TID")
            If Not sFoundNode Is Nothing Then
                wCompareWorksheet.Cells(z, 1) = x & "," & i

                wCompareWorksheet.Cells(z, 4) = sFoundNode.nodeName
                wCompareWorksheet.Cells(z, 6) = sFoundNode.Text
                z = z + 1
            Else
                Debug.Print "sFound is nothing"
            End If
        Next
    End If
Next

1 ответ

Решение

Ваш код использует абсолютный путь местоположения (это абсолютный путь местоположения, потому что он начинается с /):

.selectSingleNode("/r:NDA/r:BC/r:BF/r:BElem/r:BFountain/r:BFeature/r:TID")

В частности, /r:NDA означает запуск этого пути к местоположению из элемента документа с именем "NDA" в пространстве имен, обозначенном "r". Изменение элемента, который вы называете selectSingleNode on не изменит результаты этого пути местоположения. В терминах Excel это похоже на использование $A$1 в формуле - где бы вы ни копировали эту формулу, она всегда будет ссылаться на ячейку A1.

Вам нужно либо использовать selectNodes (как предлагается в комментариях) или использовать selectSingleNode с относительным расположением пути, как это:

Set sFoundNode = xNodeList1.Item(x).ChildNodes(i).selectSingleNode("self::r:TID")

Результат этого пути расположения зависит от узла контекста - childNodes(i), Он проверяет, называется ли сам контекстный узел "TID" в пространстве имен, обозначенном "r", и выводит подробности соответственно.

Это не очень разумный способ достижения этого результата. Вы можете просто проверить nodeName атрибут каждого дочернего узла напрямую. Еще лучше, вы могли бы использовать selectNodes найти все r:TID узлы сразу, а затем выполнить любые необходимые манипуляции с ними

Другие вопросы по тегам