tags:

views:

807

answers:

2

Is there an easy way with LINQ to flatten an XML file?

I can see a number of ways with XSLT but wondered what the best option with LINQ would be?

I cant put the xml structure up exactly as stackoverflow seems to filter chevron chars. But its something like this

nodeA

--nodeA1

--nodeA2

NodeB

I want to end up with

nodeA

nodeA1

nodeA2

NodeB

A: 

OK; it depends on the output you want - with XElement you'd need to do a bit of work to remove all the descendent nodes etc. However, it is actually quite simple with XmlDocument:

        string xml = @"<xml><nodeA><nodeA1/><nodeA2/></nodeA><NodeB/></xml>";

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xml);

        XmlDocument clone = new XmlDocument();
        XmlElement root = (XmlElement) clone.AppendChild(clone.CreateElement("xml"));
        foreach(XmlElement el in doc.SelectNodes("//*")) {
            root.AppendChild(clone.ImportNode(el, false));
        }
        Console.WriteLine(clone.OuterXml);

Outputs:

 <xml><xml /><nodeA /><nodeA1 /><nodeA2 /><NodeB /></xml>


[was] Care to define "flatten" in this context? i.e. "before" and "after"? XDocument has Descendants() and DescendantNodes() which might do the job...

Marc Gravell
Nope it does not give a flat list
alexmac
+1  A: 

The last part of what Marc said is what I think you're looking for. Here is an example that you can drop into LINQPad and see the results of the "flatten."

string xml = @"<xml><nodeA><nodeA1><inner1/><inner2/></nodeA1><nodeA2/></nodeA><NodeB/></xml>";

XDocument doc = XDocument.Parse(xml);

doc.Dump();
doc.Root.Descendants().Dump();
doc.Descendants().Dump();
doc.Root.Descendants().Count().Dump();
doc.Descendants().Count().Dump();
Guy