SAX解析器可以在Java中使用XPath吗?

SAX解析器可以在Java中使用XPath吗?,java,xml,dom,xpath,sax,Java,Xml,Dom,Xpath,Sax,我正在尝试将我的一个类迁移到SAX解析,该类使用大量XPath表达式进行DOM解析DOM解析对我来说很好,但是我尝试解析的一些文件太大,它们会导致服务器超时。我想将XPath与SAX解析一起重用,但我不确定这是否可能,如果不可能,请您帮助我,因为我不知道当我只使用SAX时,下面的代码会是什么样子: Document doc = bpsXml.getDocument(); String supplierName = BPSXMLUtils.getXpathString(doc, "/Invoice

我正在尝试将我的一个类迁移到
SAX
解析,该类使用大量
XPath
表达式进行
DOM
解析<代码>DOM解析对我来说很好,但是我尝试解析的一些文件太大,它们会导致服务器超时。我想将
XPath
SAX
解析一起重用,但我不确定这是否可能,如果不可能,请您帮助我,因为我不知道当我只使用
SAX
时,下面的代码会是什么样子:

Document doc = bpsXml.getDocument();
String supplierName = BPSXMLUtils.getXpathString(doc, "/Invoice/InvoiceHeader/Party[@stdValue='SU']/Name/Name1");
String language = BPSXMLUtils.getXpathString(doc, "/Invoice/InvoiceHeader/InvoiceLanguage/@stdValue");

处理XML最简单的方法是使用XML流API。它结合了DOM和SAX的优点(并为您提供了一个更简单的迁移)。您仍然有一个指向XML元素的游标(如在SAX中),但您的代码将游标向前移动。这使得XML处理代码的可读性大大提高。它还解决了内存问题,因为只有当前XML元素必须保存在内存中。这也是一个很好的例子


还要回答您最初的问题:在Google上进行的一次简短搜索向我表明,没有一种简单、被广泛接受的方法,这可能意味着所有自定义解决方案都不健壮、不可维护且未经良好测试。

仅使用SAX解析器无法在内存中构建XML树的表示(这就是SAX更高效的内存的原因). 它只会在遇到新的XML元素时触发“事件”。您必须在内存中保留上下文(通常是父元素的堆栈),才能“知道”您在树中的位置

由于内存中没有树,因此无法使用XPath。您只能测试当前“上下文”(manuallay托管堆栈)来查询文档。请记住,SAX解析器只会在您的文件上运行一次,因此文件中的顺序很重要


幸运的是,还有其他方法,比如在内存中构建XML树的库,但只有结构部分,它不会从文件中提取实际内容,而是根据需要提取内容。在仍然允许XPath的情况下,它比DOM解析器的内存效率要高得多。我个人经常在工作中使用这个库来用XPath解析~700MB的XML文件(是的,这很疯狂,但它工作起来很快。)

切换到SAX解析(或StAX)需要完全改变您的方法。看起来你还没有完全意识到这将是多么艰巨的工作。对于任何有意义的建议,我们需要知道文件有多大,以及您希望对数据进行何种处理。例如,如果要过滤数据,那么使用文档投影的XQuery实现可能是一个很好的答案(这将在后台自动使用SAX来构建一个只包含您实际感兴趣的数据子集的树)。

等等,为什么要从使用XPath的DOM切换到SAX?如果是因为您从web获取文件,而服务器发送文件的时间太长,那么请更改获取文件的方式,而不是解析文件的方式。有几个答案提到了可用于此目的的工具和API。这是一个非常好的主意,但在有大量XML元素和短数据组成的大文件(2+GB)时,效果并不理想。实际上,您可以将所需内存减少50/60%。这很好,但当你有非常大的文件时还不够。如今,数据增长越来越快……经过这么多年,我确实用VTD-XML解析了2GB以上的文件。它做得很好,记忆根本不是问题。你有没有试过,有没有不好的经历?你能分享更多信息吗?你给解析程序分配了多少内存(-Xmx)?我的大部分解析都使用默认的Xmx(64mb),但有时为了安全起见,我不得不将其提升到1GB(从内存来看,我不再处理这些主题)。