关于c#:XDocument或XmlDocument

XDocument or XmlDocument

我现在正在学习XmlDocument,但我刚遇到XDocument,当我试图寻找它们的区别或好处时,我找不到有用的东西,你能告诉我为什么你会使用它们吗?


如果您使用的是.NET 3.0或更低版本,则必须使用XmlDocument,即经典的dom API。同样,您会发现还有一些其他的API会期望这样做。

但是,如果您有选择的话,我会彻底推荐使用XDocument,也就是linq to xml。创建和处理文档要简单得多。例如,其区别在于:

1
2
3
4
5
6
7
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);

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

与我见过的任何其他XML API不同,名称空间在linq-to-xml中非常容易使用:

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

linq-to-xml也能很好地与linq一起工作——它的构造模型允许您使用子元素序列轻松地构建元素:

1
2
3
4
5
6
7
8
9
10
// 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
    ));

它更具声明性,符合一般的Linq风格。

正如布兰农所提到的,这些是内存中的API,而不是流式API(尽管XStreamingElement支持延迟输出)。XmlReaderXmlWriter是在.NET中传输XML的正常方式,但是您可以在某种程度上混合所有API。例如,您可以对一个大文档进行流式处理,但是可以使用linq-to-xml,方法是在元素开始时定位一个XmlReader,从中读取一个XElement,并对其进行处理,然后转到下一个元素等。关于这种技术,有很多博客文章,这里是我通过快速搜索找到的。


到目前为止,没有一个答案提到XmlDocument不提供行信息,而XDocument提供行信息(通过IXmlLineInfo接口)。

在某些情况下,这可能是一个关键特性(例如,如果您想在XML中报告错误,或者跟踪元素的一般定义位置),并且您最好在开始使用XmlDocument实现之前了解这一点,以便以后发现您必须全部更改它。


对于熟悉XMLDOM对象模型的开发人员来说,XmlDocument非常好。它已经存在一段时间了,或多或少符合W3C标准。它支持手动导航和XPath节点选择。

XDocument为.net 3.5中的linq-to-xml功能提供了支持。它大量使用IEnumerable<>,并且可以更容易地在直C中使用。

两个文档模型都要求您将整个文档加载到内存中(例如,与XmlReader不同)。


XDocument是从linq到xml的API,XmlDocument是标准的用于xml的dom风格的API。如果您很了解dom,并且不想学习linq-to-xml,那么使用XmlDocument。如果你对这两个都不熟悉,请查看比较这两个页面,并选择你喜欢哪个页面的外观更好。

我刚开始使用linq-to-xml,我喜欢您使用函数构造创建XML文档的方式。真是太好了。相比之下,dom比较笨拙。


正如其他地方提到的,与XmlDocument相比,linq to xml无疑使XML文档的创建和更改变得轻而易举,而XNamespace ns +"elementName"语法使处理名称空间时的阅读更为愉快。

对于xslxpath顽固派来说,值得一提的是,仍然可以在linq 2 xml XNodes上执行任意xpath 1.0表达式,包括:

1
using System.Xml.XPath;

然后我们可以通过以下扩展方法使用xpath导航和投影数据:

  • xpathselectelement-单个元素
  • xpathselectelements-节点集
  • xpathevaluate-scalars和其他

例如,给定XML文档:

1
2
3
4
5
6
7
8
9
10
11
<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>

我们可以评估:

1
2
3
4
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)");

另外,请注意,Xbox 360和Windows Phone OS 7.0支持XDocument。如果您以它们为目标,则为XDocument开发或从XmlDocument迁移。


除了上面的w0lands注释外,在为Windows8构建Unity3D项目时也同样适用。在这个场景中,您还需要使用xdocument。


我相信XDocument会发出更多的对象创建调用。我怀疑,因为当您处理大量XML文档时,XmlDocument将更快。

发生这种情况的一个地方是管理扫描数据。许多扫描工具以XML格式输出数据(原因很明显)。如果您必须处理许多这些扫描文件,我认为您在使用XmlDocument时会有更好的性能。