Powershell - XML ​​- Как извлечь несколько значений с разной глубины для каждого семейства узлов

Мне нужно проанализировать несколько миллионов строк XML. Для одного приложения я хочу извлечь 3 части данных для использования в других скриптах.

XML выглядит примерно так (несколько десятков тегов было удалено для каждой группы). Я могу изменить один из тегов имен, если это поможет; хотя и нежелательно, это потребует некоторой промежуточной обработки. Не все группы узлов имеют расширенные атрибуты.

<?xml version="1.0" encoding="IBM437"?>
<topo>
    <node>
        <name>device1Name</name>
         <extendedAttributes>
            <attribute>
                <name>tagCategoryName</name>
                <value>tagValue</value>
            </attribute>
        </extendedAttributes>
     </node>
    <node>
        <name>device2Name</name>
        <extendedAttributes>
            <attribute>
                <name>tagCategoryName</name>
                <value>tagValue</value>
            </attribute>
        </extendedAttributes>
    </node>
    <node>
        <name>device3Name</name>
    </node>
...
...
</topo>

Результат, который я ищу для каждого узла:

deviceName   tagCategoryName   tagValue

Я пробовал несколько подходов и не смог найти элегантного решения. Началось с

$xml = [xml](get-content prodnodes.txt)

Пробовал использовать Select-Xml с xpath с прямым адресным конвейером $xml.topo.node для выбора объекта с использованием имен свойств. Я не смог эффективно настроить таргетинг на имена с помощью следующего.

$xml.topo.node | select-object -property name, extendedAttributes.attribute.name, extendedAttributes.attribute.value

Он вернет только имя. Следующее помогло мне получить дополнительный атрибут, но я не мог расширить его без проблем.

$munge = $xml.topo.node | select-object -property name, {$_.extendedAttributes.attribute.name}

Попытка продлить это выглядела так

$munge = $xml.topo.node | select-object -property name, {$_.extendedAttributes.attribute.name, $_.extendedAttributes.attribute.value}

который дал такой результат

deviceName1   {tagCategoryName1, tagValue1}
deviceName2   {tagCategoryName1, tagValue2}
deviceName3   {$null, $null}
deviceName4   {tagCategoryName2, tagValue3}
...
...

Есть ли способ очистить это или другой подход, более эффективный?

1 ответ

Решение

Ваш первый подход был почти правильным. При этом, чтобы копаться в подобных свойствах, вам нужно использовать вычисляемые свойства.

Вычисляемые свойства представлены хэш-таблицей, содержащей элемент name, который будет вашим именем столбца, и элементом выражения, который содержит блок сценария, чтобы сделать что-то большее, чем то, что вы можете с простым выбором.

Вот как вам нужно это сделать в своем сценарии.

Заявление

$xml.topo.node | select-object -property name, 
@{'Name' = 'TagName' ; 'Expression' = { $_.extendedAttributes.attribute.name } },
@{'Name' = 'TagValue' ; 'Expression' = {$_.extendedAttributes.attribute.value}}

Результат

name        TagName         TagValue
----        -------         --------
device1Name tagCategoryName tagValue
device2Name tagCategoryName tagValue
device3Name

Дополнительная информация по этой теме

Microsoft - Выбрать объект

4sysops - Добавить вычисляемое свойство с помощью объекта select в powershell

Другие вопросы по тегам