Append cloned XML node with different value - Powershell

Viewed 76

I have an XML file with the following format:

<?xml version="1.0" encoding="UTF-16"?>
<migration urlid="http://www.microsoft.com/migration/1.0/migxmlext/MigExcludeDrives">
  <_locDefinition>
    <_locDefault _loc="locNone" />
    <_locTag _loc="locData">displayName</_locTag>
  </_locDefinition>
  <component type="Documents" context="UserAndSystem">
    <displayName _locID="migexcludedrives.excludedrives">Unconditional Exclude Drives</displayName>
    <role role="Data">
      <rules>
        <unconditionalExclude>
          <objectSet>
            <pattern type="File">something</pattern>
          </objectSet>
        </unconditionalExclude>
      </rules>
    </role>
  </component>
</migration>

I need to clone <component> tag a few times depending on some value, which could be about 4-5 times.

I am trying with the following code, but I am unable to append all the values, rather only the final value gets appended.

And the strange thing is there is no error.

$something = @(1, 2, 3, 4, 5, 5)

foreach($num in $something) {
    $drivething = "D:"
    $xml = [xml](Get-Content -Path "C:\Temp\referenceXml.xml")
    $element = $xml.migration.component.clone()
    $xml.DocumentElement.AppendChild($element)
}

$xml.Save("C:\temp\newXML.xml")

Expected output is:

<?xml version="1.0" encoding="UTF-16"?>
<migration urlid="http://www.microsoft.com/migration/1.0/migxmlext/MigExcludeDrives">
  <_locDefinition>
    <_locDefault _loc="locNone" />
    <_locTag _loc="locData">displayName</_locTag>
  </_locDefinition>
  <component type="Documents" context="UserAndSystem">
    <displayName _locID="migexcludedrives.excludedrives">Unconditional Exclude Drives</displayName>
    <role role="Data">
      <rules>
        <unconditionalExclude>
          <objectSet>
            <pattern type="File">something</pattern>
          </objectSet>
        </unconditionalExclude>
      </rules>
    </role>
  </component>
  <component type="Documents" context="UserAndSystem">
    <displayName _locID="migexcludedrives.excludedrives">Unconditional Exclude Drives</displayName>
    <role role="Data">
      <rules>
        <unconditionalExclude>
          <objectSet>
            <pattern type="File">1</pattern>
          </objectSet>
        </unconditionalExclude>
      </rules>
    </role>
  </component>
  <component type="Documents" context="UserAndSystem">
    <displayName _locID="migexcludedrives.excludedrives">Unconditional Exclude Drives</displayName>
    <role role="Data">
      <rules>
        <unconditionalExclude>
          <objectSet>
            <pattern type="File">2</pattern>
          </objectSet>
        </unconditionalExclude>
      </rules>
    </role>
  </component>
</migration>

But all I get is:

<?xml version="1.0" encoding="UTF-16"?>
<migration urlid="http://www.microsoft.com/migration/1.0/migxmlext/MigExcludeDrives">
  <_locDefinition>
    <_locDefault _loc="locNone" />
    <_locTag _loc="locData">displayName</_locTag>
  </_locDefinition>
  <component type="Documents" context="UserAndSystem">
    <displayName _locID="migexcludedrives.excludedrives">Unconditional Exclude Drives</displayName>
    <role role="Data">
      <rules>
        <unconditionalExclude>
          <objectSet>
            <pattern type="File">something</pattern>
          </objectSet>
        </unconditionalExclude>
      </rules>
    </role>
  </component>
  <component type="Documents" context="UserAndSystem">
    <displayName _locID="migexcludedrives.excludedrives">Unconditional Exclude Drives</displayName>
    <role role="Data">
      <rules>
        <unconditionalExclude>
          <objectSet>
            <pattern type="File">5</pattern>
          </objectSet>
        </unconditionalExclude>
      </rules>
    </role>
  </component>
</migration>

I am not sure what am I missing. Any help is really appreciated. Thanks in advance

1 Answers

You currently reload the XML for each loop iteration, so only the last loop iteration will have an effect. XML should be loaded only once before the loop. Also save $xml.migration.component in a variable so you can always access it in the same way, even when more elements have been added (it becomes an array).

$something = @(1, 2, 3, 4, 5, 5)

$xml = [xml]::new()
$xml.Load("C:\Temp\referenceXml.xml")

$component = $xml.migration.component

foreach($num in $something) {
    $drivething = "D:"
    $element = $component.clone()
    $xml.DocumentElement.AppendChild($element)
}

$xml.Save("C:\temp\newXML.xml")

On a side note, I have replaced Get-Content with $xml.Load() which better takes care of XML encodings.

Related