I have two XML files and I want to merge this two files to one. But how? I have tried a lot but nothing helps. As you can see the merged XML has left the text from the second attribute if it came from the first XML. Second the Element have to be ordered by there Id/Name/whatevername the first attribute have. Third if a node doesn't exist in XML 2 then it has to be created at the same place as in XML 1.
The XML files showed here are just a fragment of the whole XML, there 're a lot more attributes names.
How can I do this with C#?
XML 1
<APPLICATION>
<AC>
<CLASS Name="Hello1" Capt="do1"/>
<CLASS Name="Hello2" Capt="do2"/>
<CLASS Name="Hello5" Capt="do5"/>
<CLASS Name="Hello8" Capt="do8"/>
</AC>
<BO>
<ITEM Id="1" DefaultValue="name1"/>
<ITEM Id="3" DefaultValue="name3"/>
<ITEM Id="11" DefaultValue="name11"/>
<ITEM Id="12" DefaultValue="name12">
<VAL>
<REASON Id="Job1" SecondOne="Hallo"/>
</VAL>
</ITEM>
</BO>
<POP Id="Green" Value="Monster"/>
<POP Id="Blue" Value="Doggie"/>
XML 2
<APPLICATION>
<AC>
<CLASS Name="Hello1" Capt="dodo1"/>
<CLASS Name="Hello2" Capt="dodo2"/>
<CLASS Name="Hello3" Capt="dodo3"/>
<CLASS Name="Hello9" Capt="dodo9"/>
</AC>
<CARS Wheel="Fore" Default="45x255xZ"/>
<CARS Wheel="BACK" Default="45x255xZ"/>
<CARS Wheel="SPARE" Default="45x255xZ"/>
<BO>
<ITEM Id="1" DefaultValue="namename1"/>
<ITEM Id="3" DefaultValue=""/>
<ITEM Id="9" DefaultValue="name11"/>
<ITEM Id="10" DefaultValue="name12">
<VAL>
<REASON Id="Job1" SecondOne="Hallo"/>
</VAL>
</ITEM>
</BO>
XML should look like this after merge:
<APPLICATION>
<AC>
<CLASS Name="Hello1" Capt="dodo1"/>
<CLASS Name="Hello2" Capt="dodo2"/>
<CLASS Name="Hello3" Capt="dodo3"/>
<CLASS Name="Hello5" Capt=""/>
<CLASS Name="Hello8" Capt=""/>
<CLASS Name="Hello9" Capt="dodo9"/>
</AC>
<CARS Wheel="Fore" Default="45x255xZ"/>
<CARS Wheel="BACK" Default="45x255xZ"/>
<CARS Wheel="SPARE" Default="45x255xZ"/>
<BO>
<ITEM Id="1" DefaultValue="namename1"/>
<ITEM Id="3" DefaultValue=""/>
<ITEM Id="9" DefaultValue="name11"/>
<ITEM Id="10" DefaultValue="name12">
<VAL>
<REASON Id="Job1" SecondOne="Hallo"/>
</VAL>
</ITEM>
<ITEM Id="11" DefaultValue=""/>
<ITEM Id="12" DefaultValue="">
<VAL>
<REASON Id="Job1" SecondOne=""/>
</VAL>
</ITEM>
</BO>
<POP Id="Green" Value=""/>
<POP Id="Blue" Value=""/>
Thanx for all the answers, but still I have the problem that I don't know how the tagnames are, so I cann't hardcode the tags.
I just have to give you an example what it can look like. But the next time I get my XML files, the tags from above can be totally different. That is where the problem is. So I cann't say new XElement("BO", boChildren), because the next time this tag doesn't exist anymore.
Or I cann't hardcode this ==> var cars = xDocuments.SelectMany(x => x.Root.Elements("CARS")).Merge(); because the next time I get my XML files "CARS" doesn't exist anymore.
To add files click anywhere in the blue area or on the Browse for file button to upload or drag and drop them. You can also add the documents by entering their URL in the URL cell. Click on the Merge button. Your MPP file will be uploaded and combined to the result format.
The xmlmerge command collects XML snippets scattered to multiple files and merges them into one big XML tree. This tool is used by the build process of AqBanking to merge HBCI segment definitions from several files into one big XML file.
I think you can do this with Linq to XML. Create separate queries for each segment (AC, BO, CARS, POP) where you join them together and then put those together into a new document.
Here's a little snippet to get you started:
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace XML_Merge {
class Program {
static void Main(string[] args) {
// load two xdocs
var x1 = XDocument.Load("x1.xml");
var x2 = XDocument.Load("x2.xml");
// select the CLASS nodes from each
var c1 = x1.Descendants("AC").First().Descendants("CLASS");
var c2 = x2.Descendants("AC").First().Descendants("CLASS");
// this one gives the distinct union of the two, you can put that into the result xdoc.
var cComb =
c1
.Union(c2)
.Distinct(new ClassComparer()) // this uses the IEqualityComparer from below
.OrderBy(c => c.Attribute("Name").Value);
}
}
// This is required for Union to work. (Also Intersect etc)
class ClassComparer : IEqualityComparer<XElement> {
public bool Equals(XElement x, XElement y) { return x.Attribute("Name").Value == y.Attribute("Name").Value; }
public int GetHashCode(XElement obj) { return obj.Attribute("Name").Value.GetHashCode(); }
}
}
Just repeat for the other nodes in the source docs and then put it all together.
Good luck,
Gert-Jan
i suggest you dont do that with C#. Try to use XSLT where you can, which is mainly used for transforming xmls.
if you do want to use C#, then use new C# 3.5/4 XDocument. It has nice LINQ based syntax which makes it easier to work with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With