跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

C# Linq to XML查询教程 使用LINQ高效筛选XML数据

用XDocument.Descendants()筛选最稳,它不依赖层级、容错性强;查节点需处理命名空间、用Where()精准过滤、强制转换取值、性能敏感时缓存结果、判空用Any()。 用
XDocument
加
Descendants()
做基础筛选最稳 直接加载 XML 后用
Descendants()
查找节点,比
Elements()
更容错——它不依赖层级深度,也不会因命名空间或空格文本节点崩掉。新手常误用
Elements()
写成
doc.Root.Elements("Item")
,结果 XML 里
Item
前有注释或换行就返回空集合。 实操建议: 始终从
XDocument.Load()
或
XDocument.Parse()
开始,别用过时的
XmlDocument
查任意层级的
Product
节点,写
doc.Descendants("Product")
,不是
doc.Root.Descendants("Product")
(
Root
可能为
null
) 如果 XML 带默认命名空间(比如
xmlns="http://example.com/ns"
),必须先声明
XNamespace
,否则所有字符串匹配都失效 带条件的查询别硬拼字符串,用
Where()
+
Attribute()
或
Element()
想查
?别写
.Where(x => x.ToString().Contains("shipped"))
—— 这会把整个 XML 序列化再搜,慢、不准、还可能误匹配子节点内容。 正确做法是定位到属性或子元素后取值比较: 查属性:
doc.Descendants("Order").Where(o => (string)o.Attribute("Status") == "shipped")
查子元素文本:
doc.Descendants("Product").Where(p => (string)p.Element("Price") != null && (decimal)p.Element("Price") > 100)
注意强制转换:用
(string)
安全取文本(空元素/缺失元素返回
null
),用
(int)
/
(decimal)
转数值(失败抛异常,需确保格式可靠) 性能敏感时避免重复遍历,用
ToList()
或
ToArray()
缓存结果
Descendants()
返回的是延迟执行的
IEnumerable
,每次 foreach 或 Count() 都会重新解析 XML 树。如果后续要多次访问(比如先筛出订单,再分别取客户名、商品列表、总价),不缓存就会反复解析同一段 XML,CPU 和内存开销明显上升。 该缓存就缓存: 确定数据量不大(几千节点以内)且后续要多次读取时,加
.ToList()
一次求值 如果只遍历一次,保持延迟执行反而更省内存 别用
.Count() > 0
判空,改用
.Any()
—— 前者强制走完全部节点,后者找到第一个就停 XML 命名空间不处理,
Descendants("Tag")
永远查不到 这是最隐蔽也最高频的失败原因。只要 XML 文件顶部有
xmlns="http://tempuri.org/"
这类声明,所有未带前缀的元素实际都属于那个命名空间。此时
doc.Descendants("User")
返回空,不是语法错,是“名字对不上”。 解决方法只有一步:声明命名空间并参与查询:
XNamespace ns = "http://tempuri.org/";
然后写
doc.Descendants(ns + "User")
或
doc.Root?.Descendants(ns + "Order")
如果 XML 用了前缀(如
xmlns:ns="http://example.com"
),也要用
ns + "Tag"
,不能直接用
"ns:Tag"
没声明命名空间却写了
ns + "Tag"
会编译失败;声明了但漏加
ns +
,运行时永远查不到——这点连很多老手都会忘。

相关文章