我现在正在学习XmlDocument,但我刚遇到XDocument,当我试图寻找它们的区别或好处时,我找不到有用的东西,你能告诉我为什么你会使用它们吗?
- 我想知道为什么微软的文档人员没有在msdn中添加任何注释或评论来澄清他们之间的差异或何时使用什么。
- 有关msdn的一些信息:msdn.microsoft.com/en-us/library/…。还有一个性能问题:stackoverflow.com/questions/4383919/…。就我个人而言,我发现使用linq-to-xml更容易。
如果您使用的是.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支持延迟输出)。XmlReader和XmlWriter是在.NET中传输XML的正常方式,但是您可以在某种程度上混合所有API。例如,您可以对一个大文档进行流式处理,但是可以使用linq-to-xml,方法是在元素开始时定位一个XmlReader,从中读取一个XElement,并对其进行处理,然后转到下一个元素等。关于这种技术,有很多博客文章,这里是我通过快速搜索找到的。
- 你能告诉我为什么它们不一样吗?我的意思是,xdocument看起来很整洁,但是对于dom级别的区别,它们不是都是XML吗?有没有任何方案同时显示符合Microsoft X-DOM和W3C的dom?谢谢。
- 你说的"计划"是什么意思?你说的"表演"是什么意思?是的,它们都处理标准的XML,但是对于大多数事情来说,LINQtoXML只是一个更好的API。在.NET3.5之前,很多linq-to-xml背后的技术根本不可用。
- 我的意思是他们的文档对象模型是否不同?
- 好吧,它们都是XML本身的API,所以从这个意义上说它们没有什么不同,不。我怀疑两者都有一些局限性(而且有一个Linq to XML,我知道,但在我的头脑中却记不起来),但是在大多数情况下,您可以将它们视为具有稍微不同表示的同一个模型。
- @在最后一个例子中,Jonskeet列出了客户列表。如果列表中的foreach客户想要创建一对Xelement,那么应该如何处理:1</id>Bob</name>2</id>Frank</name></customers>。我试过在select中创建多个用逗号分隔的元素,比如:.Select(c => new XElement("id", c.id), new XElement("name", c.name));,但显然这不是语法
- @威兹利兹:我建议你提出一个新问题,而不是我们试图在评论中处理它。
- 一开始我以为这会适合这个答案,然后我决定问一个新的,已经做了和回答。谢谢)
- 这是很古老的,但是"创建文档更简单"(使用xdocument)非常薄。添加自己的xmldocument/xmlelement扩展方法来获取linq esq函数链是很简单的。例如:public static XmlElement AppendElement(this XmlElement parent, string prefix, string name, string ns) { var child = parent.OwnerDocument.CreateElement(prefix, name, ns); parent.AppendChild(child); return child; }。
- @sensorsmith:但这不包括所有其他的奖励,比如序列的自动扁平化、日期时间的处理等。您也可以为所有这些添加扩展方法,但是当您可以使用它时,为什么还要重新将linq转换为xml呢?
- 在我的查询中,如果xmlns:*与XLinQ一起使用XPath符号有什么方法吗?
- @塞里安:恐怕我不明白你的问题。我建议你在一个新的帖子里多问一些细节。
到目前为止,没有一个答案提到XmlDocument不提供行信息,而XDocument提供行信息(通过IXmlLineInfo接口)。
在某些情况下,这可能是一个关键特性(例如,如果您想在XML中报告错误,或者跟踪元素的一般定义位置),并且您最好在开始使用XmlDocument实现之前了解这一点,以便以后发现您必须全部更改它。
- 我很惊讶没有人注意到你的陈述是反事实的。xmldocument不提供行信息,而xdocument不提供行信息。
- @VVS:你让我担心了一会儿,我犯了一个糟糕的打字错误,但经过反复检查,我确认XDocument确实提供了行信息。参见xdocument.load with LoadOptions.SetLineInfo作为第二个参数。如果你知道一种方法来获取XmlDocument的行信息,我很好奇;回到我写这个答案的时候,我找不到任何答案。另一个答案似乎可以证实:stackoverflow.com/a/33622102/253883
对于熟悉XMLDOM对象模型的开发人员来说,XmlDocument非常好。它已经存在一段时间了,或多或少符合W3C标准。它支持手动导航和XPath节点选择。
XDocument为.net 3.5中的linq-to-xml功能提供了支持。它大量使用IEnumerable<>,并且可以更容易地在直C中使用。
两个文档模型都要求您将整个文档加载到内存中(例如,与XmlReader不同)。
- 我认为你的意思是"并且可以更容易地在直的vb.net中使用"。因为vb支持直接创建元素,而c仍然需要代码。
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"语法使处理名称空间时的阅读更为愉快。
对于xsl和xpath顽固派来说,值得一提的是,仍然可以在linq 2 xml XNodes上执行任意xpath 1.0表达式,包括:
然后我们可以通过以下扩展方法使用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时会有更好的性能。
- 我认为你下次应该用数字来支持你的评论,因为我相信你可能错了。参见blogs.msdn.com/b/codejunkie/archive/2008/10/08/&hellip;