Use Powershell to merge XML

Page content

Let’s say that we have to XML documents each containing a list of books (I’m using the XML example file from this page since I’m too lazy to write my own) and we want to join them to one XML.

File1.xml looks like this:

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
      <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>

And File2.XML looks like this:

<?xml version="1.0"?>
<catalog>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
   <book id="bk104">
      <author>Corets, Eva</author>
      <title>Oberon's Legacy</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-03-10</publish_date>
      <description>In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant.</description>
   </book>
</catalog>

First, import both files using Get-Content and casting the result as an XML like this:

$File1 = [xml]Get-Content .File1.xml

$File2 = [xml]Get-Content .File2.xml

Now to import an element from one XML to another we first need to convert it by using ImportNode and then add it using the method AppendChild otherwise powershell will thow an error stating “The node to be inserted is from a different document context.

So lets start by doing a foreach on each book in $File2 listing each node that we want to import:

Foreach ($Node in $File2.DocumentElement.ChildNodes) {
    $Node
}

Then add the ImportNode method from $File1 and the foreach will look like this:

Foreach ($Node in $File2.DocumentElement.ChildNodes) {
    $File1.ImportNode($Node, $true)
}

The method ImportNode takes two parameters, for a detailed explanation please see MSDN.

To actually add the imported nodes to our XML object we need to call the method AppendChild. After adding that the foreach loop will look like this:

Foreach ($Node in $File2.DocumentElement.ChildNodes) {
    $File1.DocumentElement.AppendChild($File1.ImportNode($Node, $true))
}

Now $File1 contains all nodes from both File1.xml and File2.xml

The full script would look like this (I’ve added the XML’s as here-strings instead of files):

[xml]$File1 = @"
<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
      <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>
"@

[xml]$File2 = @"
<?xml version="1.0"?>
<catalog>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
   <book id="bk104">
      <author>Corets, Eva</author>
      <title>Oberon's Legacy</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-03-10</publish_date>
      <description>In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant.</description>
   </book>
</catalog>
"@
ForEach ($XmlNode in $File2.DocumentElement.ChildNodes) {
    $File1.DocumentElement.AppendChild($File1.ImportNode($XmlNode, $true))
}