C# XML技术总结之XDocument 和XmlDocument
引言
虽然现在Json在我们的数据交换中越来越成熟,但XML格式的数据还有很重要的地位。
C#中对XML的处理也不断优化,那么我们如何选择XML的这几款处理类 XmlReader,XDocument 和XmlDocument了?
本文就从对照的方式来总结C#中XML的用法。
简介
System.Xml 命名空间(XmlDocument)为处理 XML 提供基于标准的支持。
LINQ to XML(XDocument )可以进行以下操作:
-
从文件或流加载 XML。
-
将 XML 序列化为文件或流。
-
使用功能构造从头创建 XML 树。
-
使用 LINQ 查询来查询 XML 树。
-
操作内存中的 XML 树。
-
使用 XSD 验证 XML 树。
-
组合使用这些功能将 XML 树从一种形状转换为另一种形状。
XmlReader,XDocument 和XmlDocument
XDocument 和XmlDocument会把所有的XML所有的节点加载到内存中,而XmlReader则不会把所有节点一起加载到内存,而在一定的内存下处理较大的XML。
如果XML文件结构固定,处理比较简单,建议使用XmlReader可以提高程序的性能。
如果XML文件不大或者要做复杂的处理建议使用XDocument。Linq 让程序员省去了很多繁琐冗余的代码,并且兼容设备也比较多,不像XmlDocument在一些设备和系统中不支持。
XDocument VS. XmlDocument
比较项 | XmlDocument(经典DOM API) | XDocument (LINQ to XML API) |
需要熟悉DOM知识 | ||
支持的.NetFramework版本 | .NET version 1.0 + | .NET version 3.5 or later(Linq引入后) |
杂项 | Unity3D projects for Windows 8. Xbox 360 and Windows Phone OS 7.0,必须使用XDocument | |
Namespace | System.Xml | System.Xml.Linq |
LINQ to XML | 不支持 | 支持 |
行号信息 | 不能提供行号信息 | 通过IXmlLineInfo 提供了行号信息 |
命名空间 | 支持写 | 支持元素级写 |
XPath | 不支持 | 支持, 参考System.Xml.XPath |
注释 | 不支持 | 支持可扩展的批注集,请参见 LINQ to XML 批注。 |
校验Schema | 支持,参考Validate(ValidationEventHandler) | 支持 ,参考Validate(XmlSchemaSet, ValidationEventHandler) |
加载XML | 成员方法加载(需要先new XmlDocument()) | 静态方法XElement.Load(@"books.xml") |
创建XML文档
使用XmlDocument 的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | XmlDocument doc = new XmlDocument(); XmlElement name = doc.CreateElement( "Name" ); name.InnerText = "Patrick Hines" ; XmlElement phone1 = doc.CreateElement( "Phone" ); phone1.SetAttribute( "Type" , "Home" ); phone1.InnerText = "206-555-0144" ; XmlElement phone2 = doc.CreateElement( "Phone" ); phone2.SetAttribute( "Type" , "Work" ); phone2.InnerText = "425-555-0145" ; XmlElement street1 = doc.CreateElement( "Street1" ); street1.InnerText = "123 Main St" ; XmlElement city = doc.CreateElement( "City" ); city.InnerText = "Mercer Island" ; XmlElement state = doc.CreateElement( "State" ); state.InnerText = "WA" ; XmlElement postal = doc.CreateElement( "Postal" ); postal.InnerText = "68042" ; XmlElement address = doc.CreateElement( "Address" ); address.AppendChild(street1); address.AppendChild(city); address.AppendChild(state); address.AppendChild(postal); XmlElement contact = doc.CreateElement( "Contact" ); contact.AppendChild(name); contact.AppendChild(phone1); contact.AppendChild(phone2); contact.AppendChild(address); XmlElement contacts = doc.CreateElement( "Contacts" ); contacts.AppendChild(contact); doc.AppendChild(contacts); |
使用XDocument 的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | XElement contacts = new XElement( "Contacts" , new XElement( "Contact" , new XElement( "Name" , "Patrick Hines" ), new XElement( "Phone" , "206-555-0144" , new XAttribute( "Type" , "Home" )), new XElement( "phone" , "425-555-0145" , new XAttribute( "Type" , "Work" )), new XElement( "Address" , new XElement( "Street1" , "123 Main St" ), new XElement( "City" , "Mercer Island" ), new XElement( "State" , "WA" ), new XElement( "Postal" , "68042" ) ) ) ); |
加载XML文件
使用XmlDocument 的示例
1 2 | XmlDocument booksFromFile = new XmlDocument(); booksFromFile.Load( @"books.xml" ); |
使用XDocument 的示例
1 | XElement booksFromFile = XElement.Load( @"books.xml" ); |
命名空间的处理
使用XmlDocument 的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public void addXmlns() { string xml = @"<?xml version=""1.0""?> <kml> <Document> <Placemark> </Placemark> </Document> </kml>" ; var xmldoc = new XmlDocument(); xmldoc.LoadXml(xml); string message; message = xmldoc.InnerXml; Console.WriteLine(message); // shows the updated xml } |
使用XDocument 的示例
示例1,增加namespace
1 2 3 |
示例2,读取含有namespace的文件
string markup = @" <aw:Root xmlns:aw='http://www.adventure-works.com'> <aw:Child1>child one data</aw:Child1> <aw:Child2>child two data</aw:Child2> </aw:Root>";
1234567XmlReader reader = XmlReader.Create(
new
StringReader(markup));
XElement root = XElement.Load(reader);
XmlNameTable nameTable = reader.NameTable;
XmlNamespaceManager namespaceManager =
new
XmlNamespaceManager(nameTable);
XElement child1 = root.XPathSelectElement(
"./aw:Child1"
, namespaceManager);
Console.WriteLine(child1);
XDocument
XDocument VS. XElement
XDocument | XElement |
XDocument.Load() 加载整个XML文档 包括根节点 | XElement.Load()不会加载XML的根节点 |
XElement.Load()示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | File.WriteAllText( "Test.xml" , @"<Root> <Child1>1< /Child1 > <Child2>2< /Child2 > <Child3>3< /Child3 > < /Root >"); Console.WriteLine( "Querying tree loaded with XElement.Load" ); Console.WriteLine( "----" ); XElement doc = XElement.Load( "Test.xml" ); IEnumerable<XElement> childList = from el in doc.Elements() select el; foreach (XElement e in childList) Console.WriteLine(e); |
XDocument.Load() 示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | File.WriteAllText( "Test.xml" , @"<Root> <Child1>1</Child1> <Child2>2</Child2> <Child3>3</Child3> </Root>" ); Console.WriteLine( "Querying tree loaded with XDocument.Load" ); Console.WriteLine( "----" ); XDocument doc = XDocument.Load( "Test.xml" ); IEnumerable<XElement> childList = from el in doc.Elements() select el; foreach (XElement e in childList) Console.WriteLine(e); |
XPath
XPath的强大之处在于处理元素导航还可以进行计算
- XPathSelectElement - Single Element
- XPathSelectElements - Node Set
- XPathEvaluate - Scalars and others
示例:
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 | |
1 | |
C#处理计算
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)" ); |
这里只是总结知识点,但具体的关于更多XPath的内容可以移步到XPath 教程
XML 批注(注释)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public class MyAnnotation { private string tag; public string Tag { get { return tag; } set { tag = value; } } public MyAnnotation( string tag) { this .tag = tag; } } class Program { static void Main( string [] args) { XElement root = new XElement( "Root" , "content" ); root.AddAnnotation( new MyAnnotation( "T1" )); root.AddAnnotation( new MyAnnotation( "T2" )); root.AddAnnotation( "abc" ); root.AddAnnotation( "def" ); IEnumerable< object > annotationList; annotationList = root.Annotations( typeof (MyAnnotation)); foreach ( object ma in annotationList) Console.WriteLine(((MyAnnotation)ma).Tag); Console.WriteLine( "----" ); IEnumerable< object > stringAnnotationList; stringAnnotationList = root.Annotations( typeof ( string )); foreach ( object str in stringAnnotationList) Console.WriteLine(( string )str); } } |
总结
现在再写XML相关的程序建议直接使用XDocument,XmlDocument只是主要还是兼容以前的代码。
另外XPath功能让XDocument如虎添翼,所以大家可以多研究下XPath.
至于XSD和XSL本文不做涉及,又需要的朋友参看参考文献
参考
2.使用XmlReader读Xml,使用XmlWriter写Xml
9.W3CSchool中提供的XML相关课程
作者:旭东
出处:http://www.cnblogs.com/HQFZ
关于作者:专注于微软平台项目架构、管理和企业解决方案。现主要从事WinForm、ASP.NET、WPF、WCF、等方面的项目开发、架构、管理。如有问题或建议,请不吝指教!
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题,可以联系我,非常感谢。
如果您该文觉得不错或者对你有帮助,请点下推荐,让更多的朋友看到,谢谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?