LINQ to XML 查询带命名空间的 XML 必须显式声明 XNamespace 并用 + 运算符组合命名空间与本地名,忽略或字符串拼接命名空间前缀均会导致匹配失败;默认命名空间同样需 XNamespace 处理,属性默认不继承命名空间;多命名空间按 URI 区分,推荐静态声明常量。

处理带命名空间的 XML 时,LINQ to XML 要求你显式声明并使用 XNamespace,否则查询会返回空结果——这是最常见的“查不到数据”原因。
必须用 XNamespace 声明命名空间
不能直接用字符串拼接前缀(如 "ns:Element"),也不能忽略命名空间。正确做法是先定义命名空间对象,再用 + 运算符组合它和本地名:
-
错误写法:
doc.Descendants("Book")(没带 ns,匹配失败) -
正确写法:
XNamespace ns = "http://example.com/bookstore"; doc.Descendants(ns + "Book")
处理默认命名空间(无前缀)要特别小心
如果 XML 中用了 xmlns="http://example.com/bookstore"(即没有前缀的默认命名空间),它依然生效,但容易被忽略。此时仍需用 XNamespace,且不能写成 ns + "" 或空字符串:
- 定义:
XNamespace ns = "http://example.com/bookstore"; - 查询元素:
doc.Root?.Elements(ns + "Book") - 获取属性(默认 ns 不影响属性,除非属性也带 ns):
elem.Attribute("id")即可,不用加 ns
多个命名空间时,为每个 URI 创建独立 XNamespace 实例
不同前缀可能指向同一 URI,也可能不同 URI 对应不同前缀。LINQ to XML 只认 URI,不认前缀名。所以:
XNamespace ns1 = "http://a.com"; XNamespace ns2 = "http://b.com";- 即使 XML 中写的是
xmlns:p="http://a.com" xmlns:q="http://a.com",ns1和ns2仍是两个对象,但只要 URI 相同,ns1 + "X"和ns2 + "X"实际等价 - 推荐按 URI 命名变量(如
bookNs,authNs),避免混淆
加载时无需特殊配置,但解析前必须准备好命名空间
XDocument.Load() 或 XDocument.Parse() 本身不关心命名空间,也不会自动注册前缀。所有查询逻辑都依赖你手动构造的 XNamespace:
- 可以提前定义全局常量:
public static readonly XNamespace BookNs = "http://example.com/bookstore"; - 也可以在方法内局部声明,只要保证查询时 namespace + localname 组合正确
- 用
GetDefaultNamespace()或Root.GetNamespaceOfPrefix("p")动态获取也可,但静态声明更清晰、性能更好









