Ryian Rockers
Ryian Rockers

Reputation: 105

Foreach through XML document with Powershell returning multiple nodes

Trying to gather server and environment information from an XML document. But, when I use the foreach loop to iterate through the document, it returns both nodes in the tree, instead of one at a time.

[xml]$xmlDoc = [xml](Get-Content("C:\temp\compareVHD_info.xml"))

foreach($env in $xmlDoc.pvs.env)
{
    if($env -eq "prod")
    { do stuff}
}

XML:

<pvs>
  <env>
    <prod>
        <primaryServer>
            <name>name</name>
            <storePath>path</storePath>
        </primaryServer>
        <secondaryServer>
            <name>name</name>
            <storePath>path</storePath>
        </secondaryServer>
    </prod>
    <nonProd>
        <primaryServer>
            <name>name</name>
            <storePath>path</storePath>
            <storePath>path</storePath>
            <storePath>path</storePath>
            <storePath>path</storePath>
        </primaryServer>
        <secondaryServer>
            <name>name</name>
            <storePath>path</storePath>
            <storePath>path</storePath>
            <storePath>path</storePath>
            <storePath>path</storePath>
        </secondaryServer>
    </nonProd>
  </env>
</pvs>

I'm trying to gather the primary and secondary server names, the storepaths, and the store paths. Though, when I use the code above, it returns both "prod nonProd" in the $env variable

Thanks in advance for the help!

Upvotes: 0

Views: 12419

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200203

The code you posted can't possibly work. Your XML data has just a single <env> node, so your loop iterates over a single object with 2 properties (prod and nonProd), hence a check $env -eq "prod" will always evaluate to $false. What you actually want is to select the <primaryServer> and/or <secondaryServer> nodes and output the values of their child nodes.

[xml]$xml = Get-Content 'C:\path\to\input.xml'

$xml.SelectNodes('//prod/primaryServer') | ForEach-Object {
    New-Object -Type PSObject -Property @{
        Name = $_.name
        Path = $_.storePath -join ';'
    }
} | Export-Csv 'C:\path\to\output.csv' -NoType

If you want primary and secondary in the same file change the XPath expression to something like //prod/*[self::primaryServer or self::secondaryServer] if there are other sibling nodes as well, or just //prod/* if those are the only child nodes of <prod>.

Upvotes: 6

Related Questions