如何有效地在Web应用程序中搜索大型XML文件?

时间:2014-08-31 08:22:57

标签: java xml sax

我有一个XML文档,我需要通过webapp进行搜索。该文件目前只有6mb ..但可能非常大,因此从我的研究SAX似乎是要走的路。

所以我的问题是,给我一个搜索词:

  1. 我是否将文档加载到内存中一次(进入bean列表然后再加载 把它存放在内存中)?然后在需要时搜索它? 或

  2. 解析文档以查找所需的搜索词并仅添加     匹配豆类列表?并重复这个过程     搜索?

  3. 我对webapps没有经验,但我想找到解决这个问题的最佳方法,Tomcat,SAX和Java Web应用程序的任何人都有什么建议可以达到最佳效果吗?

    此致 内特

3 个答案:

答案 0 :(得分:1)

假设您的搜索字段是您已知的字段,例如让xml的结构为:

<a>....</a>
<x>
<y>search text1</y>
<z>search text2</z>
</x>
<b>...</b>

并说必须在&#39; x&#39;上进行搜索。和它的孩子,你可以使用STAX解析器和JAXB来实现这一点。

要了解STAX和SAX之间的区别,请参阅:

When should I choose SAX over StAX?

使用这些API可以避免将整个文档存储在内存中。使用STAX解析器,当您遇到&#39; x&#39; tag使用JAXB将其加载到内存(java bean)中。

注意:只有x及其子项将被加载到内存中,而不是整个解析到目前为止的文档。 不要使用任何使用DOM解析器的方法。

示例代码,仅加载存在搜索字段的文档部分。

XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("file");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("x")) {
    xsr.nextTag();
}

JAXBContext jc = JAXBContext.newInstance(X.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, X.class);
xsr.close();

X x = jb.getValue();
System.out.println(x.y.content);

现在您有字段内容来返回相应的字段。当用户再次在&#39; x&#39;下搜索相同的字段时,从内存中提取结果并避免再次解析XML。

答案 1 :(得分:1)

如果您说您的XML文件可能非常大,我认为您不希望将其保留在内存中。如果你想要它是可搜索的,我知道你想要索引访问,而不是每次都有完整的读取。恕我直言,实现这一目标的唯一方法是解析文件并将数据加载到轻量级文件数据库(Derby,HSQL或H2)中,并将相关索引添加到数据库中。数据库允许对关闭内存数据进行索引搜索,而XML文件则不允许。

答案 2 :(得分:0)

使用XPath或XQuery搜索文件的速度可能非常快(除非你每秒都在谈论成千上万的事务)。解析文件需要花费时间 - 在内存中构建树,以便XPath或XQuery可以搜索它。所以(正如其他人所说)很大程度上取决于文件内容的变化频率。如果更改很少,您应该能够在共享内存中保留文件的副本,因此解析成本会在许多搜索中分摊。但如果经常发生变化,情况会变得更加复杂。您可以尝试在磁盘上保留原始XML的副本,并在内存中保留已解析的XML的副本,并使两者保持同步。或者你可以咬紧牙关并转向使用XML数据库 - 最初的努力最终会得到回报。

如果您想在每次搜索时解析文件,那么“SAX是要走的路”的评论才会成立。如果您这样做,那么您希望以最快的方式解析文件。但更好的方法是避免在每次搜索时重新解析它。