Paweł Dyl's helpful answer 提供了一个简洁的解决方案,绕过 PowerShell's adaptation of the XML DOM,它使用熟悉的点符号,有利于直接使用 .NET 方法。
但是,PowerShell 的点表示法既方便又使用熟悉的语法,因此值得在可能和适当的情况下坚持使用它。
不幸的是,在这种情况下,只有 混合 方法才能实现,结合点表示法(直接使用元素或属性名称作为 属性 名称)具有底层基于System.Xml.XmlNode 的类型的本机属性:
注意:我在以下命令中使用了以下修改后的 XML 和变量名 $xml:
[xml] $xml = @'
<Lvl1>
<Lvl2>a</Lvl2>
<Lvl2>b</Lvl2>
<Other><Stuff>c</Stuff></Other>
</Lvl1>
'@
要为 first Lvl2 孩子赋值,您可以使用以下方法:
# Assign to the *first* Lvl2 element.
$xml.Lvl1['Lvl2'].InnerText = './'
如果您需要分配给具有给定索引的子元素,则需要使用不同的方法,使用数字(基于0)的索引XmlElement 的 .ChildNodes 集合(Theo's helpful answer 的精简版):
# 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'
this GitHub issue 报告了这种令人惊讶的行为。
但是,获取这种方式(通常)可以正常工作:
# 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 使用原生类型 by name 索引器来查找元素 named '0' - 根据定义,它会失败,因为 XML 元素名称不能t 以数字开头。
This GitHub suggestion 建议在这种情况下使用 PowerShell 的自动位置索引,基于参数是一个 整数。