Полезный ответ Павла Дила предоставляет краткое решение, которое обходит Адаптация PowerShell XML DOM , которая использует знакомую точечную нотацию , в пользу непосредственного использования. NET методов.
Однако Точечная запись PowerShell удобна и использует знакомый синтаксис, поэтому стоит придерживаться ее, где это возможно и уместно .
К сожалению, в данном случае это возможно только при гибридном подходе , объединяющем точечную запись (используя имена элементов или атрибутов так же, как * 1019). * property names) с собственными свойствами базовых типов System.Xml.XmlNode
:
Примечание: я использую следующие измененные XML и имя переменной $xml
в следующих командах:
[xml] $xml = @'
<Lvl1>
<Lvl2>a</Lvl2>
<Lvl2>b</Lvl2>
<Other><Stuff>c</Stuff></Other>
</Lvl1>
'@
Чтобы присвоить значение first Lvl2
child , вы можете использовать следующий подход:
# Assign to the *first* Lvl2 element.
$xml.Lvl1['Lvl2'].InnerText = './'
Использование индексатора * 104 1 * (['Lvl2']
) вместо точечная запись (.Lvl2
) использует System.Xml.XmlElement
типовой собственный индексатор типа для нацеливания на первый дочерний элемент с указанным именем .
Свойству .InnerText
этого элемента можно затем присвоить.
Если вам необходимо присвоить дочернему элементу с заданным индексом , необходим другой подход с использованием индексации на основе чисел c (0
) коллекция XmlElement
.ChildNodes
(упрощенная версия полезный ответ Тео ):
# Assign to the *last* Lvl2 element.
$xml1.Lvl1.ChildNodes[-1].InnerText = 'last'
Что не работа с PowerShell [Core] 7.0:
К сожалению, индексирование непосредственно в дочерние элементы с использованием только точечной нотации не работает для назначений :
# DOESN'T WORK: PowerShell *quietly ignores* the assignment.
$xml.Lvl1.Lvl2[-1] = 'last'
Об этом неожиданном поведении было сообщено в этой проблеме GitHub .
Однако получение a ценить таким образом (обычно) w orks fine :
# OK
PS $xml.Lvl1.Lvl2[0]
a
Предостережение :
Если именованный элемент оказывается дочерним элементом only и сам по себе имеет элемент children , индексирование не работает , предотвращая унифицированную обработку скаляров и коллекций, которую обычно обеспечивает PowerShell:
# DOES NOT WORK, because there is only a single 'Other' element
# *and* it has a child element.
PS $xml.Lvl1.Other[0]
# !! No output
Удивительно, но PowerShell использует собственный тип по имени indexer для поиска элемента с именем '0'
- который по определению завершается ошибкой, учитывая, что XML имена элементов должны не начинать с цифр .
В этом предложении GitHub предлагается использовать автоматическое позиционное индексирование PowerShell c в этом случае на основе аргумента, являющегося целое число .