XDocument lub XmlDocument

501

Teraz się uczę, XmlDocumentale właśnie natknąłem się na to, XDocumenta kiedy próbuję znaleźć różnicę lub korzyści z nich, nie mogę znaleźć czegoś przydatnego, czy mógłbyś mi powiedzieć, dlaczego używałbyś jednego nad drugim?

Tarik
źródło
13
Zastanawiam się, dlaczego faceci z dokumentacji w Microsoft nie umieścili żadnych notatek ani uwag w MSDN, aby wyjaśnić swoje różnice lub kiedy z czego korzystać.
Kamran Bigdely
1
Kilka informacji na temat msdn: msdn.microsoft.com/en-us/library/… . I pytanie wydajność: stackoverflow.com/questions/4383919/... . Osobiście uważam, że łatwiej jest pracować z LINQ to XML.
nawfal

Odpowiedzi:

500

Jeśli używasz .NET w wersji 3.0 lub obniżyć, to muszą korzystać XmlDocumentaka klasycznej DOM API. Przekonasz się również, że istnieją inne interfejsy API, które będą tego oczekiwać.

Jeśli jednak dostaniesz wybór, zdecydowanie polecam użycie XDocumentaka LINQ to XML. Tworzenie dokumentów i ich przetwarzanie jest znacznie prostsze. Na przykład jest to różnica między:

XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("root");
root.SetAttribute("name", "value");
XmlElement child = doc.CreateElement("child");
child.InnerText = "text node";
root.AppendChild(child);
doc.AppendChild(root);

i

XDocument doc = new XDocument(
    new XElement("root",
                 new XAttribute("name", "value"),
                 new XElement("child", "text node")));

Przestrzenie nazw są dość łatwe w obsłudze w LINQ to XML, w przeciwieństwie do innych API XML, jakie kiedykolwiek widziałem:

XNamespace ns = "http://somewhere.com";
XElement element = new XElement(ns + "elementName");
// etc

LINQ to XML działa również bardzo dobrze z LINQ - jego model konstrukcyjny pozwala bardzo łatwo budować elementy z sekwencjami podelementów:

// Customers is a List<Customer>
XElement customersElement = new XElement("customers",
    customers.Select(c => new XElement("customer",
        new XAttribute("name", c.Name),
        new XAttribute("lastSeen", c.LastOrder)
        new XElement("address",
            new XAttribute("town", c.Town),
            new XAttribute("firstline", c.Address1),
            // etc
    ));

Wszystko jest o wiele bardziej deklaratywne, co pasuje do ogólnego stylu LINQ.

Teraz, jak wspomniał Brannon, są to interfejsy API w pamięci, a nie strumieniowe (chociaż XStreamingElementobsługuje leniwe wyjście). XmlReaderi XmlWritersą normalnymi sposobami przesyłania strumieniowego XML w .NET, ale do pewnego stopnia możesz mieszać wszystkie interfejsy API. Na przykład możesz przesyłać strumieniowo duży dokument, ale używać LINQ do XML, umieszczając XmlReaderna początku elementu, czytając XElementz niego i przetwarzając go, a następnie przechodząc do następnego elementu itp. Istnieją różne posty na blogu o tej technice, oto jeden, który znalazłem dzięki szybkiemu wyszukiwaniu .

Jon Skeet
źródło
Czy możesz mi powiedzieć, dlaczego się różnią? Mam na myśli, że tak, XDocument wygląda całkiem schludnie, ale jeśli chodzi o różnicę poziomów DOM, czyż nie są one xml, czy jest jakiś schemat, który pokazuje DOM X-DOM i DOM zgodny z W3C? Dzięki.
Tarik
3
Co rozumiesz przez „schemat”, a co przez „programy”? Tak, oba dotyczą standardowego XML, ale LINQ to XML jest po prostu ładniejszym API dla większości rzeczy. Wiele technologii stojących za LINQ to XML po prostu nie było dostępne przed .NET 3.5.
Jon Skeet,
Mam na myśli, czy ich modele obiektów dokumentu są różne?
Tarik
6
Oba są interfejsami API dla samego XML, więc w tym sensie nie różnią się, nie. Podejrzewam, że oba mają pewne ograniczenia (i jest takie LINQ to XML, o którym wiem, ale nie pamiętam z góry głowy), ale w większości przypadków można je traktować jako ten sam model z nieco innymi reprezentacjami.
Jon Skeet
1
@SensorSmith: Nie obejmuje to jednak wszystkich innych bonusów, takich jak automatyczne spłaszczanie sekwencji, obsługa DateTime itp. Możesz również dodać metody rozszerzeń do tego wszystkiego, ale po co wymieniać LINQ na XML, skoro możesz po prostu z niego korzystać?
Jon Skeet
57

Dziwi mnie, że żadna z dotychczasowych odpowiedzi nie wspomina o tym, że XmlDocumentnie podaje żadnych informacji o wierszu , a XDocumentrobi to (przez IXmlLineInfointerfejs).

Może to być krytyczna funkcja w niektórych przypadkach (na przykład, jeśli chcesz zgłosić błędy w pliku XML lub śledzić, gdzie elementy są ogólnie zdefiniowane) i lepiej być tego świadomym, zanim z przyjemnością zaczniesz wdrażać XmlDocument, aby później odkryj, że musisz to wszystko zmienić.

Julien Guertault
źródło
1
I dziwię się, że nikt nie zauważył, że twoje stwierdzenie jest odwrotnie prawdziwe. XmlDocument NIE dostarcza informacji o wierszu, podczas gdy XDocument nie.
VVS,
4
@VVS: Przez chwilę martwiłem się, że popełniłem straszną literówkę, ale po podwójnym sprawdzeniu potwierdzam, że XDocumentzawiera informacje o wierszu. Zobacz XDocument.Load ze LoadOptions.SetLineInfojako drugi argument. Jeśli znasz sposób na uzyskanie informacji o linii XmlDocument, jestem ciekawy; kiedy pisałem tę odpowiedź, nie mogłem jej znaleźć. Ta druga odpowiedź wydaje się potwierdzać: stackoverflow.com/a/33622102/253883
Julien Guertault
1
„i lepiej o tym pamiętać, zanim z radością zaczniesz wdrażać za pomocą XmlDocument, aby później odkryć, że musisz to wszystko zmienić”. Zgadnij, co właśnie zrobiłem :)
Paul
36

XmlDocumentjest świetny dla programistów znających model obiektowy XML DOM. Jest już od jakiegoś czasu i mniej więcej odpowiada standardowi W3C. Obsługuje ręczną nawigację, a także XPathwybór węzła.

XDocumentzasila funkcję LINQ to XML w .NET 3.5. To sprawia, że ​​jest intensywnie używany IEnumerable<>i może być łatwiej pracować z prostym C #.

Oba modele dokumentów wymagają załadowania całego dokumentu do pamięci (w przeciwieństwie XmlReaderdo na przykład).

Brannon
źródło
3
Myślę, że miałeś na myśli „i może być łatwiej pracować z prostym VB.net”. Ponieważ VB obsługuje bezpośrednie tworzenie elementów, w których C # nadal wymaga kodu.
Brain2000
24

XDocumentpochodzi z interfejsu API LINQ to XML i XmlDocumentjest standardowym interfejsem API typu DOM dla XML. Jeśli dobrze znasz DOM i nie chcesz uczyć się LINQ na XML, idź z XmlDocument. Jeśli jesteś nowy w obu przypadkach, sprawdź tę stronę, która porównuje oba, i wybierz, który Ci się bardziej podoba.

Właśnie zacząłem używać LINQ na XML i uwielbiam sposób, w jaki tworzysz dokument XML przy użyciu funkcjonalnej konstrukcji. To naprawdę miłe. DOM jest nieporadny w porównaniu.

Daniel Chambers
źródło
23

Jak wspomniano w innym miejscu, niewątpliwie Linq do Xml sprawia, że ​​tworzenie i modyfikowanie dokumentów xml jest dziecinnie proste w porównaniu z XmlDocument, a XNamespace ns + "elementName"składnia zapewnia przyjemne czytanie w przypadku przestrzeni nazw.

Jedną z rzeczy, o których warto wspomnieć xsli których xpathnależy pamiętać, jest to, że nadal można wykonywać dowolne xpath 1.0wyrażenia na Linq 2 Xml XNodes, włączając:

using System.Xml.XPath;

a następnie możemy nawigować i wyświetlać dane za xpathpomocą następujących metod rozszerzenia:

Na przykład biorąc pod uwagę dokument Xml:

<xml>
    <foo>
        <baz id="1">10</baz>
        <bar id="2" special="1">baa baa</bar>
        <baz id="3">20</baz>
        <bar id="4" />
        <bar id="5" />
    </foo>
    <foo id="123">Text 1<moo />Text 2
    </foo>
</xml>

Możemy ocenić:

var node = xele.XPathSelectElement("/xml/foo[@id='123']");
var nodes = xele.XPathSelectElements(
"//moo/ancestor::xml/descendant::baz[@id='1']/following-sibling::bar[not(@special='1')]");
var sum = xele.XPathEvaluate("sum(//foo[not(moo)]/baz)");
StuartLC
źródło
14

Należy również pamiętać, że XDocumentjest obsługiwany w Xbox 360 i Windows Phone OS 7.0. Jeśli celujesz w nie, rozwijaj się XDocumentlub migruj z XmlDocument.

w0land
źródło
-8

Uważam, że to XDocumentpowoduje znacznie więcej wywołań tworzenia obiektów. Podejrzewam, że gdy będziesz przetwarzać wiele dokumentów XML, XMLDocumentbędzie to szybsze.

Jednym z takich przypadków jest zarządzanie skanowanymi danymi. Wiele narzędzi skanujących wysyła swoje dane w formacie XML (z oczywistych powodów). Jeśli musisz przetworzyć wiele z tych plików skanowania, myślę, że będziesz mieć lepszą wydajność XMLDocument.

Brian
źródło
11
Myślę, że następnym razem powinieneś uzupełnić swój komentarz liczbami, ponieważ uważam, że możesz się mylić. Zobacz blogs.msdn.com/b/codejunkie/archive/2008/10/08/…
mike