Conversion de XDocument en XmlDocument et vice versa

189

C'est un problème très simple que j'ai. J'utilise XDocument pour générer un fichier XML. Je veux ensuite le renvoyer en tant que classe XmlDocument. Et j'ai une variable XmlDocument que je dois reconvertir en XDocument pour ajouter plus de nœuds.

Alors, quelle est la méthode la plus efficace pour convertir du XML entre XDocument et XmlDocument? (Sans utiliser de stockage temporaire dans un fichier.)

Wim ten Brink
la source

Réponses:

304

Vous pouvez utiliser le xDocument.CreateReader () intégré et un XmlNodeReader pour effectuer une conversion dans les deux sens.

Mettre cela dans une méthode d'extension pour faciliter le travail.

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:

Mark Coleman
la source
4
n'auriez-vous pas à vous soucier de la suppression du lecteur créé dans la méthode ToXmlDocument?
CodeMonkey1313
5
Pourquoi ToXDocument () contient-il un appel à MoveToContent ()? Cela semble vouloir ignorer tout contenu avant l'élément document, par exemple tous les commentaires et instructions de traitement en haut du document XML.
redcalx
@locster la déclaration est gérée différemment entre XmlDocument(en tant que propriété) et XDocument(en tant que nœud). Si vous souhaitez conserver la déclaration, vous devrez la gérer explicitement (voir blogs.msdn.com/b/ericwhite/archive/2010/03/05/… ou la réponse de @ Dmitry stackoverflow.com/a/8894680/2688 )
bdukes
Malheureusement, cela ne fonctionne pas dans Windows 10 UWP. J'ai publié ma solution pour cette plate-forme ci-dessous si quelqu'un est intéressé.
bc3tech
28

Pour moi, cette solution à ligne unique fonctionne très bien

XDocument y = XDocument.Parse(pXmldoc.OuterXml); // where pXmldoc is of type XMLDocument
Abhi
la source
21
Ne l'utilisez pas - bien que cela fonctionne correctement, il est très inefficace car il convertit l'ensemble de l'arborescence XML en une seule chaîne et l'analyse à nouveau par la suite.
Lucero
3
Voir cet article pour un benchmark des différentes approches 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

L'utilisation de cette extension se fait simplement en utilisant quelque chose comme ça

System.Xml.XmlElement systemXml = (new XElement("nothing")).ToXmlElement();
System.Xml.Linq.XElement linqXml = systemXml.ToXElement();
Robert Harvey
la source
13
Ne l'utilisez pas - bien que cela fonctionne correctement, il est très inefficace car il convertit l'ensemble de l'arborescence XML en une seule chaîne et l'analyse à nouveau par la suite.
Lucero
5

Si vous devez convertir l'instance de System.Xml.Linq.XDocument en l'instance de System.Xml.XmlDocument, cette méthode d'extension vous aidera à ne pas perdre la déclaration XML dans l'instance XmlDocument résultante:

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

J'espère que cela pourra aider!

Dmitry Pavlov
la source
4

Vous pouvez essayer d'écrire le XDocument dans un XmlWriter redirigé vers un XmlReader pour un XmlDocument.

Si je comprends bien les concepts, une conversion directe n'est pas possible (la structure interne est différente / simplifiée avec XDocument). Mais alors, je me trompe peut-être ...

Daren Thomas
la source
-1

Si vous avez besoin d'une variante compatible 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);
                }
            }
        }
    }
bc3tech
la source