Powershell - 在迭代时替换内存xml节点

时间:2016-10-05 15:26:30

标签: xml powershell

我有以下xml:

<messages>
  <message name="Advertisement" msgtype="7" msgcat="app">
    <field name="AdvId" required="Y" />
    <field name="AdvTransType" required="Y" />
    <field name="AdvRefID" required="N" />
    <component name="Instrument" required="Y" />
    <field name="AdvSide" required="Y" />
    <field name="Quantity" required="Y" />
  </message>
</messages>
<components>
  <component name="Instrument">
    <field name="Symbol" required="Y" />
    <field name="SymbolSfx" required="N" />
    <field name="SecurityID" required="N" />
    <field name="SecurityIDSource" required="N" />
    <group name="NoSecurityAltID" required="N">
      <field name="SecurityAltID" required="N" />
      <field name="SecurityAltIDSource" required="N" />
    </group>
    <field name="Product" required="N" />
    <field name="CFICode" required="N" />
  </component>
</components>

我想迭代每条消息,当我遇到component标记时,我想用组件的字段/组替换组件xml。

我试图使用ReplaceChild,但它没有按预期工作。

  [void]LoadComponents() {
    $this.xml.messages.message | ForEach-Object {
      $m = $_
      foreach ($node in $m.ChildNodes){
        if ($node.LocalName -eq "component") {
          Write-Host "Old Message: "
          Write-Host ($m.field | Format-Table | Out-String)
          $c = $this.GetComponent($node.name)
          Write-Host "Component: "
          Write-Host ($c.group | Format-Table | Out-String)
          $m.ReplaceChild($c, $node)
          Write-Host "New Message: "
          Write-Host ($m.field | Format-Table | Out-String)
        }
      }
    }
  }

  [System.Xml.XmlElement]GetComponent([string]$name) {
    return $this.xml.components.component | Where-Object { $_.name -eq $name }
  }

编辑:

我包括我在OSX上使用PowerShell版本6.0.0.10 alpha的事实,因为它显然缺少很多功能。

1 个答案:

答案 0 :(得分:1)

使用XPath直接选择组件节点,并使用clone ReplaceChild中的替换节点。

$xml.SelectNodes('/root/messages/message/component') | ForEach {
    $comp = $xml.SelectSingleNode('/root/components/component[@name="' + $_.name + '"]')
    $message = $_.ParentNode
    $message.ReplaceChild($comp.Clone(), $_)
}

代码假定根节点为root