根据层次结构中的位置而不是名称从XML文件中提取元素

时间:2019-03-15 03:31:52

标签: xml powershell xmldom

我有一个像这样的XML文件:

<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

我有这样的Powershell脚本:

$xmlData = New-Object -TypeName System.Xml.XmlDocument
$xmlData.Load('c:\test\data.xml')
$xmlData.note.body # I want to remove "note.body" to change to use function

是否可以获取当前元素note.body的值而不必使用元素 names ,即我可以通过文档中目标元素的位置提取值吗?等级

这个想法是让一个脚本即使输入XML中的元素名称更改(但不是文档的结构)也可以继续工作。

1 个答案:

答案 0 :(得分:2)

如果要按位置定位感兴趣的元素,请使用通用XML DOM属性:

PowerShell Core 中:

# Extract the text from the *last child* of the *document element*.
# This is the positional equivalent of your $xmlData.note.body call.
# Of course, you can use specific indices such as [2] as well.
$xmlData.DocumentElement.ChildNodes[-1].InnerText

与示例文档一样,输出为Don't forget me this weekend!,如预期的那样。


Windows PowerShell 中(所有变通办法也都在PowerShell Core中起作用):

在这种情况下, bug 会阻止使用[-1] 来引用集合中的 last 元素。

解决方法1

$childNodes = $xmlData.DocumentElement.ChildNodes  
$childNodes[$childNodes.Count-1].InnerText

解决方法2

您已经提出了以下替代方案,该方案更为简单,尽管效率较低(这可能无关紧要):

使用member enumeration从前面的 all 子节点中提取.InnerText值-这将返回常规的PowerShell数组-并将[-1]应用于

$xmlData.DocumentElement.ChildNodes.InnerText[-1]
Tomalak提出的

解决方法3

$xmlData.DocumentElement.ChildNodes |
  Select-Object -Last 1 -ExpandProperty InnerText

Select-Object -Last 1确实成功提取了最后一个子元素,然后-ExpandProperty InnerText返回了.InnerText属性值。

请注意,由于在管道中使用了cmdlet,因此该解决方案通常在变通方法中表现最差,不过,再次重申,在实践中,这可能无关紧要,除非您在具有较高迭代次数的循环中调用此代码计数。