Search code examples
vbscriptxmldom

Get the count of child nodes from XML file under a Parent having a specific value


I have a sample XML file that's constructed as below:

<?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>

I need the count of Nodes <MyNode> under the Node ParentLevel4 if the value of ParentLevel4additional is "My Data Matches".

I tried with the below script and I could not get a solution:

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

Solution

  • There are a few mistakes in your code:

    1. Remove the extra / at the end of your XPath because it will give you false results.
    2. The XPath in the following line is missing a level (ParentLevel3):

      Set ObjMyNodes=xmlDoc.selectNodes ("//ParentLevel1/ParentLevel2/ParentLevel4/MyNode/")
      
    3. Even if you add the missing level to the line above, it's still going to count all the MyNode nodes because you're re-selecting the nodes from the beginning. Moreover, if you have more than one match, it'll count all the MyNode nodes multiplied by the number of matches so you'll get unwanted + duplicate results.

    You are on the right track, but you should only select the nodes that are siblings to the matched node. Something like the following should give you the result you need:

    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