Use Powershell to merge XML
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)) }