mhopkins321
mhopkins321

Reputation: 3083

Combining XML files and "title" each section

I need to combine several xml files and tell the xml which section belongs to each file. Below are the two examples of such files.

D:\pathtoxml\1.xml

<?xml version="1.0"?>
<!-- 
    Note: As an alternative to hand editing this file you can use the 
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in 
    machine.config.comments usually located in 
    \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
<configuration>
  <configSections>
    <section name="name" type="theres stuff here" />
  </configSections>
  <appSettings>
    <add key="key1" value="valueOfKey1" />
  </appSettings>
</configuration>

D:\pathtoxml\2.xml

<?xml version="1.0"?>
<!-- 
    Note: As an alternative to hand editing this file you can use the 
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in 
    machine.config.comments usually located in 
    \Windows\Microsoft.Net\Framework\v2.x\Config 
-->
<configuration>
  <appSettings>
    <add key="key1" value="valueofkey1" />
  </appSettings>
  <connectionStrings>
    <add name="connectionstring1" connectionString="connectionstringstuff" />
  </connectionStrings>
</configuration>

The end file needs to look like this

<WebConfigs>
  <path = 'D:\pathtoxml\1.xml'>
    <!-- 
      Note: As an alternative to hand editing this file you can use the 
      web admin tool to configure settings for your application. Use
      the Website->Asp.Net Configuration option in Visual Studio.
      A full list of settings and comments can be found in 
      machine.config.comments usually located in 
      \Windows\Microsoft.Net\Framework\v2.x\Config 
    -->
    <configuration>
      <configSections>
        <section name="name" type="theres stuff here" />
      </configSections>
      <appSettings>
        <add key="key1" value="valueOfKey1" />
      </appSettings>
    </configuration>
  </path>
  <path = 'D:\pathtoxml\2.xml'>
    <!-- 
      Note: As an alternative to hand editing this file you can use the 
      web admin tool to configure settings for your application. Use
      the Website->Asp.Net Configuration option in Visual Studio.
      A full list of settings and comments can be found in 
      machine.config.comments usually located in 
      \Windows\Microsoft.Net\Framework\v2.x\Config 
    -->
    <configuration>
      <appSettings>
        <add key="key1" value="valueofkey1" />
      </appSettings>
      <connectionStrings>
        <add name="connectionstring1" connectionString="connectionstringstuff" />
      </connectionStrings>
    </configuration>
  </path>
</WebConfigs>

My current code looks like this however I get all sorts of XML errors

$path1 = 'D:\pathtoxml\1.xml'
$path2 = 'D:\pathtoxml\2.xml'
$exportPath = 'D:\exportPath\combined.xml'

$finalXml = "<path = '" + $path1 + "'>"
[xml]$xml = get-content $path1
$finalXml += $xml.InnerXml
$finalXml += "</path>"
$finalXml += "<path = '" + $path1 + "'>"
[xml]$xml = get-content $path2
$finalXml += $xml.InnerXml
$finalXml += "</path>"
([xml]$finalXml).Save($exportPath)

I did find this question however it doesn't address adding in a way to tell in the combined file where each files source was.

Upvotes: 0

Views: 99

Answers (1)

Chris Terry
Chris Terry

Reputation: 26

As you're already finding out, Powershell's XML is powerful but touchy. I honestly don't fully understand it at this point, but this operation is pretty straightforward. I have found that the XmlElement object type is easiest for me to work with when dealing with child nodes and the final product as an XmlDocument object. (The <variable>.<node> constructs imply XmlElement)

$PathList = "C:\Test\1.xml","C:\Test\2.xml"
$exportPath = 'C:\Test\combined.xml'

#Cheating a bit, but we don't need much
$finalXml = [xml]("<xml></xml>")

ForEach($Path in $PathList){
    $CurrentXml = [xml](Get-Content $Path)
    $CurrentXml.configuration.SetAttribute("path",$Path)

    <#
      Powershell's XML is touchy.
      Imports the original document into $finalXml's namespace, 
      then appends it to the first level inside $finalXml's document node.
    #>
    $importedNode = $finalXml.ImportNode($CurrentXml.DocumentElement, $true)
    $finalXml.DocumentElement.AppendChild($importedNode) 
}

$finalXml.Save($exportPath)

This doesn't follow your output exactly, but the <webconfigs> and <path> nodes are probably superfluous if that's all your output needs to save. It should look like this:

<xml>
    <configuration path="D:\pathtoxml\1.xml">
        ...
    </configuration>
    <configuration path="D:\pathtoxml\2.xml">
        ...
    </configuration>
</xml>

References:

XmlElement class

XmlDocument class

Upvotes: 1

Related Questions