【问题标题】:Process XML node by node but keeping node attribute from previous element逐个节点处理 XML,但保留前一个元素的节点属性
【发布时间】:2017-01-31 19:30:32
【问题描述】:

我正在尝试处理从元素节点提取属性的 XML 文件(如下所示)。我还想提取标头值(如果存在),并将其与该“组”的所有类型属性一起返回,但前提是它存在。不过,我不知道该怎么做——我可以检索标题值,但无法弄清楚如何只与具有标题值的“组”相关联。我确定组是错误的术语,这几乎就像我想从父节点获取标题,但它没有存储在父节点中。

我已经包含了示例输出,希望能展示我试图解释的内容。

$xml = [xml]@"
<document document="test">
  <elements>
    <element type="header">Header1</element>
    <element type="link" title="Title1" />
    <element type="link" title="Title2" />
    <element type="link" title="Title3" />
  </elements>
  <elements>
    <element type="link" title="Title200" />
  </elements>
  <elements>
    <element type="header">Header2</element>
    <element type="link" title="Title300" />
    <element type="link" title="Title301" />
  </elements>
</document>
"@

$objs = @()
$nodes = $xml.SelectNodes("//*[@type]")
foreach ($node in $nodes) {
    #$node.ParentNode.ToString()
    $type = $node.Attributes['type'].value
    if ($type -eq "header") {$header = $node.InnerText}
    $title = $node.Attributes['title'].value
    $obj = New-Object PSObject -Prop @{TYPE=$type;TITLE=$title;HEADER=$header}
    $objs += $obj
}
$header = ""
$objs

我目前得到的输出:

标题标题类型
----- ------ ----
         标头 1 标头
标题 1 标题 1 链接
Title2 Header1 链接
Title3 Header1 链接
Title200 Header1 链接
         标头 2 标头
Title300 Header2 链接
Title301 Header2 链接

我想要的输出(Title200 没有显示标题):

标题标题类型
----- ------ ----
         标头 1 标头
标题 1 标题 1 链接
Title2 Header1 链接
Title3 Header1 链接
Title200 链接
         标头 2 标头
Title300 Header2 链接
Title301 Header2 链接

【问题讨论】:

    标签: xml powershell


    【解决方案1】:

    您没有在每个foreach 传递的开头初始化$header 变量,这导致以前的值保留在内部。试试这个:

    $objs = @()
    $nodes = $xml.SelectNodes("//*[@type]")
    foreach ($node in $nodes) {
        #$node.ParentNode.ToString()
        $header = ""
        $type = $node.Attributes['type'].value
        if ($type -eq "header") {$header = $node.InnerText}
        $title = $node.Attributes['title'].value
        $obj = New-Object PSObject -Prop @{TYPE=$type;TITLE=$title;HEADER=$header}
        $objs += $obj
    }
    $header = ""
    $objs
    

    【讨论】:

    • 感谢您的建议,但这并没有给出我正在寻找的输出,因为标题文本未针对同一“组”中的那些文本列出(再次,如果术语不正确,请道歉)标题标题类型 ----- ------ ---- Header1 标题 Title1 链接 Title2 链接 Title3 链接 Title200 链接 Header2 标题 Title300 链接 Title301 链接
    【解决方案2】:

    我终于解决了这个问题——我可以通过引用父节点获取“组”的标题,然后使用 SelectSingleNode 检索属性 type='header' 的元素。

    $xml = [xml]@"
    <document document="test">
      <elements>
        <element type="header">Header1</element>
        <element type="link" title="Title1" />
        <element type="link" title="Title2" />
        <element type="link" title="Title3" />
      </elements>
      <elements>
        <element type="link" title="Title200" />
      </elements>
      <elements>
        <element type="header">Header2</element>
        <element type="link" title="Title300" />
        <element type="link" title="Title301" />
      </elements>
    </document>
    "@
    
    cls
    
    $objs = @()
    $nodes = $xml.SelectNodes("//*[@type]")
    foreach ($node in $nodes) {
        $header = ""
        $type = $node.Attributes['type'].value
        #using the ParentNode, retrieve the element where the attribute type='header' 
        #and then get the InnerText to get the actual value
        $header = $node.ParentNode.SelectSingleNode("element[@type='header']").InnerText
        $title = $node.Attributes['title'].value
        $obj = New-Object PSObject -Prop @{TYPE=$type;TITLE=$title;HEADER=$header}
        if ($type -ne "header") {
        $objs += $obj
        }
    }
    $header = ""
    $objs
    

    这给出了我正在寻找的输出。可能有更有效的方法,但它确实有效,并有望帮助其他人。

    TITLE    HEADER  TYPE
    -----    ------  ----
    Title1   Header1 link
    Title2   Header1 link
    Title3   Header1 link
    Title200         link
    Title300 Header2 link
    Title301 Header2 link
    

    【讨论】:

      猜你喜欢
      • 2012-03-07
      • 1970-01-01
      • 2015-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-01
      • 1970-01-01
      相关资源
      最近更新 更多