C# XML文件解析方法 C#如何使用Linq to XML解析XML

来源:这里教程网 时间:2026-02-21 17:40:22 作者:

XDocument
加载 XML 文件最稳妥

直接用

XDocument.Load()
读取本地文件或流,比
XElement.Load()
更适合带声明、注释、处理指令的完整 XML 文档。它保留根节点上下文,后续查子节点、命名空间更可靠。

如果 XML 文件路径含中文或特殊字符,先确保文件编码是 UTF-8(无 BOM);否则可能抛
XmlException: Data at the root level is invalid
网络响应流(如
HttpWebResponse.GetResponseStream()
)必须可重读,否则
XDocument.Load()
可能读空 —— 建议用
new StreamReader(stream).ReadToEnd()
转成字符串再用
XDocument.Parse()
不推荐用
XmlReader.Create()
配合
XDocument.Load()
做预过滤,除非 XML 超大(百 MB 级),否则徒增复杂度

查询节点时小心默认命名空间

很多真实 XML(如 Office Open XML、SOAP 响应)带

xmlns="http://..."
。此时用
doc.Descendants("Item")
查不到任何节点 —— 因为
"Item"
被当作无命名空间名,而实际节点属于默认命名空间。

先提取默认命名空间:
XNamespace ns = doc.Root.GetDefaultNamespace();
查询时显式拼接:
doc.Descendants(ns + "Item")
若 XML 有多个前缀(如
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
),用
doc.Root.GetNamespaceOfPrefix("xsi")
获取对应
XNamespace
忽略命名空间强行查(仅调试用):
doc.Descendants().Where(e => e.Name.LocalName == "Item")
,但会丢失命名空间语义,慎用于生产

Elements()
Descendants()
别混用

两者行为差异直接影响性能和结果:

root.Elements("Child")
:只查直接子元素,层级明确,速度快,适合已知结构
root.Descendants("Child")
:递归查所有后代,可能跨多层,易误匹配(比如嵌套的同名子节点)
若 XML 深度大、节点多,
Descendants()
可能触发全树遍历;高频调用建议先缓存
IEnumerable<xelement></xelement>
结果,而非反复调用
想查“某元素下的第一个
Value
”,别写
e.Descendants("Value").First()
,改用
e.Elements("Group").Elements("Value").FirstOrDefault()
,更精准也更快
var doc = XDocument.Load("config.xml");
XNamespace ns = doc.Root.GetDefaultNamespace();
// 正确:带命名空间查询
var items = doc.Root.Element(ns + "Data")
                 .Elements(ns + "Record")
                 .Select(r => new {
                     Id = (int)r.Element(ns + "Id"),
                     Name = (string)r.Element(ns + "Name")
                 }).ToList();
命名空间处理和层级选择是出错最多的地方,尤其当 XML 来自第三方服务时,务必先用
doc.ToString()
打印结构确认根节点声明和实际元素路径。

相关推荐