I want to be able to expose an object that represents an XML file to my users. This can be done with many libraries (xmlBeans, JAXB...) and it's all well and fine until I have to support different versions of that XML file (evolving schema problem) for backward compatibility.
我希望能够向用户公开表示XML文件的对象。这可以通过许多库(xmlBeans,JAXB ...)来完成,并且在我必须支持该XML文件的不同版本(不断发展的模式问题)以实现向后兼容之前,这一切都很好。
I want this to be completely transparent to my users, meaning it is my system that needs to decide which which version of XML file needs to be used at a certain point in time.
我希望这对我的用户完全透明,这意味着我的系统需要决定在某个特定时间点需要使用哪个版本的XML文件。
Here's a short pseudo code of what I want to achieve:
这是我想要实现的简短伪代码:
public VersionIndependantObject getVersionSpecificXmlBindedObject() {
//Determening XSD version and binding XML file to JAVA object
return javaObject;
}
VersionIndependantObject - this is an object representation of XML file found on the system at that time (it could be v1,v2...).
VersionIndependantObject - 这是当时在系统上找到的XML文件的对象表示(可能是v1,v2 ......)。
Is there a way of doing with one of an already existing libraries for XML -> Java Object binding?
有没有办法处理一个已经存在的XML库 - > Java Object绑定?
2 个解决方案
#1
2
XML Schema is Backwards Compatible
Often times XML schemas will evolve so that that they are backwards compatible. This is done by only adding new attributes and elements that are optional. This means an old XML document will still be valid against the new schema. When this strategy is used you simply need to regenerate the model against the new XML schema.
通常,XML模式会发展,以便它们向后兼容。这是通过仅添加可选的新属性和元素来完成的。这意味着旧的XML文档仍然对新模式有效。使用此策略时,您只需要针对新的XML模式重新生成模型。
XML Schema is Not Backwards Compatible
If the model is not backwards compatable then things are more complicated.
如果模型不能向后兼容,那么事情就更复杂了。
Generating the Model
生成模型
You could generate a model for each version of the XML schema. If the namespace doesn't change you will need to override the default package name.
您可以为每个版本的XML模式生成模型。如果命名空间未更改,则需要覆盖默认包名称。
Unmarshalling
解组
The instead of unmarshalling the XML directly you could parse it with a StAX parser. Then you can use the XMLStreamReader
to get the version attribute and determine the model to be used. Then unmarshal the XMLStreamReader
into that model.
而不是直接解组XML,您可以使用StAX解析器解析它。然后,您可以使用XMLStreamReader获取version属性并确定要使用的模型。然后将XMLStreamReader解组到该模型中。
UPDATE
I've already done that (the logic behind which model to use when unmarshaling part is a bit different though). the problem is transparency towards the user (return type). It's not until runtime that I know which model will be returned. How would you handle that?
我已经完成了(当解组部分时使用的模型背后的逻辑虽然有点不同)。问题是对用户的透明度(返回类型)。直到运行时我才知道将返回哪个模型。你会怎么处理?
You either need to have a generic return type (i.e. Object
) that can be of any of the generated models, or like in your question have version specific methods that each return their corresponding generated model. I would investigate what schema evolution strategy is being used. Many people try to be backwards friendly (since it helps their processing too).
您需要具有可以是任何生成的模型的泛型返回类型(即Object),或者像您的问题中那样具有特定于版本的方法,每个方法都返回其相应的生成模型。我将研究正在使用的模式演化策略。许多人试图向后友好(因为它也有助于他们的处理)。
#2
0
I use JAXB for support many version of XSD. It very simple and completely. But you should have in classpath classes for all version of your XSD's schemas. For generation classes from difference schemas you should use xjc.exe
from JDK and file binding.xml if schema's have some namespace:
我使用JAXB来支持许多版本的XSD。它非常简单而且完全。但是你应该在类路径类中拥有所有版本的XSD模式。对于来自差异模式的生成类,如果模式具有一些名称空间,则应使用JDK中的xjc.exe和文件binding.xml:
com.blah.v1.MyJAXBObject
com.blah.v2.MyJAXBObject
For marshalling/unmarshalling objects I use javax.xml.bind.JAXB
utility class.
对于编组/解组对象,我使用javax.xml.bind.JAXB实用程序类。
Usage example:
用法示例:
JAXB.unmarshal(xml, jaxbObject.getClass());
JAXB.marshal(jaxbObject, xml);
#1
2
XML Schema is Backwards Compatible
Often times XML schemas will evolve so that that they are backwards compatible. This is done by only adding new attributes and elements that are optional. This means an old XML document will still be valid against the new schema. When this strategy is used you simply need to regenerate the model against the new XML schema.
通常,XML模式会发展,以便它们向后兼容。这是通过仅添加可选的新属性和元素来完成的。这意味着旧的XML文档仍然对新模式有效。使用此策略时,您只需要针对新的XML模式重新生成模型。
XML Schema is Not Backwards Compatible
If the model is not backwards compatable then things are more complicated.
如果模型不能向后兼容,那么事情就更复杂了。
Generating the Model
生成模型
You could generate a model for each version of the XML schema. If the namespace doesn't change you will need to override the default package name.
您可以为每个版本的XML模式生成模型。如果命名空间未更改,则需要覆盖默认包名称。
Unmarshalling
解组
The instead of unmarshalling the XML directly you could parse it with a StAX parser. Then you can use the XMLStreamReader
to get the version attribute and determine the model to be used. Then unmarshal the XMLStreamReader
into that model.
而不是直接解组XML,您可以使用StAX解析器解析它。然后,您可以使用XMLStreamReader获取version属性并确定要使用的模型。然后将XMLStreamReader解组到该模型中。
UPDATE
I've already done that (the logic behind which model to use when unmarshaling part is a bit different though). the problem is transparency towards the user (return type). It's not until runtime that I know which model will be returned. How would you handle that?
我已经完成了(当解组部分时使用的模型背后的逻辑虽然有点不同)。问题是对用户的透明度(返回类型)。直到运行时我才知道将返回哪个模型。你会怎么处理?
You either need to have a generic return type (i.e. Object
) that can be of any of the generated models, or like in your question have version specific methods that each return their corresponding generated model. I would investigate what schema evolution strategy is being used. Many people try to be backwards friendly (since it helps their processing too).
您需要具有可以是任何生成的模型的泛型返回类型(即Object),或者像您的问题中那样具有特定于版本的方法,每个方法都返回其相应的生成模型。我将研究正在使用的模式演化策略。许多人试图向后友好(因为它也有助于他们的处理)。
#2
0
I use JAXB for support many version of XSD. It very simple and completely. But you should have in classpath classes for all version of your XSD's schemas. For generation classes from difference schemas you should use xjc.exe
from JDK and file binding.xml if schema's have some namespace:
我使用JAXB来支持许多版本的XSD。它非常简单而且完全。但是你应该在类路径类中拥有所有版本的XSD模式。对于来自差异模式的生成类,如果模式具有一些名称空间,则应使用JDK中的xjc.exe和文件binding.xml:
com.blah.v1.MyJAXBObject
com.blah.v2.MyJAXBObject
For marshalling/unmarshalling objects I use javax.xml.bind.JAXB
utility class.
对于编组/解组对象,我使用javax.xml.bind.JAXB实用程序类。
Usage example:
用法示例:
JAXB.unmarshal(xml, jaxbObject.getClass());
JAXB.marshal(jaxbObject, xml);