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

