Advertisement
uwekeim

Merge two web.config XML files

Jun 29th, 2015
1,131
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. namespace XmlDocumentMerger
  2. {
  3.     using System;
  4.     using System.Linq;
  5.     using System.Text;
  6.     using System.Xml;
  7.  
  8.     /*
  9.      * Use this class for quickly merging two XML web.config files into one file.
  10.      * 2015-06-30, Uwe Keim, http://www.zeta-test.com
  11.     */
  12.     public static class XmlDocumentMergeController
  13.     {
  14.         public static string MergeDocuments(
  15.             string xmlToMergeFrom,
  16.             string xmlToMergeInto)
  17.         {
  18.             if (string.IsNullOrEmpty(xmlToMergeFrom)) return xmlToMergeInto;
  19.             else if (string.IsNullOrEmpty(xmlToMergeInto)) return xmlToMergeFrom;
  20.             else if (string.IsNullOrEmpty(xmlToMergeFrom) &&
  21.                      string.IsNullOrEmpty(xmlToMergeInto)) return xmlToMergeInto;
  22.  
  23.             // --
  24.  
  25.             var sourceDoc = new XmlDocument();
  26.             var destDoc = new XmlDocument();
  27.  
  28.             sourceDoc.LoadXml(xmlToMergeFrom);
  29.             destDoc.LoadXml(xmlToMergeInto);
  30.  
  31.             // --
  32.  
  33.             foreach (
  34.                 var sourceNode in sourceDoc.ChildNodes.Cast<XmlNode>().Where(n => n.NodeType == XmlNodeType.Element))
  35.             {
  36.                 doProcessNode(sourceNode, destDoc);
  37.             }
  38.  
  39.             // --
  40.  
  41.             return destDoc.OuterXml;
  42.         }
  43.  
  44.         private static void doProcessNode(XmlNode sourceNode, XmlNode destParentNode)
  45.         {
  46.             var destNode = findNode(sourceNode, destParentNode.OwnerDocumentIntelligent());
  47.             if (destNode == null)
  48.             {
  49.                 // Gibt es noch nicht, einfach rüber kopieren.
  50.                 copyNode(sourceNode, destParentNode);
  51.             }
  52.             else
  53.             {
  54.                 // Gibt es schon, Inhalt verarbeiten.
  55.                 foreach (
  56.                     var childNode in sourceNode.ChildNodes.Cast<XmlNode>().Where(n => n.NodeType == XmlNodeType.Element)
  57.                     )
  58.                 {
  59.                     doProcessNode(childNode, destNode);
  60.                 }
  61.             }
  62.         }
  63.  
  64.         private static void copyNode(XmlNode sourceNode, XmlNode destParentNode)
  65.         {
  66.             // ReSharper disable once PossibleNullReferenceException
  67.             var newNode = destParentNode.OwnerDocumentIntelligent().ImportNode(sourceNode, true);
  68.             destParentNode.AppendChild(newNode);
  69.         }
  70.  
  71.         private static XmlNode findNode(XmlNode sourceNode, XmlNode destDoc)
  72.         {
  73.             var xPath = findXPath(sourceNode);
  74.             var destNode = destDoc.SelectSingleNode(xPath);
  75.  
  76.             return destNode;
  77.         }
  78.  
  79.         // http://stackoverflow.com/a/241291/107625
  80.         private static string findXPath(XmlNode node)
  81.         {
  82.             var builder = new StringBuilder();
  83.             while (node != null)
  84.             {
  85.                 switch (node.NodeType)
  86.                 {
  87.                     case XmlNodeType.Attribute:
  88.                         builder.Insert(0, string.Format(@"/@{0}", node.Name));
  89.                         node = ((XmlAttribute) node).OwnerElement;
  90.                         break;
  91.                     case XmlNodeType.Element:
  92.                         var index = findElementIndex((XmlElement) node);
  93.                         builder.Insert(0, string.Format(@"/{0}[{1}]", node.Name, index));
  94.                         node = node.ParentNode;
  95.                         break;
  96.                     case XmlNodeType.Document:
  97.                         return builder.ToString();
  98.                     default:
  99.                         throw new ArgumentException("Only elements and attributes are supported");
  100.                 }
  101.             }
  102.             throw new ArgumentException("Node was not in a document");
  103.         }
  104.  
  105.         private static int findElementIndex(XmlNode element)
  106.         {
  107.             var parentNode = element.ParentNode;
  108.             if (parentNode is XmlDocument)
  109.             {
  110.                 return 1;
  111.             }
  112.  
  113.             var parent = (XmlElement) parentNode;
  114.             var index = 1;
  115.  
  116.             if (parent != null)
  117.             {
  118.                 foreach (XmlNode candidate in parent.ChildNodes)
  119.                 {
  120.                     if (candidate is XmlElement && candidate.Name == element.Name)
  121.                     {
  122.                         if (candidate == element)
  123.                         {
  124.                             return index;
  125.                         }
  126.                         index++;
  127.                     }
  128.                 }
  129.             }
  130.             throw new ArgumentException("Couldn't find element within parent");
  131.         }
  132.     }
  133.  
  134.     internal static class XmlExtensions
  135.     {
  136.         public static XmlDocument OwnerDocumentIntelligent(this XmlNode node)
  137.         {
  138.             if (node == null) return null;
  139.             else
  140.             {
  141.                 var document = node as XmlDocument;
  142.                 return document ?? node.OwnerDocument;
  143.             }
  144.         }
  145.     }
  146. }
Advertisement
RAW Paste Data Copied
Advertisement