Konvertieren von XDocument in XmlDocument und umgekehrt

189

Es ist ein sehr einfaches Problem, das ich habe. Ich benutze XDocument, um eine XML-Datei zu generieren. Ich möchte es dann als XmlDocument-Klasse zurückgeben. Und ich habe eine XmlDocument-Variable, die ich zurück in XDocument konvertieren muss, um weitere Knoten anzuhängen.

Was ist die effizienteste Methode zum Konvertieren von XML zwischen XDocument und XmlDocument? (Ohne temporären Speicher in einer Datei zu verwenden.)

Wim zehn Brink
quelle

Antworten:

304

Sie können den integrierten xDocument.CreateReader () und einen XmlNodeReader verwenden, um hin und her zu konvertieren.

Fügen Sie dies in eine Erweiterungsmethode ein, um die Arbeit zu vereinfachen.

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

Quellen:

Mark Coleman
quelle
4
Müssen Sie sich nicht darum kümmern, den in der ToXmlDocument-Methode erstellten Reader zu entsorgen?
CodeMonkey1313
5
Warum enthält ToXDocument () einen Aufruf von MoveToContent ()? Dies sieht so aus, als würde jeglicher Inhalt vor dem Dokumentelement übersprungen, z. B. Kommentare und Verarbeitungsanweisungen oben im XML-Dokument.
Redcalx
@locster Die Deklaration wird zwischen XmlDocument(als Eigenschaft) und XDocument(als Knoten) unterschiedlich behandelt. Wenn Sie die Deklaration beibehalten möchten, müssen Sie sie explizit behandeln (siehe blogs.msdn.com/b/ericwhite/archive/2010/03/05/… oder @ Dmitrys Antwort stackoverflow.com/a/8894680/2688) )
Bdukes
Leider funktioniert dies in Windows 10 UWP nicht. Ich habe meine Lösung für diese Plattform unten veröffentlicht, wenn sich jemand dafür interessiert.
bc3tech
28

Für mich funktioniert diese einzeilige Lösung sehr gut

XDocument y = XDocument.Parse(pXmldoc.OuterXml); // where pXmldoc is of type XMLDocument
Abhi
quelle
21
Verwenden Sie dies nicht - obwohl dies korrekt funktioniert, ist es sehr ineffizient, da es den gesamten XML-Baum in eine einzelne Zeichenfolge konvertiert und diese anschließend erneut analysiert.
Lucero
3
In diesem Beitrag finden Sie einen Benchmark der verschiedenen Ansätze blogs.msdn.microsoft.com/xmlteam/2009/03/31/…
Bernard Vander Beken
7
using System.Xml;
using System.Xml.Linq;

   #region Extention Method
    public static XElement ToXElement(this XmlElement element)
    {
        return XElement.Parse(element.OuterXml);
    }

    public static XmlElement ToXmlElement(this XElement element)
    {
        var doc = new XmlDocument();
        doc.LoadXml(element.ToString());
        return doc.DocumentElement;            
    }
    #endregion

Die Verwendung dieser Erweiterung erfolgt dann einfach mit so etwas

System.Xml.XmlElement systemXml = (new XElement("nothing")).ToXmlElement();
System.Xml.Linq.XElement linqXml = systemXml.ToXElement();
Robert Harvey
quelle
13
Verwenden Sie dies nicht - obwohl dies korrekt funktioniert, ist es sehr ineffizient, da es den gesamten XML-Baum in eine einzelne Zeichenfolge konvertiert und diese anschließend erneut analysiert.
Lucero
5

Wenn Sie die Instanz von System.Xml.Linq.XDocument in die Instanz von System.Xml.XmlDocument konvertieren müssen, hilft Ihnen diese Erweiterungsmethode dabei , die XML-Deklaration in der resultierenden XmlDocument-Instanz nicht zu verlieren :

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

Hoffentlich hilft das!

Dmitry Pavlov
quelle
4

Sie können versuchen, das XDocument in einen XmlWriter zu schreiben, der für ein XmlDocument an einen XmlReader weitergeleitet wird.

Wenn ich die Konzepte richtig verstehe, ist eine direkte Konvertierung nicht möglich (die interne Struktur ist mit XDocument anders / vereinfacht). Aber dann könnte ich mich irren ...

Daren Thomas
quelle
-1

Wenn Sie eine Win 10 UWP-kompatible Variante benötigen:

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