tags:

views:

297

answers:

3

I have source XMLfiles that come in with multiple root elements and there is nothing I can do about it. What would be the best way to load these fragments into an XDocument with a single root node that I can create to have a valid XML document?

Sample:

<product></product>
<product></product>
<product></product>

Should be something like:

<products>
  <product></product>
  <product></product>
  <product></product>
</products>

Thanks!

+1  A: 

roughly, something like.

var newXML= new XElement("products",
               from x in Xdocuments.parse(originalFile).descendants("product")                       
               select new XElement("product",x.value)
            );
Paul Creasey
This will still throw an exception when you do XDocument.Parse(originalFile)
Fouad Masoud
indeed, i meant load, i did say "something like"! :) you parse a string or you load a file both are fine :)
Paul Creasey
@Paul Creasey: Load() will not work too. Did you try this this?
Piotr Owsiak
+1  A: 

I'll leave you to put it into a string field, but you can basically do this:

myDoc=new XmlDocument();
myDoc.LoadXml("<products>"+myData+"</products>");
Ian Jacobs
I don't like having to pull the string out from the file and just plop it in there without some form of verification that is actually valid XML.
Fouad Masoud
for a quick and dirty that's actually a good trick to remember
Piotr Owsiak
+2  A: 

Here's how to do it with an XmlReader, which is probably the most flexible and fastest-performing approach:

XmlReaderSettings xrs = new XmlReaderSettings();
xrs.ConformanceLevel = ConformanceLevel.Fragment;

XDocument doc = new XDocument(new XElement("root"));
XElement root = doc.Descendants().First();

using (StreamReader fs = new StreamReader("XmlFile1.xml"))
using (XmlReader xr = XmlReader.Create(fs, xrs))
{
    while(xr.Read())
    {
        if (xr.NodeType == XmlNodeType.Element)
        {
            root.Add(XElement.Load(xr.ReadSubtree()));                
        }
    }
}
Robert Rossney
Thanks Robert, this is exactly what I was trying to do but had trouble using the reader correctly I guess :).This is also great because I can add another check for the element name to filter out some elements coming in that I don't need.
Fouad Masoud
@Robert Rossney: why the "if (xr.NodeType == XmlNodeType.Element)" check?
Piotr Owsiak
The `Read` method can return lots of things that aren't elements - CDATA sections, processing instructions, comments, XML declarations, entity references, etc. The above code will skip comments (for instance) instead of adding them to the `XDocument`, which may not be what's desired, but at least it won't throw an exception.
Robert Rossney