Powershell XML parse not working on subnodes
I am tring to parse the following file:
<?xml version="1.0" encoding="UTF-8" ?>
<printDrivers>
<printDriver id="XE8550">
<inf>x28550p.inf</inf>
<driverPath>\drivers\XEROX\8550\8550_Driver</driverPath>
<printerPaths>
<printerPath>\\print-man\man-25</printerPath>
</printerPaths>
</printDriver>
<printDriver id="HP4050TN">
<inf>hpbf002i.inf</inf>
<driverPath>\drivers\HP\LaserJet\LaserJet_4050_PCL6</driverPath>
<printerPaths>
<printerPath>\\print-man\man-8</printerPath>
<printerPath>\\print-man\man-14</printerPath>
</printerPaths>
</printDriver>
</printDrivers>
with the following powershell script:
$nodelist = $xd.selectnodes("/printDrivers/printDriver") # XPath is case sensitive
foreach ($printerDriverNode in $nodelist) {
$XMLid = $printerDriverNode.getAttribute("id")
$XMLinf = $printerDriverNode.selectSingleNode("inf").get_innerXml()
$XMLdriverPath = $printerDriverNode.selectSingleNode("driverPath").get_innerXml()
$printerPathNodeList = $printerDriverNode.selectNodes("printerPaths/printerPath")
foreach ($printerPathNode in $printerPathNod开发者_开发知识库eList) {
$XMLprinterPath = $printerPathNode.selectSingleNode("printerPath").get_innerXml()
}
}
It all works fine, except for the "nested" node. When I run the script it only gets the first . i.e. it won't get \print-man\man-14, only \print-man\man-8.
How can I get it to bring back all of the nodes?
Thanks,
Ben
foreach ($printerPathNode in $printerPathNodeList) {
$XMLprinterPath = $printerPathNode.selectSingleNode("printerPath").get_innerXml()
}
You're already iterating over the printerPaths/printerPath
nodes here - no need to do another .selectsinglenode
on that <printerPath>
node - just read the .InnerXml
or .InnerText
from that $printerPathNode
- that should give you the values you're looking for
That's expected, you're assigning the same variable ($XMLprinterPath) multiple times, so the second value overrides the first. Did you meant to use that as an array or list?
If you have PowerShell V2.0 available, you can use Select-Xml
which generates objects for you on-the-fly:
Select-Xml -Path "test.xml" -Xpath "/printDrivers/printDriver" | ForEach-Object {
$id = $_.Node.id
$inf = $_.Node.inf
$driverPath = $_.Node.driverPath
$_.Node | Select-Xml -Xpath "printerPaths/printerPath" | ForEach-Object {
$printerPath = $_.Node.InnerText
}
}
I am guessing you are trying to flatten the XML into objects
$r = $xml.printDrivers.printDriver | %{
New-Object PSObject -Property @{
id = $_.id
inf = $_.inf
driverPath = $_.driverPath
printerPaths = @(&{$_.printerPaths | % {$_.printerPath} })
}
}
$r[1].printerPaths
You already have the node, so just use it :)
$nodelist = $xd.selectnodes("/printDrivers/printDriver") # XPath is case sensitive
foreach ($printerDriverNode in $nodelist) {
$printerPathNodeList = $printerDriverNode.selectNodes("printerPaths/printerPath")
foreach ($printerPathNode in $printerPathNodeList) {
write-host $printerPathNode.get_innerXml()
}
}
Note, that it is possible to access xml like objects.
$xd.printDrivers.printdriver | % { $_.id; $_.printerPaths.printerPath }
精彩评论