Convertendo XDocument em XmlDocument e vice-versa


189

É um problema muito simples que eu tenho. Eu uso o XDocument para gerar um arquivo XML. Desejo retorná-lo como uma classe XmlDocument. E eu tenho uma variável XmlDocument que preciso converter novamente em XDocument para acrescentar mais nós.

Então, qual é o método mais eficiente para converter XML entre XDocument e XmlDocument? (Sem usar armazenamento temporário em um arquivo.)

Respostas:


304

Você pode usar o xDocument.CreateReader () incorporado e um XmlNodeReader para converter para frente e para trás.

Colocando isso em um método de extensão para facilitar o trabalho.

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

Fontes:


4
você não precisaria se preocupar em descartar o leitor criado no método ToXmlDocument?
CodeMonkey1313

5
Por que ToXDocument () contém chamada para MoveToContent ()? Parece que ele ignoraria qualquer conteúdo antes do elemento do documento, por exemplo, comentários e instruções de processamento na parte superior do documento XML.
redcalx

@locster a declaração é tratada de maneira diferente entre XmlDocument(como uma propriedade) e XDocument(como um nó). Se você deseja preservar a declaração, precisará manipulá-la explicitamente (consulte blogs.msdn.com/b/ericwhite/archive/2010/03/05/… ou a resposta de @ Dmitry stackoverflow.com/a/8894680/2688 )
bdukes

Infelizmente, isso não funciona no Windows 10 UWP. Publiquei minha solução para essa plataforma abaixo, se alguém estiver interessado.
bc3tech

28

Para mim, esta solução de linha única funciona muito bem

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

21
Não use isso - embora isso funcione corretamente, é muito ineficiente, pois converte toda a árvore XML em uma única string e analisa isso novamente posteriormente.
Lucero

3
Veja este post para um benchmark das diferentes abordagens 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

O uso desta extensão é feito usando simplesmente algo como isto

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

13
Não use isso - embora isso funcione corretamente, é muito ineficiente, pois converte toda a árvore XML em uma única string e analisa isso novamente posteriormente.
Lucero

5

Se você precisar converter a instância de System.Xml.Linq.XDocument na instância de System.Xml.XmlDocument, esse método de extensão ajudará você a não perder a declaração XML na instância 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 ajude!


4

Você pode tentar gravar o XDocument em um XmlWriter canalizado para um XmlReader para um XmlDocument.

Se eu entendo os conceitos corretamente, uma conversão direta não é possível (a estrutura interna é diferente / simplificada com o XDocument). Mas então, eu posso estar errado ...



-1

Se você precisar de uma variante compatível com 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);
                }
            }
        }
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.