Convertir XDocument a XmlDocument y viceversa


189

Es un problema muy simple que tengo. Yo uso XDocument para generar un archivo XML. Luego quiero devolverlo como una clase XmlDocument. Y tengo una variable XmlDocument que necesito convertir de nuevo a XDocument para agregar más nodos.

Entonces, ¿cuál es el método más eficiente para convertir XML entre XDocument y XmlDocument? (Sin usar ningún almacenamiento temporal en un archivo).

Respuestas:


304

Puede usar el xDocument.CreateReader () incorporado y un XmlNodeReader para convertir de un lado a otro.

Poner eso en un método de Extensión para que sea más fácil trabajar con él.

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

Fuentes:


44
¿no debería preocuparse por deshacerse del lector creado con el método ToXmlDocument?
CodeMonkey1313

55
¿Por qué ToXDocument () contiene una llamada a MoveToContent ()? Esto parece probable que omita cualquier contenido antes del elemento del documento, por ejemplo, cualquier comentario e instrucciones de procesamiento en la parte superior del documento XML.
redcalx

@locster la declaración se maneja de manera diferente entre XmlDocument(como una propiedad) y XDocument(como un nodo). Si desea conservar la declaración, deberá manejarla explícitamente (consulte blogs.msdn.com/b/ericwhite/archive/2010/03/05/… o la respuesta de @ Dmitry stackoverflow.com/a/8894680/2688 )
bdukes

Lamentablemente, esto no funciona en Windows 10 UWP. He publicado mi solución para esa plataforma a continuación si alguien está interesado.
bc3tech

28

Para mí, esta solución de línea única funciona muy bien.

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

21
No use esto, aunque esto funciona correctamente, es muy ineficiente ya que convierte todo el árbol XML en una sola cadena y lo analiza nuevamente después.
Lucero

3
Consulte esta publicación para obtener un punto de referencia de los diferentes enfoques 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

El uso de esta extensión se hace simplemente usando algo como esto

System.Xml.XmlElement systemXml = (new XElement("nothing")).ToXmlElement();
System.Xml.Linq.XElement linqXml = systemXml.ToXElement();

13
No use esto, aunque esto funciona correctamente, es muy ineficiente ya que convierte todo el árbol XML en una sola cadena y lo analiza nuevamente después.
Lucero

5

Si necesita convertir la instancia de System.Xml.Linq.XDocument en la instancia de System.Xml.XmlDocument, este método de extensión lo ayudará a no perder la declaración XML en la instancia resultante de XmlDocument:

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

¡Espero que ayude!


4

Podría intentar escribir el XDocument en un XmlWriter canalizado a un XmlReader para un XmlDocument.

Si entiendo los conceptos correctamente, no es posible una conversión directa (la estructura interna es diferente / simplificada con XDocument). Pero entonces, podría estar equivocado ...



-1

Si necesita una variante compatible con Win 10 UWP:

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);
                }
            }
        }
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.