LINQ to XML 查询带命名空间的 XML 必须显式声明 XNamespace 并用 + 运算符组合命名空间与本地名,忽略或字符串拼接命名空间前缀均会导致匹配失败;默认命名空间同样需 XNamespace 处理,属性默认不继承命名空间;多命名空间按 URI 区分,推荐静态声明常量。
处理带命名空间的 XML 时,LINQ to XML 要求你显式声明并使用 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")
elem.Attribute("id") 即可,不用加 ns不同前缀可能指向同一 URI,也可能不同 URI 对应不同前缀。LINQ to XML 只认 URI,不认前缀名。所以:
XNamespace ns1 = "http://a.com"; XNamespace ns2 = "http://b.com";xmlns:p="http://a.com" xmlns:q="http://a.com",ns1 和 ns2 仍是两个对象,但只要 URI 相同,ns1 + "X" 和 ns2 + "X" 实际等价bookNs, authNs),避免混淆XDocument.Load() 或 XDocument.Parse() 本身不关心命名空间,也不会自动注册前缀。所有查询逻辑都依赖你手动构造的 XNamespace:
public static readonly XNamespace BookNs = "http://example.com/bookstore";
GetDefaultNamespace() 或 Root.GetNamespaceOfPrefix("p") 动态获取也可,但静态声明更清晰、性能更好