使用 xmlReader 在 C# 中过滤特定元素值的大型 XML
Posted
技术标签:
【中文标题】使用 xmlReader 在 C# 中过滤特定元素值的大型 XML【英文标题】:Filter Large XML for specific element value in C# Using xmlReader 【发布时间】:2021-09-03 01:05:27 【问题描述】:在这个线程中: Filter XML for specific element value in C#
我能够使用XDocument
过滤xml
文件以查找特定元素。但是,对于巨大的xml
文件,XDocument
似乎不是一个可行的解决方案,因为它会因System.OutOfMemoryException
消息而失败。挖掘了一下,看起来xmlReader
在处理大型xmls
时内存效率更高。
如何重写接受的答案,使用xmlReader
,得到相同的结果?
【问题讨论】:
您的 xaml 是否具有静态结构?如果是这样,您可以尝试将其导入 c# 类 是的,反序列化它,然后砰!用你喜欢的方式过滤它。这不是一个选项吗? @Emanuele 是的,结构是静态的。您能否使用上述链接中的相同 xml 粘贴执行此操作的代码? 【参考方案1】:请尝试以下解决方案。
它的可扩展性很强,可以毫无问题地处理多 GB 大小的 XML 文件。
XStreamingElement 正在使用一种扩展方法,该方法使用 XmlReader
流式传输由 <section>Section 1</section>
节点过滤的源 XML。
c#
void Main()
const string inputXMLFile = @"e:\Temp\Sanosi.xml";
const string outputXMLFile = @"e:\Temp\Sanosi_Streamed.xml";
const string ROW = "Entry";
const string FILTER = "Section 1";
// Stream XML to file system
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
timer.Start();
// Shape output XML
XStreamingElement newXML = new XStreamingElement("root",
from element in StreamElements(inputXMLFile, ROW)
.Where(x => x.Element("section").Value.Equals(FILTER))
select new XElement(ROW, element.Elements("image")
));
newXML.Save(outputXMLFile, SaveOptions.OmitDuplicateNamespaces);
FileInfo fileBefore = new FileInfo(inputXMLFile);
FileInfo fileAfter = new FileInfo(outputXMLFile);
timer.Stop();
Console.WriteLine("Streamed XML file '0', 1 bytes to file system as: '2', 3 bytes5Elapsed time: 4",
fileBefore.FullName
, fileBefore.Length
, fileAfter.FullName
, fileAfter.Length
, timer.Elapsed
, Environment.NewLine);
private static IEnumerable<XElement> StreamElements(string fileName, string elementName)
using (var rdr = XmlReader.Create(fileName))
rdr.MoveToContent();
while (rdr.Read())
if ((rdr.NodeType == XmlNodeType.Element) && (rdr.Name == elementName))
var e = XElement.ReadFrom(rdr) as XElement;
yield return e;
rdr.Close();
【讨论】:
这不会解决内存不足的问题。 @jdweng,我经常使用这种方法来处理多 GB XML 文件。 Windows 10 操作系统任务管理器未显示任何内存使用高峰。 @jdweng,请在 LinkedIn 上与我联系。 您没有使用像 OP 这样的大文件。带有大文件的 XML linq 经常出现内存不足错误。解决的唯一方法是像我发布的代码一样使用 XmlReader。阅读问题。你的机器可能比 OP 有更多的内存。 @jdweng,仅供参考,使用该技术,我能够在具有 8 GB RAM 的机器上处理大小为 30+ GB 的 XML 文件。【参考方案2】:我使用这样的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
class Program
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
XmlReader reader = XmlReader.Create(FILENAME);
while (!reader.EOF)
if (reader.Name != "Entry")
reader.ReadToFollowing("Entry");
if (!reader.EOF)
XElement entry = (XElement)XElement.ReadFrom(reader);
【讨论】:
在最后一个 if 语句中获得“entry”xelement 后,如何搜索此元素以检查 Section = Section 1,以便获得我正在寻找的元素?类似 Entry.Descendants().Where(x => x.Element("section").Value.Equals("Section 1")).Elements("image"); 尝试以下操作:List以上是关于使用 xmlReader 在 C# 中过滤特定元素值的大型 XML的主要内容,如果未能解决你的问题,请参考以下文章
C# 使用 XmlReader 但不使用 XmlDocument 获取额外的空白值
XmlReader - 自关闭元素不会触发 EndElement 事件?
XmlReader - 如何在没有 System.OutOfMemoryException 的情况下读取元素中很长的字符串