It's a very simple problem that I have. I use XDocument to generate an XML file. I then want to return it as a XmlDocument class. And I have an XmlDocument variable which I need to convert back to XDocument to append more nodes.
So, what is the most efficient method to convert XML between XDocument and XmlDocument? (Without using any temporary storage in a file.)
You can use the built in xDocument.CreateReader() and an XmlNodeReader to convert back and forth.
Putting that into an Extension method to make it easier to work with.
using System;
using System.Xml;
using System.Xml.Linq;
namespace MyTest
{
internal class Program
{
private static void Main(string[] args)
{
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml("<Root><Child>Test</Child></Root>");
var xDocument = xmlDocument.ToXDocument();
var newXmlDocument = xDocument.ToXmlDocument();
Console.ReadLine();
}
}
public static class DocumentExtensions
{
public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
var xmlDocument = new XmlDocument();
using(var xmlReader = xDocument.CreateReader())
{
xmlDocument.Load(xmlReader);
}
return xmlDocument;
}
public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
}
}
Sources:
http://msdn.microsoft.com/en-us/library/bb356384.aspx
http://geekswithblogs.net/aspringer/archive/2009/07/01/xdocument-extension.aspx
For me this single line solution works very well
XDocument y = XDocument.Parse(pXmldoc.OuterXml); // where pXmldoc is of type XMLDocument
If you need to convert the instance of System.Xml.Linq.XDocument into the instance of the System.Xml.XmlDocument this extension method will help you to do not lose the XML declaration in the resulting XmlDocument instance:
using System.Xml;
using System.Xml.Linq;
namespace www.dimaka.com
{
internal static class LinqHelper
{
public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
var xmlDocument = new XmlDocument();
using (var reader = xDocument.CreateReader())
{
xmlDocument.Load(reader);
}
var xDeclaration = xDocument.Declaration;
if (xDeclaration != null)
{
var xmlDeclaration = xmlDocument.CreateXmlDeclaration(
xDeclaration.Version,
xDeclaration.Encoding,
xDeclaration.Standalone);
xmlDocument.InsertBefore(xmlDeclaration, xmlDocument.FirstChild);
}
return xmlDocument;
}
}
}
Hope that helps!
You could try writing the XDocument to an XmlWriter piped to an XmlReader for an XmlDocument.
If I understand the concepts properly, a direct conversion is not possible (the internal structure is different / simplified with XDocument). But then, I might be wrong...
There is a discussion on http://blogs.msdn.com/marcelolr/archive/2009/03/13/fast-way-to-convert-xmldocument-into-xdocument.aspx
It seems that reading an XDocument via an XmlNodeReader is the fastest method. See the blog for more details.
If you need a Win 10 UWP compatible variant:
using DomXmlDocument = Windows.Data.Xml.Dom.XmlDocument;
public static class DocumentExtensions
{
public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
var xmlDocument = new XmlDocument();
using (var xmlReader = xDocument.CreateReader())
{
xmlDocument.Load(xmlReader);
}
return xmlDocument;
}
public static DomXmlDocument ToDomXmlDocument(this XDocument xDocument)
{
var xmlDocument = new DomXmlDocument();
using (var xmlReader = xDocument.CreateReader())
{
xmlDocument.LoadXml(xmlReader.ReadOuterXml());
}
return xmlDocument;
}
public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var memStream = new MemoryStream())
{
using (var w = XmlWriter.Create(memStream))
{
xmlDocument.WriteContentTo(w);
}
memStream.Seek(0, SeekOrigin.Begin);
using (var r = XmlReader.Create(memStream))
{
return XDocument.Load(r);
}
}
}
public static XDocument ToXDocument(this DomXmlDocument xmlDocument)
{
using (var memStream = new MemoryStream())
{
using (var w = XmlWriter.Create(memStream))
{
w.WriteRaw(xmlDocument.GetXml());
}
memStream.Seek(0, SeekOrigin.Begin);
using (var r = XmlReader.Create(memStream))
{
return XDocument.Load(r);
}
}
}
}
Success story sharing
XmlDocument
(as a property) andXDocument
(as a node). If you want to preserve the declaration, you'll need to handle it explicitly (see blogs.msdn.com/b/ericwhite/archive/2010/03/05/… or @Dmitry's answer stackoverflow.com/a/8894680/2688)