Получить количество дочерних узлов из XML-файла под родительским элементом, имеющим определенное значение

У меня есть образец XML-файла, который построен, как показано ниже:

<?xml version="1.0" encoding="UTF-8"?>
        <ParentLevel1>
            <ParentLevel2>
                <ParentLevel3>
                    <ParentLevel4>
                        <MyNode>Data 1</MyNode>
                        <MyNode>Data 2</MyNode>
                        <MyNode>Data 3</MyNode>
                        <MyNode>Data 4</MyNode>
                        <MyNode>Data 5</MyNode>
                        <MyNode>Data 6</MyNode>
                    </ParentLevel4>
                    <ParentLevel4additional>My Data Matches</ParentLevel4additional>
                </ParentLevel3>
                <ParentLevel3>
                    <ParentLevel4>
                        <MyNode>Data 7</MyNode>
                        <MyNode>Data 8</MyNode>
                        <MyNode>Data 9</MyNode>
                        <MyNode>Data 10</MyNode>
                        <MyNode>Data 11</MyNode>
                        <MyNode>Data 12</MyNode>
                    </ParentLevel4>
                    <ParentLevel4additional>My Data does not Match</ParentLevel4additional>
                </ParentLevel3>
            </ParentLevel2>
        </ParentLevel1>

Мне нужно количество узлов <MyNode> под узлом ParentLevel4, если значение ParentLevel4additional равно «Мои совпадения данных».

Я попытался с помощью приведенного ниже сценария, и я не смог найти решение:

MyNodeCount = 0
AdditionNodeCount = 0
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.Async = "False"

If (xmlDoc.Load(strXMLFile)) Then
    Set AdditionNode =xmlDoc.selectNodes ("//ParentLevel1/ParentLevel2/ParentLevel3/ParentLevel4additional/")

    For Each ParentLevel4additional in AdditionNode
        if ParentLevel4additional.Text = "My Data Matches" Then
            Set ObjMyNodes=xmlDoc.selectNodes ("//ParentLevel1/ParentLevel2/ParentLevel4/MyNode/")
            For Each MyNode in ObjMyNodes
                MyNodeCount = MyNodeCount + 1
            Next
            AdditionNodeCount = AdditionNodeCount + 1
        End If
    Next

    Wscript.Echo MyNodeCount
    Wscript.Echo AdditionNodeCount
Else
    WScript.Echo "Error loading XML file '" & strXMLFile & "'." & vbCrLf & _
                 "Error code: 0x" & Hex(xmlDoc.ParseError.ErrorCode) & vbCrLf & _
                 "Description: " & xmlDoc.ParseError.Reason & vbCrLf & _
                 "Line: " & xmlDoc.ParseError.Line & vbCrLf & _
                 "Character: " & xmlDoc.ParseError.LinePos
    WScript.Quit 1
End If

person PremKumarS    schedule 26.04.2018    source источник


Ответы (2)


В вашем коде есть несколько ошибок:

  1. Удалите лишний / в конце вашего XPath, потому что это даст вам ложные результаты.
  2. В XPath в следующей строке отсутствует уровень (ParentLevel3):

    Set ObjMyNodes=xmlDoc.selectNodes ("//ParentLevel1/ParentLevel2/ParentLevel4/MyNode/")
    
  3. Даже если вы добавите отсутствующий уровень в строку выше, все равно будут подсчитаны все MyNode узла, потому что вы повторно выбираете узлы с самого начала. Более того, если у вас есть более одного совпадения, он будет подсчитывать все узлы MyNode, умноженные на количество совпадений, поэтому вы получите нежелательные + повторяющиеся результаты.

Вы на правильном пути, но вам следует выбирать только те узлы, которые являются одноуровневыми по отношению к соответствующему узлу. Что-то вроде следующего должно дать вам нужный результат:

If (xmlDoc.Load(strXMLFile)) Then
    Set NodesList = xmlDoc.SelectNodes("//ParentLevel1/ParentLevel2/ParentLevel3")

    For Each node in NodesList
        Set ParentLevel4additional = node.SelectSingleNode("ParentLevel4additional")
        If ParentLevel4additional.Text = "My Data Matches" Then
            For Each myNode in node.SelectNodes("ParentLevel4/MyNode")
                MyNodeCount = MyNodeCount + 1
            Next
            AdditionNodeCount = AdditionNodeCount + 1
        End If
    Next

    Wscript.Echo MyNodeCount
    Wscript.Echo AdditionNodeCount
Else
    WScript.Echo "Error loading XML file '" & strXMLFile & "'." & vbCrLf & _
                 "Error code: 0x" & Hex(xmlDoc.ParseError.ErrorCode) & vbCrLf & _
                 "Description: " & xmlDoc.ParseError.Reason & vbCrLf & _
                 "Line: " & xmlDoc.ParseError.Line & vbCrLf & _
                 "Character: " & xmlDoc.ParseError.LinePos
    WScript.Quit 1
End If
person 41686d6564    schedule 26.04.2018

Используйте xPath:

//ParentLevel3[ParentLevel4additional='My Data Matches']/ParentLevel4

Вы можете использовать следующий код, чтобы получить количество дочерних узлов желаемого родительского узла:

Dim xmlPath, objXml, xPath
xmlPath = "J:\Documents\Gurman\Work\PersonalWork\Misc Codes\26042018_SO\source.xml"
set objXml = CreateObject("Microsoft.Xmldom")
objXml.async = False
objXml.load xmlPath

xPath = "//ParentLevel3[ParentLevel4additional='My Data Matches']/ParentLevel4"
set objNode = objXml.selectSingleNode(xPath)
set childnodes = objNode.ChildNodes
i=0
for each node in childnodes
    i = i+1
next

msgbox "No. of ChildNodes = " & i

set objNode = Nothing
set objXml = Nothing
person Gurmanjot Singh    schedule 26.04.2018