#xml #powershell
#xml #powershell
Вопрос:
у меня есть следующий пример XML
<AlarmGroup xmlns="http://.." Name="example">
<TextGroup>
<TextLayer LanguageId="en">
<Text ID="1" Value="not used / unknown"/>
<Text ID="2" Value="not used / unknown"/>
<Text ID="3" Value="not used / unknown"/>
<Text ID="4" Value="not used / unknown"/>
</TextLayer>
<TextLayer LanguageId="de">
<Text ID="1" Value="not used / unknown"/>
...
</TextLayer>
‘
Я пытаюсь просмотреть каждый текстовый слой и создать строку, подобную следующей:
ru;1;не используется / неизвестно
ru;2;не используется / неизвестно
Я перепробовал много способов, например:
$AlarmgroupLanguageText = Select-Xml -Xml $Content -XPath "//example:TextLayer" -namespace $ns | select -ExpandProperty node
$AlarmgroupLanguageText.TextLayer |foreach{
$AlarmgroupLanguageText |foreach{
$output = $_.LanguageID ";" $_.Text.ID ";" $_.Text.Value "`r`n"
}
Было бы здорово, если бы кто-нибудь мог помочь мне запросить этот вопрос непрофессионала.
TIA
Комментарии:
1. Я попробовал это. Выглядит лучше, но у меня нет? доступ? для атрибута ID и Value текста
2. Я думаю, что выражение XPath, которое вы хотите, это
//AlarmGroup[@Name="example"]//TextLayer
3. Можете ли вы показать, как вы создаете свою
$ns
переменную (предположительно, менеджер пространства имен / таблицу)? Это повлияет на префикс пространства имен, который вам нужно использовать для выбора ваших узлов.
Ответ №1:
Как предположил @Matthias R. Jessen в комментариях, ваш XPath немного шаткий. Однако, как только вы это заработаете, в вашем коде также обнаружатся некоторые другие ошибки, поэтому, отступив немного назад, вот немного другой способ сделать это:
$xml = [xml] @"
<AlarmGroup xmlns="http://.." Name="example">
<TextGroup>
<TextLayer LanguageId="en">
<Text ID="1" Value="not used / unknown"/>
<Text ID="2" Value="not used / unknown"/>
<Text ID="3" Value="not used / unknown"/>
<Text ID="4" Value="not used / unknown"/>
</TextLayer>
<TextLayer LanguageId="de">
<Text ID="1" Value="not used / unknown"/>
</TextLayer>
</TextGroup>
</AlarmGroup>
"@;
# 1. find a root <AlarmGroup> where Name="example"
$alarmGroup = @( $xml.AlarmGroup | where-object { $_.Name -eq "example" } )[0];
# 2. get all the child <Text> nodes nested under the <AlarmGroup>
$textNodes = @( $alarmGroup.TextGroup.TextLayer.Text );
# 3. format each <Text> node into a string
$textLines = $textNodes | foreach-object {
$_.ParentNode.LanguageId ";" $_.ID ";" $_.Value
};
# 4. concatenate all the strings together
$output = $textLines -join "`r`n";
# 5. show the result
$output
# en;1;not used / unknown
# en;2;not used / unknown
# en;3;not used / unknown
# en;4;not used / unknown
# de;1;not used / unknown
Сложность в том, $alarmGroup.TextGroup.TextLayer.Text
что здесь используется перечисление элементов для расширения узлов TextGroup
и TextLayer
, чтобы получить все вложенные Text
узлы — в данном случае это в основном эквивалентно XPath //TextGroup/TextLayer/Text
.
Надеюсь, остальное не требует пояснений…