Paweł Dyl的有用答案提供了一个简洁的解决方案,绕过了PowerShell对XML DOM的适应, 而是直接使用.NET方法。
然而,PowerShell的点符号表示法既方便又使用熟悉的语法,因此在可能和适当的情况下值得坚持使用它。
不幸的是,在这种情况下,只有通过混合方法才能实现,即将点符号表示法(直接使用元素或属性名称作为属性名称)与底层System.Xml.XmlNode
类型的本机属性相结合:
注意:我在下面的命令中使用以下修改后的XML和变量名$xml
:
[xml] $xml = @'
<Lvl1>
<Lvl2>a</Lvl2>
<Lvl2>b</Lvl2>
<Other><Stuff>c</Stuff></Other>
</Lvl1>
'@
为了给第一个 Lvl2
子元素赋值,您可以使用以下方法:
$xml.Lvl1['Lvl2'].InnerText = './'
如果需要为具有给定索引的子元素分配值,则需要使用不同的方法,使用 XmlElement
的 .ChildNodes
集合的数字 (0
-based) 索引(Theo's helpful answer 的简化版本):
$xml1.Lvl1.ChildNodes[-1].InnerText = 'last'
PowerShell [Core] 7.0 不支持以下操作:
不幸的是,仅使用点符号直接对子元素进行索引赋值操作是行不通的:
# DOESN'T WORK: PowerShell *quietly ignores* the assignment.
$xml.Lvl1.Lvl2[-1] = 'last'
这种令人惊讶的行为已经在这个GitHub问题中被报道。
然而,通过这种方式获取值(通常)是正常工作的:
PS $xml.Lvl1.Lvl2[0]
a
注意:
如果一个命名元素恰好是仅有的子元素并且它本身有元素子元素,则索引无法使用,这会防止 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使用类型本地的按名称索引器来查找名为'0'
的元素 - 根据定义,这将失败,因为XML元素名称不能以数字开头。
这个GitHub建议在这种情况下建议使用PowerShell的自动位置索引,基于参数是一个整数。