2011-08-27 27 views
6

输入文件包含数千个大小约为10GB的XML格式的事务。需求是根据用户输入选择每个事务XML并将其发送到处理系统。使用StAX和XPath读取巨大的XML文件

文件

<transactions> 
    <txn id="1"> 
     <name> product 1</name> 
     <price>29.99</price> 
    </txn> 

    <txn id="2"> 
     <name> product 2</name> 
     <price>59.59</price> 
    </txn> 
</transactions> 

的(技术)用户有望给输入的标签名称,如<txn>的样品含量。

我们希望提供此解决方案以使其更通用。文件内容可能不同,用户可以给出一个XPath表达式,如“//transactions/txn”来选择单个事务。

有一些技术方面的东西,我们要在这里考虑

  • 该文件可以是共享位置或FTP
  • 由于文件大小是巨大的,我们不能加载整个文件in JVM

我们可以在这种情况下使用StAX解析器吗?它必须将XPath表达式作为输入并选择/选择事务XML。

寻找建议。提前致谢。

+0

我的建议是使用扩展VTD-XML在MEM地图模式和64位jvm –

回答

8

Stax和xpath是非常不同的东西。 Stax允许您仅向前解析流式XML文档。 Xpath允许在两个方向上解析。 Stax是一个非常快速的流式XML解析器,但是,如果你想要xpath,java有一个单独的库。

看看这个问题,一个非常类似的讨论:Is there any XPath processor for SAX model?

+2

如果你打算让我失望,请留下评论。这样每个人都学会了! – Jon7

+0

因为您的声明“Stax和xpath是非常不同的东西”而导致投票不正确。 XPath(至少它的子集)仍然可以在Stax模型(拉式模型)中实现。它在C#中实现https://msdn.microsoft.com/en-us/library/ms950778.aspx – TriCore

0

你需要快速处理它还是需要快速查找数据?这些要求需要不同的方法。

要快速读取整个数据,StAX将会正常。如果您需要快速查找,而不是将其加载到某个数据库,则可以使用Berkeley DB XML(例如,

1

这绝对是一个用例XPROC流播和并行处理实现像QuiXProc(http://code.google.com/p/quixproc

在这种情况下,你将不得不使用

<p:for-each> 
    <p:iteration-source select="//transactions/txn"/> 
    <!-- you processing on a small file --> 
    </p:for-each> 

你甚至可以wrapp每个随之变换与XPROC

单行
<p:wrap-sequence wrapper="transactions"/> 

希望这有助于

1

我们通过使用SAX解析器定期解析1GB +复杂的XML文件,该解析器完全符合您的描述:它可以提取部分DOM树,可以使用XPATH方便地进行查询。

我陷入了困境here - 它使用SAX而不是StAX解析器,但值得一看。

13

如果性能是一个重要因素,和/或文档大小很大(这两种情况似乎都是这种情况),事件解析器(如SAX或StAX)与本机Java XPath实现之间的区别是后者在评估XPath表达式之前构建W3C DOM文档。 [有趣的是要注意,像DOM或Axiom这样的所有Java文档对象模型实现都使用事件处理器(如SAX或StAX)来构建内存中的表示形式,所以如果只能使用事件处理器,节省内存和建立DOM所需的时间。]

正如我所提到的,JDK中的XPath实现在W3C DOM Document上运行。

Document document = getParser().parse(source); 

这是你的XML的10GB后,将代表:您可以通过查看com.sun.org.apache.xpath.internal.jaxp.XPathImpl,在之前的评估()方法被调用的解析器必须先分析源在Java JDK源代码实现看到这在内存中(加上任何开销)—可能不是你想要的。虽然您可能需要更“通用”的解决方案,但您的示例XPath和XML标记看起来都相对简单,所以似乎没有真正强有力的XPath理由(除了编程优雅)。对于XProc的建议也是如此:这也会构建一个DOM。如果你真的需要一个DOM,你可以使用Axiom而不是W3C DOM。 Axiom有一个非常友好的API,并通过StAX构建它的DOM,因此速度很快,并且使用Jaxen来实现它的XPath。 Jaxen需要一些种类的DOM(W3C DOM,DOM4J或JDOM)。这对于所有的XPath实现都是正确的,所以如果你不真的需要XPath粘贴,那么推荐使用事件解析器。

SAX是旧的流媒体API,StAX更新,速度更快。无论是使用本地JDK StAX实现(javax.xml.stream)还是使用Woodstox StAX实现(根据我的经验,这个实现速度都要快得多),我建议创建一个XML元素类型名称匹配的XML事件过滤器(以捕获您的<txn>元素)。这将创建可以针对您的匹配用户值进行检查的小事件(元素,属性,文本)。在适当的匹配之后,如果您发现结果更容易导航,您可以从事件中提取必要的信息,或者管理有界事件以从中构建迷你DOM。但是,如果标记很简单,这听起来可能是过度的。

这可能是最简单,最快的方法,并避免构建DOM的内存开销。如果您将元素和属性的名称传递给过滤器(以便您的匹配算法可配置),则可以使其相对通用。

+0

你听说过vtd-xml吗? –

+0

直到你的评论,没有我没有。我已经下载了发行版,并且很乐意尝试。它如果按照我声称的那样执行,我会考虑在生产环境中使用它,但如果您愿意也可以在LGPL或Apache下发布vtd-xml,那么我看到的一个故障倾向于问我(因为您是其作者)执照?我们无法在我们的环境中使用GPL。无论如何谢谢你的提示。 –

+0

您是分发代码还是仅在内部使用它? –

0

用于处理大于10GB的大型XML文件的有趣解决方案。

  1. 使用ANTLR为感兴趣的部分创建字节偏移量。与基于DOM的方法相比,这将节省一些内存。
  2. 使用JAXB读取字节位置零件

在维基百科的例子查找信息转储(17GB)在此SO回答https://stackoverflow.com/a/43367629/1485527