Создать фильтрацию XPath по значению типа?

#xml #powershell #xpath

Вопрос:

У меня есть приведенный ниже XML (это часть более крупного документа):

 lt;class type="I want to filter on whatever value this is"gt;  lt;instance name="QuestionSet4"gt;  lt;property name="QuestionSetName"gt;QuestionSet4lt;/propertygt;  lt;property name="Ratio"gt;5lt;/propertygt;  lt;/instancegt;  lt;instance name="QuestionSetTrust"gt;  lt;property name="QuestionSetName"gt;QuestionSetTrustlt;/propertygt;  lt;property name="Ratio"gt;5lt;/propertygt;  lt;/instancegt;  lt;/classgt;  

Моя цель состоит в том , чтобы использовать PowerShell Select-Xml таким образом, чтобы я мог возвращать оба name свойства для каждого узла, используя XPath, который фильтрует класс type , чтобы вывод был примерно таким:

 QuestionSetName, Ratio QuestionSet4, 5 QuestionSetTrust, 5  

Класс type уникален в документе, поэтому я задался вопросом, можно ли фильтровать на основе этого, а не жестко кодировать элемент, как показано ниже:

 /root/class[3]/@type  

Вместо этого это было бы /root/class/@type="I want to filter on whatever value this is"...

Имена экземпляров будут меняться от документа к документу, поэтому я также не могу фильтровать это.

Ответ №1:

Вы можете разрешить соответствующие instance узлы с помощью выражения XPath, например, следующего:

 //class[@type = 'I want to filter on whatever value this is']/instance  

Таким образом, вы могли бы построить желаемые выходные объекты следующим образом:

 $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  } }  

Если у вас есть много lt;property /gt; элементов, которые нужно перечислить для каждого lt;instance /gt; , это быстро приведет к беспорядку, но вы можете немного упростить это следующим образом:

 $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 }  

Комментарии:

1. Ваш первый отрывок работает идеально. Спасибо!