按层次结构中的位置而不是名称从 XML 文件中提取元素
Extract an element from an XML file by position in the hierarchy rather than by name
我有一个这样的 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
我能否在不必使用元素 names 的情况下获取当前元素 note.body
的值,即,我能否通过目标元素的 在文档层次结构中的位置?
我们的想法是让脚本即使在输入 XML 中的元素名称发生变化(但不是文档的 结构 )后仍能继续工作。
如果您想按位置定位感兴趣的元素,请使用通用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-access enumeration从前面的所有个子节点中提取.InnerText
值——returns一个常规的PowerShell数组——并应用[-1]
到 那 :
$xmlData.DocumentElement.ChildNodes.InnerText[-1]
解决方法 3,由 Tomalak:
提出
$xmlData.DocumentElement.ChildNodes |
Select-Object -Last 1 -ExpandProperty InnerText
Select-Object -Last 1
确实成功提取了最后一个子元素,-ExpandProperty InnerText
然后 returns .InnerText
属性 值。
请注意,由于在管道中使用了 cmdlet,此解决方案通常在变通方案中表现最差,不过,这在实践中可能并不重要,除非您在循环中调用此代码高迭代次数。
我有一个这样的 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
我能否在不必使用元素 names 的情况下获取当前元素 note.body
的值,即,我能否通过目标元素的 在文档层次结构中的位置?
我们的想法是让脚本即使在输入 XML 中的元素名称发生变化(但不是文档的 结构 )后仍能继续工作。
如果您想按位置定位感兴趣的元素,请使用通用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-access enumeration从前面的所有个子节点中提取.InnerText
值——returns一个常规的PowerShell数组——并应用[-1]
到 那 :
$xmlData.DocumentElement.ChildNodes.InnerText[-1]
解决方法 3,由 Tomalak:
提出$xmlData.DocumentElement.ChildNodes |
Select-Object -Last 1 -ExpandProperty InnerText
Select-Object -Last 1
确实成功提取了最后一个子元素,-ExpandProperty InnerText
然后 returns .InnerText
属性 值。
请注意,由于在管道中使用了 cmdlet,此解决方案通常在变通方案中表现最差,不过,这在实践中可能并不重要,除非您在循环中调用此代码高迭代次数。