Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting values from all nodes with specific name from XML

Tags:

powershell

xml

I'm having problem with the most efficient way to get all the values of the nodes with certain name from XML.

For example:

<h1>
<MyNode>Node One</MyNode>
<h2>
    <MyNode>Note Two</MyNode>
    <DiffrentNode>I dont want that</DiffrentNode>
    <h3>
        <MyNode>Node Three</MyNode>
    </h3>
</h2>
<HHH1>
    <MyNode>Node Four</MyNode>
</HHH1>
</h1>
<g2>
    <MyNode>Node Five</MyNode>
</g2>

From the XML I want to get these values:

  • Node One
  • Node Two
  • Node Three
  • Node Four
  • Node Five

I'd like to be able to do the same with code like that:

<h1>
<h2 MyArgument = "Argument One" Stuff = "I dont want that">
    <DiffrentNode>Something I dont want</DiffrentNode>
    <h3 MyArgument = "Argument Two" Stuff = "I dont want that too">
    </h3>
</h2>
<HHH1>
    <DiffrentNode>Something I dont want</DiffrentNode>
</HHH1>
</h1>
<g2 MyArgument = "Argument Three">
    <DiffrentNode>Something I dont want</DiffrentNode>
</g2>

and get:

  • Argument One
  • Argument Two
  • Argument Three

Any ideas? So far I tried doing:

$xdoc = New-Object System.Xml.XmlDocument
$file = Resolve-Path("C:\CompiledDynoview.xml")
$xdoc.load($file)
[xml] $xdoc = Get-Content $file
$xdoc.h1.MyNode
$xdoc.h1.h2.MyNode
$xdoc.h1.h3.MyNode
...

But it doesn't seem to be the best way. There should be something better.

like image 544
Skylerdw Avatar asked Dec 29 '15 15:12

Skylerdw


1 Answers

You're trying to do different things here, so you won't be able to use the exact same code for both operations.

In your first example you want to select the value of all nodes with the name MyNode. Select the nodes with the XPath expression //MyNode and expand their #text property. There are various ways to do this, for instance with Select-Xml, as @PetSerAl suggested:

Select-Xml -XPath '//MyNode' -Path 'C:\path\to\first.xml' |
  Select-Object -Expand Node |
  Select-Object -Expand '#text'

or by importing the file as an XmlDocument object and using its SelectNodes() method:

[xml]$xml = Get-Content 'C:\path\to\first.xml'
$xml.SelectNodes('//MyNode') | Select-Object -Expand '#text'

In your second example you want to select the value of the attribute MyArgument from all nodes that have this particular attribute. Use the XPath expression //@MyArgument to select all attributes MyArgument, then expand their value as before, like this:

Select-Xml -XPath '//@MyArgument' -Path 'C:\path\to\second.xml' |
  Select-Object -Expand Node |
  Select-Object -Expand '#text'

or like this:

[xml]$xml = Get-Content 'C:\path\to\second.xml'
$xml.SelectNodes('//@MyArgument') | Select-Object -Expand '#text'

Side note:

$xml = New-Object System.Xml.XmlDocument
$xml.load('C:\path\to\your.xml')

and

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

do the same thing, so use one or the other, not both.

like image 105
Ansgar Wiechers Avatar answered Oct 10 '22 23:10

Ansgar Wiechers