Konwertowanie XDocument na XmlDocument i odwrotnie

189

To bardzo prosty problem, który mam. Używam XDocument do generowania pliku XML. Następnie chcę zwrócić jako klasę XmlDocument. I mam zmienną XmlDocument, którą muszę przekonwertować z powrotem na XDocument, aby dodać więcej węzłów.

Więc jaka jest najbardziej wydajna metoda konwersji XML między XDocument i XmlDocument? (Bez użycia tymczasowego przechowywania w pliku.)

Wim ten Brink
źródło

Odpowiedzi:

304

Możesz użyć wbudowanej funkcji xDocument.CreateReader () i XmlNodeReader do konwersji w tę iz powrotem.

Umieszczenie tego w metodzie rozszerzenia, aby ułatwić pracę.

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

Źródła:

Mark Coleman
źródło
4
nie musiałbyś się martwić o usunięcie czytnika, który został utworzony metodą ToXmlDocument?
CodeMonkey1313
5
Dlaczego ToXDocument () zawiera wywołanie MoveToContent ()? Wygląda na to, że pominie jakąkolwiek treść przed elementem dokumentu, np. Wszelkie komentarze i instrukcje przetwarzania na górze dokumentu XML.
redcalx
@locster deklaracja jest traktowana inaczej XmlDocument(jako właściwość) i XDocument(jako węzeł). Jeśli chcesz zachować deklarację, musisz potraktować ją jawnie (zobacz blogs.msdn.com/b/ericwhite/archive/2010/03/05/… lub odpowiedź stackoverflow.com/a/8894680/2688 @ Dmitry'ego )
bdukes
Niestety nie działa to w systemie Windows 10 UWP. Poniżej zamieściłem moje rozwiązanie dla tej platformy, jeśli ktoś jest zainteresowany.
bc3tech,
28

Dla mnie to rozwiązanie jednoliniowe działa bardzo dobrze

XDocument y = XDocument.Parse(pXmldoc.OuterXml); // where pXmldoc is of type XMLDocument
Abhi
źródło
21
Nie używaj tego - chociaż działa to poprawnie, jest bardzo nieefektywne, ponieważ konwertuje całe drzewo XML na pojedynczy ciąg znaków, a następnie analizuje je ponownie.
Lucero,
3
Zobacz ten post, aby zapoznać się z analizą
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

Wykorzystanie tego rozszerzenia jest wykonywane po prostu przy użyciu czegoś takiego

System.Xml.XmlElement systemXml = (new XElement("nothing")).ToXmlElement();
System.Xml.Linq.XElement linqXml = systemXml.ToXElement();
Robert Harvey
źródło
13
Nie używaj tego - chociaż działa to poprawnie, jest bardzo nieefektywne, ponieważ konwertuje całe drzewo XML na pojedynczy ciąg znaków, a następnie analizuje je ponownie.
Lucero,
5

Jeśli musisz przekonwertować instancję System.Xml.Linq.XDocument na instancję System.Xml.XmlDocument, ta metoda rozszerzenia pomoże ci nie stracić deklaracji XML w wynikowej instancji 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; 
        } 
    } 
}

Mam nadzieję, że to pomaga!

Dmitrij Pawłow
źródło
4

Możesz spróbować zapisać XDocument do XmlWriter podłączonego do XmlReadera dla XmlDocument.

Jeśli dobrze rozumiem pojęcia, bezpośrednia konwersja nie jest możliwa (struktura wewnętrzna jest inna / uproszczona w XDocument). Ale może się mylę ...

Daren Thomas
źródło
-1

Jeśli potrzebujesz wariantu zgodnego z 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
źródło