在 C# (.NET) 中处理 XML:从基础到高级技术
XML(可扩展标记语言)仍然是 .NET 生态系统中存储和传输结构化数据的关键格式之一。无论您是在创建配置文件、与 Web 服务交换数据,还是处理文档,C# 的内置工具都提供了灵活且高效的 XML 处理方式。在本文中,我们将介绍三种主要方法:经典的 XmlDocument、现代的 XDocument(LINQ to XML)以及流式处理的 XmlReader/XmlWriter。
1. 经典 XmlDocument(DOM 模型)
System.Xml.XmlDocument 类实现了 DOM(文档对象模型)——它将整个 XML 文档以节点树的形式加载到内存中。这对于需要频繁导航和修改的中小型文档非常方便。
加载和读取 XML
using System.Xml;
XmlDocument doc = new XmlDocument();doc.Load("books.xml"); // 从文件加载
// 获取根元素XmlElement root = doc.DocumentElement;
// 选择所有 book 元素XmlNodeList books = root.SelectNodes("//book");foreach (XmlNode book in books){ string title = book["title"].InnerText; string author = book["author"].InnerText; Console.WriteLine($"{title} — {author}");}创建和保存 XML
XmlDocument doc = new XmlDocument();XmlElement root = doc.CreateElement("library");doc.AppendChild(root);
XmlElement book = doc.CreateElement("book");book.SetAttribute("id", "1");
XmlElement title = doc.CreateElement("title");title.InnerText = "战争与和平";book.AppendChild(title);
root.AppendChild(book);doc.Save("library.xml");2. 现代 LINQ to XML(XDocument)
System.Xml.Linq 命名空间提供了更简洁、功能更丰富的 API。XDocument 和 XElement 允许以 LINQ 风格编写代码,这在查询和转换时尤其方便。
使用 XDocument 进行解析
using System.Xml.Linq;
XDocument doc = XDocument.Load("books.xml");
var books = doc.Descendants("book") .Select(b => new { Title = b.Element("title")?.Value, Author = b.Element("author")?.Value, Year = (int)b.Element("year") });
foreach (var book in books){ Console.WriteLine($"{book.Title} ({book.Year})");}使用构造函数创建 XML
XDocument doc = new XDocument( new XElement("library", new XElement("book", new XAttribute("id", "1"), new XElement("title", "罪与罚"), new XElement("author", "费奥多尔·陀思妥耶夫斯基") ) ));doc.Save("library.xml");XDocument 的优势:
- 支持 LINQ 查询,用于数据过滤和投影。
- 通过嵌套构造函数创建元素,语法更易读。
- 通过
XNamespace自动处理命名空间。
3. 流式处理:XmlReader 和 XmlWriter
对于处理大型 XML 文件(数百兆字节或千兆字节),使用 XmlDocument 或 XDocument 可能会导致内存溢出。在这种情况下,应使用流式类 XmlReader 和 XmlWriter,它们顺序处理数据,无需加载整个文档。
使用 XmlReader 读取
using (XmlReader reader = XmlReader.Create("large.xml")){ while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "record") { string id = reader.Get