C#按路徑流式遍歷XML節(jié)點的實用方法
引言
在處理大型 XML 文檔時,傳統(tǒng)的 XDocument.Load 會一次性將整個文檔加載到內存中,對于大文件非常消耗資源。尤其在只需要部分節(jié)點的場景下,這種方式既浪費內存,又影響性能。
本文將分享一個按路徑流式遍歷 XML 節(jié)點的實用方法,支持深層嵌套路徑,并保持流式解析,內存占用低,非常適合大文件處理。
方法原理
流式解析
使用 XmlReader 逐節(jié)點讀取 XML 文檔,而不是一次性加載整個文檔,節(jié)省內存。
按路徑過濾節(jié)點
用戶只需提供路徑,例如 "set/fields/field",方法會按照路徑遞歸查找目標元素。
XNode.ReadFrom 創(chuàng)建完整 XElement
當讀到目標元素時,使用 XNode.ReadFrom(reader) 構建 XElement,包括子節(jié)點及結束標簽,并將 XmlReader 定位到下一個兄弟節(jié)點,保證流式遍歷不中斷。
遞歸獲取子節(jié)點
對于多級路徑,使用遞歸方法從 XElement 訪問子節(jié)點
使用示例
假設有如下 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("字段數(shù)量:" + fields.Count());
foreach (var f in fields)
{
Console.WriteLine(f.Element("fieldname")?.Value);
}
輸出:
字段數(shù)量:2 rq djbh
優(yōu)點總結
- 內存占用低:大 XML 文件也能按需遍歷,不會一次性加載整個文檔。
- 路徑靈活:支持任意深度路徑,按需獲取節(jié)點。
- 避免 ReadSubtree 陷阱:使用
XNode.ReadFrom與遞歸子節(jié)點,狀態(tài)管理清晰。 - 延遲執(zhí)行:返回
IEnumerable<XElement>,可以直接在foreach中流式消費。
擴展思路
- 可以在路徑中增加通配符
*或//,支持 XPath-like 查找。 - 可以結合
yield return,實現(xiàn)大文件邊解析邊處理,適合數(shù)據(jù)清洗、日志分析、報表導出等場景。
完整代碼
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 節(jié)點,路徑用 / 分隔
/// </summary>
/// <param name="xmlstr">XML 字符串</param>
/// <param name="xpath">節(jié)點路徑,例如 "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>
/// 遞歸獲取子節(jié)點
/// </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節(jié)點的實用方法的文章就介紹到這了,更多相關C#流式遍歷XML節(jié)點內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#修改及重置電腦密碼DirectoryEntry實現(xiàn)方法
這篇文章主要介紹了C#修改及重置電腦密碼DirectoryEntry實現(xiàn)方法,實例分析了C#修改及重置電腦密碼的相關技巧,需要的朋友可以參考下2015-05-05
C#中BitConverter.ToUInt16()和BitConverter.ToString()的簡單使用
這篇文章主要介紹了C#中BitConverter.ToUInt16()和BitConverter.ToString()的簡單使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02
解決C# 截取當前程序窗口指定位置截圖的實現(xiàn)方法
本篇文章是對C#中截取當前程序窗口指定位置截圖的實現(xiàn)方法進行了詳細的分析介紹,需要的朋友參考下2013-05-05
C#實現(xiàn)把圖片轉換成二進制以及把二進制轉換成圖片的方法示例
這篇文章主要介紹了C#實現(xiàn)把圖片轉換成二進制以及把二進制轉換成圖片的方法,結合具體實例形式分析了基于C#的圖片與二進制相互轉換以及圖片保存到數(shù)據(jù)庫的相關操作技巧,需要的朋友可以參考下2017-06-06
C# OpenCvSharp實現(xiàn)去除文字中的線條
這篇文章主要為大家詳細介紹了C#如何使用OpenCvSharp實現(xiàn)去除文字中的線條效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-11-11

