如何从XML反序列化Java对象?
我相信这可能已经讨论了很长时间或回答之前,但我需要一点关于我的情况的最佳方法的更多信息 问题: 我们有一些从100k到5MB的大型XML数据,需要将它们膨胀成Java对象。问题是,数据实际上并没有很好地映射到对象上,所以我们只需要拉出数据的某些部分并创建对象。有鉴于此,像JAXB或XStream这样的解决方案确实不合适 因此,我们需要尽可能高效地提取XML数据并将其导入java对象 可能的解决方案: 在我看来,我们有3种可能的解决方案: SAX解析 DOM解析 XSLT 我们可以将XML加载到任何JAXP实现中,并使用上述方法之一提取数据 问题 我有几个问题/顾虑: XSLT在幕后是如何工作的?它只是一个DOM解析器吗?我问,因为XSLT看起来是一个不错的方法,但如果它不能给我们比DOM更好的性能,我真的不想考虑它。 哪些是提供DOM、XSLT和SAXXML解析器的流行库? 根据您的经验,选择DOM、SAX或XSLT的原因是什么?DOM或XSLT的易用性是否完全主导了SAX提供的性能改进? 有什么基准吗?我发现的那些都是8岁的。因此,近期的一些基准将受到赞赏。 除了上面概述的解决方案之外,还有其他我可能遗漏的解决方案吗? 编辑: 一些澄清。。。您可以使用XSLT直接将值注入Java对象。。。它通常用于将XML转换为其他XML,但我是从将方法从XSLT调用到java以注入值的角度来进行讨论的。如何从XML反序列化Java对象?,java,xml,performance,xslt,Java,Xml,Performance,Xslt,我相信这可能已经讨论了很长时间或回答之前,但我需要一点关于我的情况的最佳方法的更多信息 问题: 我们有一些从100k到5MB的大型XML数据,需要将它们膨胀成Java对象。问题是,数据实际上并没有很好地映射到对象上,所以我们只需要拉出数据的某些部分并创建对象。有鉴于此,像JAXB或XStream这样的解决方案确实不合适 因此,我们需要尽可能高效地提取XML数据并将其导入java对象 可能的解决方案: 在我看来,我们有3种可能的解决方案: SAX解析 DOM解析 XSLT 我们可以将XML加载到
我仍然不清楚XSLT处理器到底是如何工作的。。。如何将XML输入到您编写的XSLT代码中?我们遇到了类似的情况,我只是拼凑了一些XPath代码来解析我需要的东西 即使在100k+XML文件上,速度也惊人地快。我们尽可能降低技术含量。我们每天处理1000个这样大小的文件,解析时间非常短。我们没有内存问题、泄漏等
如果我的记忆准确的话,我们用Groovy编写了一个快速原型-概念验证花了我大约10分钟的时间我们遇到了类似的情况,我只是拼凑了一些XPath代码来解析我需要的东西 即使在100k+XML文件上,速度也惊人地快。我们尽可能降低技术含量。我们每天处理1000个这样大小的文件,解析时间非常短。我们没有内存问题、泄漏等
如果我的记忆准确的话,我们用Groovy编写了一个快速原型——概念验证花了我大约10分钟的时间。DOM、SAX和XSLT是不同的动物 DOM解析将整个文档加载到内存中,按照今天的标准,对于100K到5MB的内存来说非常小 SAX是一个流解析器,它读取XML并为每个标记向代码传递事件
XSLT是用于将一个XML树转换为另一个XML树的系统。即使编写了将输入转换为更合适的格式的转换,也必须使用DOM或SAX编写一些东西来将其转换为Java对象。DOM、SAX和XSLT是不同的动物 DOM解析将整个文档加载到内存中,按照今天的标准,对于100K到5MB的内存来说非常小 SAX是一个流解析器,它读取XML并为每个标记向代码传递事件
XSLT是用于将一个XML树转换为另一个XML树的系统。即使编写了将输入转换为更合适格式的转换,也必须使用DOM或SAX编写一些东西将其转换为Java对象。使用XSLT将大型XML文件转换为本地域模型,该模型通过JAXB映射到Java对象 从JDK5+内置的XML库开始,除非您绝对需要XSLT2.0,在这种情况下,请使用Saxon 不要关注SAX/DOM的相对性能,而是关注学习如何编写XPath表达式和使用XSLT,然后在以后发现性能有问题时才考虑性能
EclipseXML编辑器很不错,但如果您负担得起,spring for Oxygen XML可以让您实时进行XPath计算。使用XSLT将大型XML文件转换为本地域模型,该模型通过JAXB映射到java对象 从JDK5+内置的XML库开始,除非您绝对需要XSLT2.0,在这种情况下,请使用Saxon 不要关注SAX/DOM的相对性能,而是关注学习如何编写XPath表达式和使用XSLT,然后在以后发现性能有问题时才考虑性能 EclipseXML编辑器很不错,但是如果您负担得起,SpringforOxyXML,它将允许您实时进行XPath计算。,用于XML绑定的JavaAPI可能是什么 你想要的。您可以使用它将XML文档膨胀为由Java内容对象组成的Java对象图。这些内容对象是JAXB生成的类的实例,以匹配XML文档的模式 但是,如果您已经有了一组Java类,或者还没有文档的模式,那么JAXB可能不是最好的方法。我建议先进行SAX解析,然后在解析过程中构建Java对象。或者,您可以尝试DOM解析,然后遍历生成的文档树以提取感兴趣的部分(可能使用XPath),但在Java中,5MB的XML可能会变成50MB的DOM树对象。,XML绑定的Java API可能就是您想要的。您可以使用它将XML文档膨胀为由Java内容对象组成的Java对象图。这些内容对象是JAXB生成的类的实例,以匹配XML文档的模式
但是,如果您已经有了一组Java类,或者还没有文档的模式,那么JAXB可能不是最好的方法。我建议先进行SAX解析,然后在解析过程中构建Java对象。或者,您可以尝试DOM解析,然后遍历生成的文档树以提取感兴趣的部分(可能使用XPath),但在Java中,5MB的XML可能会变成50MB的DOM树对象。您可以在中使用@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;
}
您可以在中使用@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;
}
见下面我的答案。解析几个字段的XPath通常非常简单,而且通常非常快速。XSLT使用XML树,因此它使用一些DOM提供程序。但在这里,您必须衡量普通DOM实现和转换的焦点语言之间的性能和开发时间。。。XSLT还可以与SAX和流式检查Saxon XSLT处理器配合使用。我认为您可以从这个链接开始,然后使用一些桥接器,这样流式结果将直接提供一些SAX,以便使用一个著名的XML Java对象库。@vtd XML author-JAXB是一种无模式数据绑定技术。仅仅因为您可以使用JAXB从模式生成对象模型,并不意味着您也可以。您发布的文章也错误地将Castor描述为需要模式。请参阅下面我的答案。解析几个字段的XPath通常非常简单,而且通常非常快速。XSLT使用XML树,因此它使用一些DOM提供程序。但在这里,您必须衡量普通DOM实现和转换的焦点语言之间的性能和开发时间。。。XSLT还可以与SAX和流式检查Saxon XSLT处理器配合使用。我认为您可以从这个链接开始,然后使用一些桥接器,这样流式结果将直接提供一些SAX,以便使用一个著名的XML Java对象库。@vtd XML author-JAXB是一种无模式数据绑定技术。仅仅因为您可以使用JAXB从模式生成对象模型,并不意味着您也可以。您发布的文章还错误地将Castor描述为需要模式。这就是为什么我要问XSLT的原因。。。我需要知道XSLT处理器是如何工作的。。。最常见的实现是DOM还是SAX。XSLT比SAX更容易使用,但如果它对性能影响太大,那么我们必须使用SAX。JAXB可以从Java类开始。查看EclipseLink JAXB MOXy中的@XmlPath扩展如何用于利用XPath实现这个用例:这就是我为什么要问XSLT的原因。。。我需要知道XSLT处理器是如何工作的。。。最常见的实现是DOM还是SAX。XSLT比SAX更容易使用,但如果它对性能影响太大,那么我们必须使用SAX。JAXB可以从Java类开始。查看EclipseLink JAXB MOXy中的@XmlPath扩展如何用于利用XPath实现这个用例:但是,为什么我不能在使用XSLT处理XML时将XML映射到我的域模型?我不理解使用XSLT将其转换为JAXB可以使用的格式的好处,只是让JAXB再次解析XML。IME,SAX和DOM之间的性能比较真的不多,它实际上只是归结为您的文档是否足够小,可以在内存中解析?如果是这样的话,那么基于DOM的解析器就是最好的选择。如果没有,则需要转到SAX。如果您的需求非常简单,那么不要害怕跳过整个API,只需将您的文档视为文本流并自行解析即可。我经常在消息路由器上这样做,我需要解析的几个字段位于文档的开头。但是,为什么我不能在使用XSLT处理XML时将XML映射到我的域模型?我不理解使用XSLT将其转换为JAXB可以使用的格式的好处,只是让JAXB再次解析XML。IME,两者之间的性能比较实在不多 SAX和DOM,它真的可以归结为您的文档是否足够小,可以在内存中解析?如果是这样的话,那么基于DOM的解析器就是最好的选择。如果没有,则需要转到SAX。如果您的需求非常简单,那么不要害怕跳过整个API,只需将您的文档视为文本流并自行解析即可。我经常在消息路由器上这样做,我需要解析的几个字段位于文档的开头。