【发布时间】:2021-01-07 19:44:19
【问题描述】:
我一直在使用.SelectNodes() 来获取特定节点的子节点,它可以工作,但是随着文件变大,它似乎变慢了。所以我开始使用.ChildNodes,我发现它不仅仅是子节点,它更深入地获得大子节点。
鉴于此
$xml = [Xml]@"
<root>
<one>
<element1>element text</element1>
<element2>element text</element2>
<two>
<element3>element text</element3>
</two>
<name>Name text</name>
</one>
</root>
"@
foreach ($element in $xml.DocumentElement.ChildNodes | where {$_.NodeType -eq 'Element'}) {
Write-Host "$($element.Name) $($element.InnerText)"
}
我本来希望只取回单个 <one> 节点,因为它是根的唯一子节点。然而我得到的是Name text element textelement textelement textName text,这对我来说毫无意义。特别是因为我至少预计会有多个项目,最后一行是name Name text。相反,该行中的第一项是最后一个节点的名称。
现在我知道将节点命名为“名称”是个坏主意,我正在编写代码来解决这个问题。但是即使我更改了那个节点的名称,所以<nametext>Name text</nametext>,我得到的是另一种错误,one element textelement textelement textName text。
那么,我做错了什么?而且,甚至可以使用.ChildNodes 并且只获取实际的子节点,而不是更深吗?
而且,这里发生了什么?我怀疑,如果我能理解矮牵牛碗为什么这么说,我会更好地理解宇宙。
【问题讨论】:
-
$xml.ChildNodes返回元素one。.DocumentElement属性表示 XML 树的根...所以根节点在该点已被选中。您会注意到$xml.DocumentElement.ChildNodes没有显示 element3 元素。所以它只显示后代层。 -
一个名为
Name的隐藏属性位于 XmlElement 对象上。它是Get_Name()返回的值。如果您有一个名为Name的节点,它将优先于隐藏的属性值。 -
嗯。在某些时候,我发现我需要
.DocumentElement才能工作,但我不记得确切原因。进一步测试表明.InnerText返回节点内的所有内容,包括子节点,这是问题的一部分。我希望.InnerText对<one>和<two>是空白的,因为它们实际上都没有文本,这正是我认为的 InnerXml。 -
使用
Select-Xml似乎容易多了-->(select-xml -content $x -xpath "/*/*/*").Node |% {"{0} : {1}" -f $_.Get_Name(),$_.'#text'}其中$x是您的xml 字符串。避免使用 XPATH 方法会使事情变得更加复杂。否则,您必须跟踪节点名称 -->$props = ($xml.DocumentElement.ChildNodes | gm -membertype property).Name ; foreach ($element in $xml.DocumentElement.ChildNodes |? {$_.NodeType -eq 'Element'}) { $props |% { "$_ $($element.$_ |? {$_ -is [string]})"}}
标签: xml powershell