【发布时间】:2017-02-22 07:46:00
【问题描述】:
我正在使用 .NET Framework 4.6.2 开发一个用于解析大型 xml 文件的 C# 库。
这个库将成为 Windows 服务的一部分,我不想浪费内存使用 XDocument 一次性加载 XML 文件。
也许有更好的选择,但我决定改用XmlReader。特别是ReadToFollowing这个方法。
我读到 XmlReader 代表一种阅读器,它提供对 XML 数据的快速、非缓存、只进访问。
我要读取的 xml 文件有一个部分,其中包含一些数据,在继续阅读之前我必须检查这些数据。另一个包含更多有用数据的部分,以及 最后一部分非常大,包含大量代码。
如果文件总是有相同的节顺序是好的,但我不确定,这是我的问题,如果文件总是有我上面描述的相同的节顺序。
XML 文件会有相同的节顺序吗?我有它的 XSD 文件,但我不知道这些文件是否描述了它的节中的顺序。
XML 文件的一个例子是这样的(由于保密协议,我无法分享原始文件):
<?xml version="1.0" encoding="UTF-8"?>
<Incomming_Msg xmlns="http://xxx/xxx.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xxx/xxx.2-messages.xsd ">
<DataToCheck>
<Field1>
<SubField1>123456789</SubField1>
</Field1>
<Field2>
<SubField2>123asz11-12asd</SubField2>
<!-- Omitted for brevety -->
</Field2>
<!-- Omitted for brevety -->
</DataToCheck>
<DataToInsert1>
<!-- Omitted for brevety -->
</DataToInsert1>
<DataToInsert2>
<!-- Omitted for brevety -->
</DataToInsert2>
<DataToInsert3>
<!-- Omitted for brevety -->
</DataToInsert3>
<TonsOfCodes>
<CodeLevel>
<Code>
<Serial>1234567890</Serial>
</Code>
</CodeLevel>
<!-- Omitted for brevety -->
<!-- This section could be very very big -->
</TonsOfCodes>
</Incomming_Msg>
例如xml文件如果在文件开头带有TonsOfCodes部分,读取文件找到DataToCheck部分会很慢。
【问题讨论】:
-
<xs:sequence>在 .xsd 文件中表明元素必须按引入顺序排列。如果您可以控制 xml 文件的生成方式,则可以依赖持久顺序。但如果不是 - 那么您需要在内存使用量和需要读取文件的次数之间进行权衡 -
@Fabio 我检查了 XSD 文件,它有一个
<xs:sequence>字段,其序列元素顺序与我预期的相同。谢谢。 -
为了进一步参考,这种技术(由于对文档结构的假设而避免将文档完全加载到内存中)称为流式传输。它对于读取非常大的半结构化文件非常普遍且至关重要。由于 XQuery 之类的声明性语言,一些查询引擎甚至能够以对用户透明的方式执行此操作。
-
@GhislainFourny 我也在寻找更好的方法。如果您想分享更好的技术来做到这一点,我们将不胜感激。
-
@VansFannel 一般来说,我倾向于推荐使用 XPath、XQuery 和 XSLT 等声明性语言来操作 XML,因为它们没有命令式和/或面向对象语言所具有的阻抗不匹配。 XML。有几个很好的 XQuery 引擎,比如 Saxon、Zorba、existDB、BaseX。它们都符合标准,但提供不同类型的附加功能和库。我对 Zorba 比较熟悉,它提供了流式处理大文件的功能,但其他引擎也可能有自己的方式。我希望这会有所帮助!
标签: c# xml xsd xml-parsing