C#按路径流式遍历XML节点的实用方法

 更新时间:2025年10月30日 09:51:08   作者:贪嘴  
在处理大型 XML 文档时,传统的 XDocument.Load 会一次性将整个文档加载到内存中,对于大文件非常消耗资源,本文将分享一个按路径流式遍历 XML 节点的实用方法,支持深层嵌套路径,并保持流式解析,需要的朋友可以参考下

引言

在处理大型 XML 文档时,传统的 XDocument.Load 会一次性将整个文档加载到内存中,对于大文件非常消耗资源。尤其在只需要部分节点的场景下,这种方式既浪费内存,又影响性能。

本文将分享一个按路径流式遍历 XML 节点的实用方法,支持深层嵌套路径,并保持流式解析,内存占用低,非常适合大文件处理。

方法原理

流式解析

使用 XmlReader 逐节点读取 XML 文档,而不是一次性加载整个文档,节省内存。

按路径过滤节点

用户只需提供路径,例如 "set/fields/field",方法会按照路径递归查找目标元素。

XNode.ReadFrom 创建完整 XElement

当读到目标元素时,使用 XNode.ReadFrom(reader) 构建 XElement,包括子节点及结束标签,并将 XmlReader 定位到下一个兄弟节点,保证流式遍历不中断。

递归获取子节点

对于多级路径,使用递归方法从 XElement 访问子节点

使用示例

假设有如下 XML:

<set>
  <fields>
    <field>
      <fieldname>rq</fieldname>
      <datatype>字符</datatype>
    </field>
    <field>
      <fieldname>djbh</fieldname>
      <datatype>字符</datatype>
    </field>
  </fields>
</set>

调用:

string xmlstr = File.ReadAllText("example.xml");

var fields = XmlStreamHelper.StreamElements(xmlstr, "set/fields/field");

Console.WriteLine("字段数量:" + fields.Count());
foreach (var f in fields)
{
    Console.WriteLine(f.Element("fieldname")?.Value);
}

输出:

字段数量:2
rq
djbh

优点总结

  1. 内存占用低:大 XML 文件也能按需遍历,不会一次性加载整个文档。
  2. 路径灵活:支持任意深度路径,按需获取节点。
  3. 避免 ReadSubtree 陷阱:使用 XNode.ReadFrom 与递归子节点,状态管理清晰。
  4. 延迟执行:返回 IEnumerable<XElement>,可以直接在 foreach 中流式消费。

扩展思路

  1. 可以在路径中增加通配符 * 或 //,支持 XPath-like 查找。
  2. 可以结合 yield return,实现大文件边解析边处理,适合数据清洗、日志分析、报表导出等场景。

完整代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

public static class XmlStreamHelper
{
    /// <summary>
    /// 按路径流式遍历 XML 节点,路径用 / 分隔
    /// </summary>
    /// <param name="xmlstr">XML 字符串</param>
    /// <param name="xpath">节点路径,例如 "set/fields/field"</param>
    public static IEnumerable<XElement> StreamElements(string xmlstr, string xpath)
{
    if (string.IsNullOrWhiteSpace(xmlstr) || string.IsNullOrWhiteSpace(xpath))
        yield break;

    var nodes = xpath.Split('/');
    using var reader = XmlReader.Create(new StringReader(xmlstr), new XmlReaderSettings { IgnoreWhitespace = true, IgnoreComments = true });
    reader.MoveToContent();

    if (nodes.Length == 1)
    {
        if (XNode.ReadFrom(reader) is XElement el)
        {
            foreach (var e in el.Elements(xpath))
            {
                yield return e;
            }
        }
    }
    else
    {
        while (reader.Read())
        {
            if (reader.NodeType != XmlNodeType.Element) continue;

            if (reader.Name == nodes[0] && XNode.ReadFrom(reader) is XElement el)
            {
                foreach (var child in GetElementsRecursive(el, nodes, 1))
                    yield return child;
            }
        }
    }
}

    /// <summary>
    /// 递归获取子节点
    /// </summary>
    private static IEnumerable<XElement> GetElementsRecursive(XElement el, string[] nodes, int index)
    {
        if (index == nodes.Length - 1)
            return el.Elements(nodes[index]);

        var sub = el.Element(nodes[index]);
        return sub == null ? Enumerable.Empty<XElement>() : GetElementsRecursive(sub, nodes, index + 1);
    }
}

到此这篇关于C#按路径流式遍历XML节点的实用方法的文章就介绍到这了,更多相关C#流式遍历XML节点内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解LINQ入门(中篇)

    详解LINQ入门(中篇)

    这篇文章主要介绍了详解LINQ入门(中篇),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • C#使用Ado.net读取Excel表的方法

    C#使用Ado.net读取Excel表的方法

    这篇文章主要介绍了C#使用Ado.net读取Excel表的方法,涉及C#使用OLEDB操作Excel的方法,需要的朋友可以参考下
    2015-04-04
  • C#窗体间通讯的几种常用处理方法总结

    C#窗体间通讯的几种常用处理方法总结

    这篇文章主要介绍了C#窗体间通讯的几种常用处理方法总结,有很好的实用价值,需要的朋友可以参考下
    2014-08-08
  • WPF在VisualTree上增加Visual

    WPF在VisualTree上增加Visual

    这篇文章介绍了WPF在VisualTree上增加Visual的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • 基于C# 实现 OPC DA Server的问题小结

    基于C# 实现 OPC DA Server的问题小结

    这篇文章主要介绍了基于C# 实现 OPC DA Server的相关知识,关于C#怎么编写一个进程外的DCOM组件,这里先不做介绍了,这里主要介绍下OPC DA Server 的第一个接口,感兴趣的朋友跟随小编一起看看吧
    2024-04-04
  • c# 获取机器唯一识别码的示例

    c# 获取机器唯一识别码的示例

    这篇文章主要介绍了c# 获取机器唯一识别码的示例,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03
  • 程序中两个Double类型相加出现误差的解决办法

    程序中两个Double类型相加出现误差的解决办法

    本篇文章介绍了,程序中两个Double类型相加出现误差的解决办法。需要的朋友参考下
    2013-04-04
  • C# 守护进程的介绍及实现详解

    C# 守护进程的介绍及实现详解

    本文主要介绍了C# 守护进程的介绍及实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • VMS中解协议常用方法备忘(小结)

    VMS中解协议常用方法备忘(小结)

    这篇文章主要介绍了VMS中解协议常用方法备忘(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • C# 打开蓝牙设置界面的两种方法

    C# 打开蓝牙设置界面的两种方法

    这篇文章主要介绍了C# 打开蓝牙设置界面的两种方法,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07

最新评论