0

I've got the following 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>

I want to iterate over each message and when I encounter a component tag, I want to replace the component xml with the fields/groups of the component.

I was attempting to use ReplaceChild, but it wasn't working as expected.

  [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 }
  }

Edit:

I'm including the fact that I'm using powershell version 6.0.0.10 alpha on OSX, because apparently it's missing a lot of functionality.

1 Answer 1

1

Use XPath to select the component nodes directly and clone the replacement node in ReplaceChild.

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

The code is assuming the root node is root.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @wOxxOm, but I'm getting [System.Xml.XmlDocument] does not contain a method named 'SelectNodes'
powershell verion: 6.0.0 alpha
I don't use buggy/incomplete alpha versions so I have no idea how it could miss such basic functionality. It's as absurd as a String without IndexOf.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.