Parsing XML with namespace with PowerShell

Viewed 9395

I need a little help with understanding of an XML in PowerShell. I have several XML files like this:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.example.com/xml/catalog/2006-10-31">
    <product product-id="11210">
        ...
        <available-flag>true</available-flag>
        <online-flag>false</online-flag>
        <online-flag site-id="ru">true</online-flag>
        <online-flag site-id="fr">true</online-flag>
        <online-flag site-id="uk">false</online-flag>
        <online-flag site-id="de">true</online-flag>
        ...
    </product>
    <product product-id="50610">
        ...
        <available-flag>true</available-flag>
        <online-flag>true</online-flag>
        <online-flag site-id="ru">false</online-flag>
        <online-flag site-id="fr">true</online-flag>
        <online-flag site-id="uk">false</online-flag>
        <online-flag site-id="de">fasle</online-flag>
        ...
    </product>
    <product product-id="82929">
        ...
        <available-flag>true</available-flag>
        <online-flag>true</online-flag>
        <online-flag site-id="ru">false</online-flag>
        <online-flag site-id="fr">true</online-flag>
        <online-flag site-id="uk">false</online-flag>
        <online-flag site-id="de">true</online-flag>
        ...
    </product>
</catalog>

I need to get the values of two elements in PowerShell:

  • <online-flag> (without site-id attribute)
  • <online-flag site-id="ru">

for the product with product-id="50610".

I have the following code:

$Path = "C:\Temp\0\2017-08-12_190211.xml"
$XPath = "/ns:catalog/ns:product[@product-id='50610']"

$files = Get-ChildItem $Path | Where {-not $_.PSIsContainer}

if ($files -eq $null) {
    return
}

foreach ($file in $files) {
    [xml]$xml = Get-Content $file
    $namespace = $xml.DocumentElement.NamespaceURI
    $ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
    $ns.AddNamespace("ns", $namespace)
    $product = $xml.SelectSingleNode($XPath, $ns)
}

Several questions:

  1. With this code I am able to select the needed product node. PowerShell shows:

    online-flag        : {true, online-flag, online-flag, online-flag...}
    

    But how then I can select the values of the needed online-flag elements (if it is possible both ways: XPath one and the object one)?

  2. Is it possible to select a node in the "object" way? Like this:

    $product = $xml.catalog.product |
               Where-Object {$_."product-id".value -eq "50610"}
    
  3. If I have several files, what is the best way to select filename, global online-flag (without attributes), specific online-flag?

3 Answers
Related