如何从XML反序列化Java对象?

我相信这可能已经详细讨论或回答过,但是我需要更多关于我的情况的最佳方法的信息……

问题:
我们有一些大型XML数据(从100k到5MB不等),我们需要将它们扩展到Java对象中。 问题是数据根本不能很好地映射到对象上,所以我们只需要拉出数据的某些部分并创建对象。 鉴于此,JAXB或XStream等解决方案确实不合适。

因此,我们需要将XML数据拉出并尽可能高效地将其转换为java对象。

可能的解决方案:
我看到它的方式,我们有3种可能的解决方案:

  • SAX解析
  • DOM解析
  • XSLT

我们可以将XML加载到任何JAXP实现中,并使用上述方法之一拉出数据。

问题(S)
我有几个问题/疑虑:

  • XSLT如何在幕后工作? 它只是一个DOM解析器吗? 我问,因为XSLT似乎是一个很好的方法,但我真的不想考虑它,如果它不会给我们比DOM更好的性能。
  • 有哪些流行的库提供DOM,XSLT和SAX XML解析器?
  • 根据您的经验,选择DOM,SAX或XSLT的原因是什么? DOM或XSLT的易用性是否完全支配SAX提供的性能改进?
  • 那里有任何基准吗? 我发现的那些是旧的(如8岁)。 因此,最近的一些基准将不胜感激。
  • 除了上面提到的那些我还有什么其他解决方案可能会丢失吗?

编辑:
一些说明……您可以使用XSLT直接将值注入Java对象…它通常用于将XML转换为其他XML,但我是从调用XSLT到java的方法的角度来谈论注入价值。

我还不清楚XSLT处理器是如何正常工作的…它如何将XML提供给你编写的XSLT代码?

使用XSLT将大型XML文件转换为使用JAXB映射到java对象的本地域模型。

从内置XML库的JDK 5+开始(除非你绝对需要XSLT 2.0,在这种情况下使用Saxon)

不要专注于SAX / DOM的相对性能,专注于学习如何编写XPath表达式并使用XSLT,然后担心以后的性能,当且仅当您发现它是一个问题时。

Eclipse XML编辑器很不错,但如果你能负担得起,可以选择Oxygen XML,它可以让你实时进行XPath评估。

我们有类似的情况,我只是把一些XPath代码汇总在一起,解析了我需要的东西。

即使在100k + XML文件上也非常快。 我们尽可能地低技术。 我们每天处理大约1000个文件,解析时间非常短。 我们没有内存问题,泄漏等。

我们在Groovy中写了一个快速原型(如果我的记忆准确的话) – 概念certificate花了我大约10分钟

JAXB ,XML绑定的Java API可能就是您想要的。 您可以使用它将XML文档扩展为由“Java内容对象”组成的Java对象图。 这些内容对象是JAXB生成的类的实例,以匹配XML文档的模式

但是,如果您已经拥有一组Java类,或者还没有该文档的架构,那么JAXB可能不是最好的方法。 我建议做一个SAX解析,然后在解析期间构建你的Java对象。 或者,您可以尝试DOM解析,然后遍历生成的Document树以提取感兴趣的部分(可能使用XPath) – 但是5MB的XML可能会变成Java中的50MB DOM树对象。

DOM,SAX和XSLT是不同的动物。

DOM解析将整个文档加载到内存中,对于100K到5MB(按照今天的标准来说非常小)可以工作。

SAX是一个流解析器,它读取XML并将事件传递给每个标记的代码。

XSLT是一个将一个XML树转换为另一个XML树的系统。 即使您编写了将输入转换为更合适格式的转换,您仍然必须使用DOM或SAX编写一些内容以将其转换为Java对象。

您可以使用EclipseLink JAXB(MOXy)中的@XmlPath扩展来轻松处理此用例。 有关详细示例,请参阅:

示例代码:

package blog.geocode; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.eclipse.persistence.oxm.annotations.XmlPath; @XmlRootElement(name="kml") @XmlType(propOrder={"country", "state", "city", "street", "postalCode"}) public class Address { @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:Thoroughfare/ns:ThoroughfareName/text()") private String street; @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:LocalityName/text()") private String city; @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:AdministrativeAreaName/text()") private String state; @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:CountryNameCode/text()") private String country; @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:PostalCode/ns:PostalCodeNumber/text()") private String postalCode; }