ChatGPT解决这个技术问题 Extra ChatGPT

Converting XDocument to XmlDocument and vice versa

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.)


M
Mark Coleman

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


wouldn't you have to worry about disposing the reader that was created in the ToXmlDocument method?
Why does ToXDocument() contain call to MoveToContent()? This looks liek it would skip over any content ahead of the document element, e.g. any comments and processing instructions at the top of the XML doc.
@locster the declaration is handled differently between XmlDocument (as a property) and XDocument (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)
Unfortunately this doesn't work in Windows 10 UWP. I've posted my solution for that platform below if anybody's interested.
A
Abhi

For me this single line solution works very well

XDocument y = XDocument.Parse(pXmldoc.OuterXml); // where pXmldoc is of type XMLDocument

Don't use this - while this does work correctly, it is very inefficient since it converts the whole XML tree to a single string and parses that again afterwards.
See this post for a benchmark of the different approaches blogs.msdn.microsoft.com/xmlteam/2009/03/31/…
I'm working on a utility, not production code. Simple and easy is more important to me than performance.
D
Dmitry Pavlov

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!


D
Daren Thomas

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...


p
paul

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.


b
bc3tech

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);
                }
            }
        }
    }

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now