我确信这可能已经详细讨论过或者之前已经回答过,但是我需要更多关于我的情况的最佳方法的信息......
问题:
我们有一些大型XML数据(从100k到5MB不等),我们需要将它们扩展到Java对象中。问题是数据根本不能很好地映射到对象上,所以我们只需要拉出数据的某些部分并创建对象。鉴于此,JAXB或XStream等解决方案确实不合适。
因此,我们需要提取XML数据并尽可能高效地将其导入Java对象。
可能的解决方案:
我看到它的方式,我们有3种可能的解决方案:
我们可以将XML加载到任何JAXP实现中,并使用上述方法之一拉出数据。
的问题(S)
我有几个问题/担忧:
修改
一些说明......您可以使用XSLT直接将值注入Java对象...它通常用于将XML转换为其他XML,但我是从调用XSLT到java的方法的角度来谈论注入价值。
我还不清楚XSLT处理器是如何正常工作的...它如何将XML提供给你编写的XSLT代码?
答案 0 :(得分:3)
使用XSLT将大型XML文件转换为使用JAXB映射到java对象的本地域模型。
从内置XML库的JDK 5+开始(除非你绝对需要XSLT 2.0,在这种情况下使用Saxon)
不要专注于SAX / DOM的相对性能,专注于学习如何编写XPath表达式和使用XSLT,然后当且仅当您发现它是一个问题时才会担心性能。
Eclipse XML编辑器很不错,但如果你能负担得起,可以使用Oxygen XML,它可以让你实时进行XPath评估。
答案 1 :(得分:2)
我们有类似的情况,我只是将一些XPath代码整理在一起,解析了我需要的东西。
即使在100k + XML文件上也非常快。我们尽可能地低技术。我们每天处理大约1000个文件,并且解析时间非常短。我们没有内存问题,泄漏等。
我们在Groovy中写了一个快速原型(如果我的记忆准确的话) - 概念证明花了我大约10分钟
答案 2 :(得分:2)
JAXB,XML绑定的Java API可能就是您想要的。您可以使用它将XML文档扩展为由“Java内容对象”组成的Java对象图。这些内容对象是JAXB生成的类的实例,以匹配XML文档的模式
但是如果你已经拥有一组Java类,或者还没有该文档的架构,那么JAXB可能不是最好的方法。我建议做一个SAX解析,然后在解析期间构建你的Java对象。或者,您可以尝试DOM解析,然后遍历生成的Document树以提取感兴趣的部分(可能使用XPath) - 但是5MB的XML可能会变成Java中的50MB DOM树对象。
答案 3 :(得分:1)
DOM,SAX和XSLT是不同的动物。
DOM解析将整个文档加载到内存中,对于100K到5MB(按照今天的标准来说非常小)可以工作。
SAX是一个流解析器,它读取XML并将事件传递给每个标记的代码。
XSLT是一个将一个XML树转换为另一个XML树的系统。即使你编写了一个将输入转换为更合适的格式的转换,你仍然需要使用DOM或SAX编写一些东西来将其转换为Java对象。
答案 4 :(得分:1)
您可以使用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;
}