在 Java 中直接使用 JAXP 而不是 DOM/SAX 有啥好处?

Posted

技术标签:

【中文标题】在 Java 中直接使用 JAXP 而不是 DOM/SAX 有啥好处?【英文标题】:What is the advantage of using JAXP instead of DOM / SAX directly in Java?在 Java 中直接使用 JAXP 而不是 DOM/SAX 有什么好处? 【发布时间】:2016-04-09 02:28:56 【问题描述】:

作为 XML 解析的新手,我试图了解不同的技术。针对不同需求的不同技术数量之多令人困惑:

W3C-DOM XOM jDom JAXP JAXB DOM 萨克斯 StAX TrAX 伍德斯托克斯 dom4j 深红色 VTD-XML Xerces-J 蓖麻 XStream ...

仅举几例。

DOM 和 SAX 似乎是解析和处理 XML 的一种低级方式,因此我决定专注于在不同来源中被提及最多且是低级的方式:

DOM、SAX、JAXP。

我在***、JAXP-Tutorial from Oracle、XML-Parsing in general 等网站上阅读了有关解析器的一般信息。

我也尝试过一些教程,如this german one 等。

我现在对 DOM 和 SAX 有了一点了解,但使用 JAXP 的原因仍然超出我的理解。在内部使用 DOM、SAX、... 似乎更像是一个接口,但为什么不直接使用 DOM 或 SAX 呢?

通俗地说使用 JAXP 有什么好处?

【问题讨论】:

当我使用(操作/创建)xml 时,我总是使用 DOM,但这只是我个人的看法!我认为它工作得很好,并提供了您需要的所有功能。 这可能会帮助你jaxp.java.net/1.4/JAXP-FAQ.html ParkerHalo:DOM 似乎是一种使用 XML 的非常直观的方式。不使用 DOM 的主要原因通常被表述为文档的大小,但人们只说“如果文档太大,使用 SAX 而不是 DOM”,而从未定义“大”的含义——代码行数、文档以 MB 为单位的大小、xml 对象的数量……以及发生这种情况的数量。 20,000 行被认为是大行还是 1,000,000 行等等。 @hamena314 当内存不足时,您会注意到什么是大的(使用 DOM 不会花费太多时间)。至于 JAXP,它只是一个旧术语(用于 XML 处理的 Java Api)来指代 SAX/DOM/StAX 解析器。你不能真正“使用”JAXP。 @Kayman 这是我必须注意的事情(因为每次使用解析器时环境都不同),还是有“经验法则”,即超过 X MB,超过 Y 行代码等?因为在完成所有实现之后才注意到似乎为时已晚。 【参考方案1】:

JAXP 只是 Sun(现在是 Oracle)对它们与 JDK 捆绑在一起的 SAX 和 DOM 类集合的名称。如果您使用 JAXP,那么您也在使用 SAX 和/或 DOM。这不是一回事。

JAXP 还在 javax.xml.parsers 包中添加了一些帮助类,它们填补了 SAX 1 和 DOM 1 中的空白,即 15 多年前这些库的旧版本。然而,这些对于今天使用的 SAX2/DOM3 来说不是必需的。更糟糕的是,诸如 DocumentBuilderFactory 和 SAXParserFactory 之类的 javax.xml.parsers 类的设计方式令人困惑(默认情况下它们不知道命名空间),因此它们几乎总是被错误地使用。然后开发人员来这里询问为什么他们的程序没有做他们认为应该做的事情。只需忽略这些类并改用 XMLReaderFactory (SAX 2) 或 DOMImplementationLS (DOM 3)。

【讨论】:

命名空间感知意味着,在 XML 文档中,company 可能有一个名为 adress 的 XML 元素,稍后在文档中,employee 可能有一个名为 @987654324 的 XML 元素@?是那个,你指的是什么?尽管使用了不同的 Factory(?) 类,例如 DOMImplementationLS 而不是 DocumentBuilderFactory,但在使用上还有其他区别吗? @ElliotteRustyHarold 我一直认为 JAXP 是一个接口,但是当你说 Oracle/Sun 使用这个名称来指代“SAX 和 DOM 类的集合”(即具体实现),我认为你是对的。他们在将接口与其具体实现混淆方面有着非常糟糕的记录。 @hamena314 除了构建器和工厂类之外,JAXP SAX 和常规 SAX 在使用上没有区别。它们是相同的类。它们只是与 JDK 捆绑在一起。 DOM 的答案相同。在这种情况下,命名空间感知与解析器如何将本地名称和限定名称传递给哪些方法有关。您总是希望将其打开,而 javax.xml.parsers 类默认将其关闭。 :-(【参考方案2】:

(虽然你没有这么明确地说,但你的问题似乎只与 Java 世界有关,这个答案反映了这一点。)

JAXP 是一组涵盖 XML 解析、XSLT 转换和 XML 模式验证的接口。如果我们只关注 XML 解析方面,它的主要贡献是提供了一种定位 XML 解析器实现的机制,因此您的源代码不会被锁定到特定产品中。坦率地说,这些天来它的价值有限。仅有的两个常用的 SAX/DOM 解析器是嵌入在 JDK 中的一个和 Apache Xerces。 Apache Xerces 在各方面都更好,只是需要单独下载。

至于其他解析接口,它们分为两类:基于事件的 API 和基于树的 API。基于树的 API 更易于使用,但在处理大型文档时会占用大量内存。

两个主要的基于事件的 API 是 SAX(推送)和 StAX(拉取)。拉解析是许多程序员发现的更容易的事情,因为您可以使用程序堆栈来维护状态信息;不幸的是,尽管 StAX API 有点错误 - 不同的实现以不同的方式修复了它的差距。 StAX 最完整和最可靠的实现是 Woodstox 解析器; SAX 最完整和最可靠的实现是 Apache Xerces。但不要尝试使用基于事件的解析方法,除非您的应用程序确实需要该级别的性能(并且除非您具有避免失去应用程序级别的所有性能提升所需的经验级别。)

对于基于树的 API,DOM 仍然占主导地位,仅仅是因为它是由 W3C 定义并在 JDK 中实现的,因此被视为“标准”;它也是所有有关该主题的书籍中提到的。然而,在所有树模型中,毫无疑问,它是设计最差的(主要是因为它早于名称空间的引入)。替代方案包括 JDOM2、DOM4J、XOM 和 AXIOM。我倾向于推荐 JDOM2 或 XOM。

【讨论】:

你说得对,我已经更改了我的标题,以便在其中包含“Java”。所以 JAXP 是某种包含 DOM/SAX(XML 解析)、XSLT、...的盒子?如果我直接使用 DOM / SAX,我间接地“使用”了 JAXP,因为 DOM 和 SAX 源自 JAXP?我已经阅读了一些关于 XOM 的评论,它似乎相当不错,但是许可证 (LGPL) 可能会让我很难在我的项目中使用它。但我必须阅读更多相关内容。 注意,JDK中的SAX/DOM实现是基于Apache Xerces,实际上比原来的维护得更好。 @AndreasVeithen,是的,它是原版的一个分支。但它有一些非常严重的错误,这些错误在驴子的岁月里(嗯,至少从 2009 年开始)就已经知道了,而且从未修复过。当你报告他们时,你甚至没有得到任何确认,他们只是进入了一个黑洞。 @hamena314,我不会将 JAXP(特别是 JAXP 的 XML 解析部分)描述为“包含”DOM/SAX 服务,更像是一种让您能够找到 DOM 供应商的路由器/SAX 服务。区别在于,如果您知道要使用的 DOM/SAX 实现的类名,并且不希望跨不同实现的可移植性,那么您通常可以绕过 JAXP 搜索机制。 @AndreasVeithen 有关此类错误的示例,请参阅bugs.java.com/bugdatabase/view_bug.do?bug_id=8145969。虽然这是最近报告的,但这是一个非常古老的错误,我至少在五年前报告了它,尽管我在 Oracle 数据库中找不到我以前的报告(只有一封来自我给客户的电子邮件,告诉他们我已经报告了它) .

以上是关于在 Java 中直接使用 JAXP 而不是 DOM/SAX 有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章

使用 XSD、目录解析器和用于 XSLT 的 JAXP DOM 验证 XML

使用JAXP进行XM解析(基于DOM)

jaxp使用笔记

解析xml

SAX,DOM,JAXP,JDOM,DOM4J比较

解析xml