用 XmlDocument
加载并遍历节点最直接
适合中小 XML 文件(几百 KB 以内),语法直观,支持 XPath 查询。注意它会把整个文档加载进内存,大文件容易 OOM。
Load()接收文件路径、
Stream或
TextReader,推荐用
FileStream避免编码问题 根节点是
DocumentElement,子节点用
ChildNodes或
SelectNodes("xpath")
取属性值别忘了判空:node.Attributes["id"]?.Value,否则可能抛
NullReferenceException
var doc = new XmlDocument();
doc.Load("config.xml");
var items = doc.SelectNodes("/root/item");
foreach (XmlNode node in items) {
string name = node["name"]?.InnerText ?? "";
string id = node.Attributes["id"]?.Value ?? "";
}
大文件必须用 XmlReader
流式解析
内存占用恒定,但只能单向读取,不支持随机访问或修改。适用于日志、导出数据等超大 XML(GB 级)。
用XmlReader.Create()构造,传入
XmlReaderSettings关闭 DTD 解析(防 XXE) 核心逻辑靠
Read()+
NodeType判断:只在
XmlNodeType.Element和
XmlNodeType.Text时取值 遇到嵌套结构要自己维护栈或状态机,不能依赖父节点导航
var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit };
using var reader = XmlReader.Create("big.xml", settings);
while (reader.Read()) {
if (reader.NodeType == XmlNodeType.Element && reader.Name == "record") {
reader.Read(); // 跳到内容
if (reader.NodeType == XmlNodeType.Text) {
Console.WriteLine(reader.Value);
}
}
}
XDocument
(LINQ to XML)写起来最简洁
语法糖多,支持 LINQ 查询,适合配置类、结构清晰的小 XML。底层仍是基于
XmlReader,但比
XmlDocument内存更省。
XDocument.Load()和
XElement.Load()都可直接读文件 属性用
element.Attribute("name")?.Value,元素内容用 element.Element("child")?.Value
用 Descendants()替代 XPath 的
//item,但不支持完整 XPath 语法
var doc = XDocument.Load("data.xml");
var items = doc.Root?.Descendants("item")
.Select(x => new {
Id = x.Attribute("id")?.Value,
Name = x.Element("name")?.Value
}).ToList();
解析失败常见原因和绕过方法
不是代码写错,而是 XML 本身不规范。.NET 默认严格校验,稍有偏差就报错。
System.Xml.XmlException: 根级别上的数据无效→ 文件开头有 BOM 或空白字符,用
StreamReader指定编码再传给
XmlReader
无法找到文档类型定义→ 关闭 DTD:
settings.DtdProcessing = DtdProcessing.Prohibit中文乱码 → 不要直接用
File.ReadAllText()读完再 Load,XML 声明里的编码(如
encoding="gb2312")必须被尊重
真正难的不是选哪个 API,而是确认 XML 是否合法、编码是否一致、有没有隐藏控制字符 —— 这些往往比解析逻辑更耗时间。
