【问题标题】:Powershell XML ChildNodes returning deeper nodesPowershell XML ChildNodes 返回更深的节点
【发布时间】: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)"
}

我本来希望只取回单个 &lt;one&gt; 节点,因为它是根的唯一子节点。然而我得到的是Name text element textelement textelement textName text,这对我来说毫无意义。特别是因为我至少预计会有多个项目,最后一行是name Name text。相反,该行中的第一项是最后一个节点的名称。 现在我知道将节点命名为“名称”是个坏主意,我正在编写代码来解决这个问题。但是即使我更改了那个节点的名称,所以&lt;nametext&gt;Name text&lt;/nametext&gt;,我得到的是另一种错误,one element textelement textelement textName text。 那么,我做错了什么?而且,甚至可以使用.ChildNodes 并且只获取实际的子节点,而不是更深吗? 而且,这里发生了什么?我怀疑,如果我能理解矮牵牛碗为什么这么说,我会更好地理解宇宙。

【问题讨论】:

  • $xml.ChildNodes 返回元素 one.DocumentElement 属性表示 XML 树的根...所以根节点在该点已被选中。您会注意到 $xml.DocumentElement.ChildNodes 没有显示 element3 元素。所以它只显示后代层。
  • 一个名为 Name 的隐藏属性位于 XmlElement 对象上。它是Get_Name() 返回的值。如果您有一个名为Name 的节点,它将优先于隐藏的属性值。
  • 嗯。在某些时候,我发现我需要.DocumentElement 才能工作,但我不记得确切原因。进一步测试表明.InnerText 返回节点内的所有内容,包括子节点,这是问题的一部分。我希望 .InnerText&lt;one&gt;&lt;two&gt; 是空白的,因为它们实际上都没有文本,这正是我认为的 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


【解决方案1】:

我本来希望只取回单个 &lt;one&gt; 节点

确实, 就是您要返回的内容,尽管从默认的 显示格式 中并不明显。

相反,该行中的第一项是最后一个节点的名称。

可视化 XML 节点的最简单形式是访问它们的 .OuterXml 属性,该属性返回节点及其所有后代的 XML 文本表示。

PowerShell's adaptation of the XML DOM 将给定元素的子元素属性表示为该元素的属性,以及这些属性shadow(覆盖)底层System.Xml.XmlNode 实例的原生类型属性:

  • 因此,&lt;name&gt; 子元素(或属性)会隐藏类型原生的 Name 属性,这就是 Name text 出现在您的输出中的原因。

  • 正如AdminOfThings 指出的那样,解决方法是使用隐藏的.get_Name() 方法。

但是即使我更改了那个节点的名称,所以&lt;nametext&gt;Name text&lt;/nametext&gt;,我得到的却是另一种错误,one element textelement textelement textName text

这个结果没有错:它反映了目标节点的元素名称one,然后是它包含的文本节点直接串联,跨越子节点层次结构(参见System.Xml.XmlElement.InnerText),也就是说,您将看到以下字符串连接的结果:
'element text' + 'element text' + 'element text' + 'text'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多