I have the below XML (that is part of a larger document):
<class type="I want to filter on whatever value this is">
<instance name="QuestionSet4">
<property name="QuestionSetName">QuestionSet4</property>
<property name="Ratio">5</property>
</instance>
<instance name="QuestionSetTrust">
<property name="QuestionSetName">QuestionSetTrust</property>
<property name="Ratio">5</property>
</instance>
</class>
My goal is to use PowerShell's Select-Xml
such that I can return both of the name
properties for each node using an XPath that filters on the class type
, so that the output is something like this:
QuestionSetName, Ratio
QuestionSet4, 5
QuestionSetTrust, 5
The class type
is unique in the document so I wondered if it was possible to filter based on that rather than hard coding the element like below:
/root/class[3]/@type
It would instead be /root/class/@type="I want to filter on whatever value this is"...
Instance names will change from document to document so I cannot filter on this either.
CodePudding user response:
You can resolve the relevant instance
nodes with an XPath expression like the following:
//class[@type = 'I want to filter on whatever value this is']/instance
So you could construct the desired output objects like this:
$xml |Select-Xml -XPath "//class[@type = 'I want to filter on whatever value this is']/instance" |ForEach-Object {
[pscustomobject]@{
QuestionSetName = ($_.Node |Select-Xml "./property[@name='QuestionSetName']").Node.InnerText
Ratio = ($_.Node |Select-Xml "./property[@name='Ratio']").Node.InnerText
}
}
If you have a lot of <property />
elements to enumerate for every <instance />
it'll quickly get messy, but you can simplify it slightly like this:
$propertyNames = 'QuestionSetName','Ratio','Size','SomeOtherProperty'
$xml |Select-Xml -XPath "//class[@type = 'I want to filter on whatever value this is']/instance" |ForEach-Object {
$properties = [ordered]@{}
foreach($name in $propertyNames){
$properties[$name] = ($_.Node |Select-Xml "./property[@name='${name}']").Node.InnerText
}
[pscustomobject]$properties
}