Java Jaxb:如何解组 xs:any XML 字符串部分?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9687588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Jaxb: how to unmarshall xs:any XML-string part?
提问by Petter Nordlander
I have an application doing XML<->conversions using Jaxb and automatically generated classes with maven-jaxb2-plugin.
我有一个应用程序使用 Jaxb 进行 XML<-> 转换,并使用 maven-jaxb2-plugin 自动生成类。
Someplace deep in my schema, I have the possibility to enter "ANY" xml.
在我的架构深处,我有可能输入“任何”xml。
Update: this better describes my schema. Some known XML wrapping a totally unknown part (the "any" part).
更新:这更好地描述了我的架构。一些已知的 XML 包装了一个完全未知的部分(“任何”部分)。
<xs:complexType name="MessageType">
<xs:sequence>
<xs:element name="XmlAnyPayload" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:any namespace="##any"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="OtherElements">
....
</xs:sequence>
This maps (by jaxb) to a inner class like this.
这(通过 jaxb)映射到这样的内部类。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"any"
})
public static class XmlAnyPayload {
@XmlAnyElement(lax = true)
protected Object any;
When I unmarshall the entire structure, it is no problem. The "Object any" will render into a org.apache.xerces.dom.ElementNSImpl. Now, I want to recreate the Java object manually and then go to XML. How do I take some random XML and put into the any (org.apache.xerces.dom.ElementNSImpl) element to be able to build up the Java object?
当我解组整个结构时,没有问题。“Object any”将呈现为 org.apache.xerces.dom.ElementNSImpl。现在,我想手动重新创建 Java 对象,然后转到 XML。如何获取一些随机 XML 并将其放入 any (org.apache.xerces.dom.ElementNSImpl) 元素中以便能够构建 Java 对象?
Also, the next case is when I have this element as java, I want to unmarshall this very part (to be able to extract the XML string of this element). But this is not possible. I get an exception about root elements. But it is not possible to annotate ElementNSImpl.
此外,下一种情况是当我将此元素作为 java 使用时,我想解组这部分(以便能够提取此元素的 XML 字符串)。但这是不可能的。我得到一个关于根元素的异常。但是不可能注释ElementNSImpl。
unable to marshal type "com.sun.org.apache.xerces.internal.dom.ElementNSImpl" as an element because it is missing an @XmlRootElement annotation
Do you have any suggestions on how to handle these problems?
您对如何处理这些问题有什么建议吗?
采纳答案by lexicore
@XmlAnyElement(lax = true)
means in plain English something like:
@XmlAnyElement(lax = true)
用简单的英语表示,例如:
Dear JAXB! If you have a mapping for this element, please unmarshal it into a Java object. If you don't know this element, just leave it as a DOM element.
亲爱的 JAXB!如果您有此元素的映射,请将其解组为 Java 对象。如果你不知道这个元素,就把它作为一个 DOM 元素。
This is exactly what is happening in your case. So if you want to actually unmarshal the content of this lax any, provide JAXB context with a mapping for the element you wish to unmarshal. The easiest way to do this is to annotate your class with @XmlRootElement
这正是您的情况。因此,如果您想真正解组这个松散的内容,请为 JAXB 上下文提供您希望解组的元素的映射。最简单的方法是用@XmlRootElement
@XmlRootElement(name="foo", namespace="urn:bar")
public class MyClass { ... }
Now when you create your JAXB context, add MyClass
into it:
现在,当您创建 JAXB 上下文时,添加MyClass
到其中:
JAXBContext context = JAXBContext.newInstance(A.class, B.class, ..., MyClass.class);
In this case, if JAXB meets the {urn:bar}foo
element in the place of that xs:any
, it will know that this element is mapped onto MyClass
and will try to unmarshal MyClass.
在这种情况下,如果 JAXB 遇到{urn:bar}foo
代替 that的元素xs:any
,它将知道该元素已映射到MyClass
并尝试解组 MyClass。
If you are creating JAXB context based on the package name (you probably do), you can still add you class (say, com.acme.foo.MyClass
) to it. The easiest way is to create a com/acme/foo/jaxb.index
resource:
如果您正在根据包名称创建 JAXB 上下文(您可能会这样做),您仍然可以将您的类(例如,com.acme.foo.MyClass
)添加到它。最简单的方法是创建一个com/acme/foo/jaxb.index
资源:
com.acme.foo.MyClass
And the add your package name to the context path:
并将您的包名称添加到上下文路径:
JAXBContext context = JAXBContext.newInstance("org.dar.gee.schema:com.acme.foo");
There are other ways with ObjectFactory
etc., but the trick with jaxb.index
is probably the easiest one.
还有其他方法与ObjectFactory
等,但技巧jaxb.index
可能是最简单的一种。
Alternatively, instead of unmarshalling everything in one run, you can leave the content of xs:any
as DOM and unmarshal it into the target object in a second unmarshalling with anothe JAXB context (which know your MyClass
class). Something like:
或者,不是在一次运行中解组所有内容,您可以将xs:any
DOM的内容保留为 DOM,并在使用另一个 JAXB 上下文(知道您的MyClass
类)进行第二次解组时将其解组到目标对象中。就像是:
JAXBContext payloadContext = JAXBContext.newInstance(MyClass.class);
payloadContext.createUnmarshaller().unmarshal((Node) myPayload.getAny());
This approach is sometimes better, especially when you have a combination of container/payload schemas which are relatively independent. Depends on the case.
这种方法有时更好,特别是当您有相对独立的容器/有效负载模式组合时。视情况而定。
All said above applies to marshalling as well. It's all neatly bidirectional.
上述所有内容也适用于编组。这一切都是双向的。
回答by korifey
<xs:any/>
requires some not intuitive stuff to be converted to java object. If you have no difference, try using
需要将一些不直观的东西转换为 java 对象。如果您没有区别,请尝试使用
<element name="any" type="xs:anyType"/>
回答by Puce
I think you need the XSDs for this "any" part and generate classes for them as well.
我认为您需要这个“任何”部分的 XSD 并为它们生成类。
Here is some more information:
以下是更多信息:
http://jaxb.java.net/guide/Mapping_of__xs_any___.html
http://jaxb.java.net/guide/Mapping_of__xs_any___.html
Edit: if your object you want to marshal doesn't have the @XmlRootElement annotation (see error message), then I think you have to wrap it with a JAXBElement.
编辑:如果您要编组的对象没有 @XmlRootElement 注释(请参阅错误消息),那么我认为您必须用 JAXBElement 包装它。