none
Count XML nodes

    Question

  • I want a simple script that given a file and xpath, it will return then number of items.  Here is what I am starting with but it does not return any info:

    [xml]$data = Get-Content C:\ExpenseFeed1.xml
    $rows = $data.selectnodes("/ExpenseFeed/Expense/ExpenseId")
    write-host $rows.length
    Write-host "completed"

    The XML looks like:

    <?xml version="1.0" encoding="utf-8"?>
    <ExpenseFeed>
      <Expense>
        <ExpenseId>53686</ExpenseId>   
        <ExpenseId>53687</ExpenseId>
    ....

    Monday, February 04, 2013 9:05 PM

Answers

  • I almost wonder if there's a problem with the XML file. I'm using a simple testing xml file as shown below, and get a count of 2.

    You may want to interactively inspect your $rows and your $data to make sure of what you're getting. The $rows.count will only give you a 0 if your selectnodes query returns no nodes.

    One of the funny things about this is that $rows is still a System.Xml.XPathNodeList object. You'll successfully get XPathNodeList descriptive data if you do this:

    Get-Member -InputObject $rows

    However, piping $rows into Get-Member throws an error:

    PS C:\Users\aka> $rows | gm
    gm : No object has been specified to the get-member cmdlet.
    At line:1 char:9
    + $rows | gm
    +         ~~
        + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
        + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand

    Here's the XML file that works for me:

    <?xml version="1.0" encoding="utf-8"?>
    <ExpenseFeed>
      <Expense>
        <ExpenseId>53686</ExpenseId>    
        <ExpenseId>53687</ExpenseId>
    </Expense>
    </ExpenseFeed>
    

    Wednesday, February 06, 2013 5:34 AM

All replies

  • $rows is not a collection or array, but an XPathNodeList. So it doesn't have a length property. However, it does have a Count. When you have puzzling behavior from array-like/collection-like items, you can check what they actually are like this:

    gm -InputObject $rows

    In this case, you can use $rows.Count and access elements by $row.Item(x).

    If you really do need array-like behavior, you can get that by "combing" $rows:

    $rows = $rows | %{$_}

    Monday, February 04, 2013 9:22 PM
  • [System.Xml.XmlDocument] $data  = new-object System.Xml.XmlDocument
    $data.load("C:\temp\1.xml")
    $rows = $data.selectnodes("//ExpenseFeed/Expense/ExpenseId")
    write-host $rows.count
    write-host "completed"

    Monday, February 04, 2013 9:22 PM
  • [System.Xml.XmlDocument] $data  = new-object System.Xml.XmlDocument
    $data.load("C:\temp\1.xml")
    $rows = $data.selectnodes("//ExpenseFeed/Expense/ExpenseId")
    write-host $rows.count
    write-host "completed"


    Thanks.  I am now using count as suggested, and this exact script, but it returns "0".
    Tuesday, February 05, 2013 4:56 PM
  • I almost wonder if there's a problem with the XML file. I'm using a simple testing xml file as shown below, and get a count of 2.

    You may want to interactively inspect your $rows and your $data to make sure of what you're getting. The $rows.count will only give you a 0 if your selectnodes query returns no nodes.

    One of the funny things about this is that $rows is still a System.Xml.XPathNodeList object. You'll successfully get XPathNodeList descriptive data if you do this:

    Get-Member -InputObject $rows

    However, piping $rows into Get-Member throws an error:

    PS C:\Users\aka> $rows | gm
    gm : No object has been specified to the get-member cmdlet.
    At line:1 char:9
    + $rows | gm
    +         ~~
        + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
        + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand

    Here's the XML file that works for me:

    <?xml version="1.0" encoding="utf-8"?>
    <ExpenseFeed>
      <Expense>
        <ExpenseId>53686</ExpenseId>    
        <ExpenseId>53687</ExpenseId>
    </Expense>
    </ExpenseFeed>
    

    Wednesday, February 06, 2013 5:34 AM
  • Yes, it must be the file.  Thanks for your patience!
    Wednesday, February 06, 2013 1:32 PM