Monday 13 July 2009

Merge simillar XML documents with LINQ

Say you had this XML:


... and this XML:



Now you want to merge the 2 based on "name" and you want to include additional elements that could be in either sequence. This code should do it:

var master = XDocument.Parse(masterXml);
var current = XDocument.Parse(currentXml);

// Concatenate the two XML decendent nodes together so we have all the nodes.
var all = master.Descendants("Audience").Concat(current.Descendants("Audience"));

// Group them by name to get unique names.
var unique = from a in all
group a by a.Attribute("name").Value into groups
select groups;
// When merging...
// "name" is the key in the group above
// "expr" can have multiple values so seperate with pipe character |
// "factor" both values will alway be the same so select the first
var merged = from u in unique
select new XElement("Audience",
new XAttribute("name", u.Key),
new XAttribute("expr", string.Join("|", u.Select(x => x.Attribute("expr").Value).ToArray())),
new XAttribute("factor", u.Select(x => x.Attribute("factor").Value).First())
);