如何使用JAXB支持 interleaved unknown XML?使用 @XmlAnyElement 似乎无法胜任工作..
我正在尝试编写XML模式以允许来自其他命名空间的交错元素,并将其与Java 6中的内置JAXB一起使用。(我没有完全尝试使用JAXB 2.2.1,因为我不喜欢我有幸要求我的API用户为支持 JAXB库做魔术,但我相信它也不适用于2.2.1)
因此,例如,给定模式anything.xsd,此example.xml应该有效:
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://example.com/schema"
xmlns:other="http://example.com/other">
<rootFiles>
<other:before>before rootFile</other:before>
<rootFile path="test" />
<other:after>after rootFile</other:after>
</rootFiles>
</container>
<rootFile>
之前和之后都应允许来自其他命名空间的任何XML。
使用<xsd:any>
<xsd:element>
之前和之后的<rootFile>
元素,使用<xsd:sequence minOccurs="0"><xsd:element minOccurs="1" .. /><xsd:any /></xsd:sequence>
元素非常简单。 在可选元素周围交错是比较棘手的,但这是一个单独的帖子。诀窍是将包装组改为可选:<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<container xmlns="http://example.com/schema">
<rootFiles>
<other:before xmlns:other="http://example.com/other">before rootFile</other:before>
<other:after xmlns:other="http://example.com/other">after rootFile</other:after>
<rootFile path="test"/>
</rootFiles>
</container>
我添加了 jaxb:property ,为any-after any-properties指定了不同的属性名称。我必须这样做以避免XJC抱怨属性“任何”已经定义。
问题是JAXB似乎将所有未知元素放入 anyBefore 属性中,就像再次编组unmarshalled元素时看到的那样(参见完整的example Maven Project):
rootFiles.getAnyAfter()
这使得无法检查 @XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"anyBefore",
"rootFile",
"anyAfter"
})
public static class RootFiles {
@XmlAnyElement(lax = true)
protected List<Object> anyBefore;
@XmlElement(required = true)
protected List<Container.RootFiles.RootFile> rootFile;
@XmlAnyElement(lax = true)
protected List<Object> anyAfter;
以查看哪些未知数出现在哪里,但对我来说更严重的是,不可能再次将XML序列化而不会弄乱交错的XML。
XJC正确创建了两个任何 - 属性:
@XmlAnyElement
XmlAnyElement的JavaDoc说:
此批注与XmlElement,XmlAttribute,XmlValue,XmlElements,XmlID和XmlIDREF互斥。 在类及其超类中只能有一个带注释的XmlAnyElement JavaBean属性。
由此我得出结论,JAXB并不真正关心第二个{{1}},只是将所有直接未知数放入第一个任何属性中。我不知道该做什么。
请注意,我主要关注的是将未知元素保存在正确的位置(顺序似乎被保留),我并不特别关心解析它们,只是确保它们在序列化XML时有点在同一个地方再次对 元素进行一些修改后。
现在你可能想知道为什么我会设计这样一个愚蠢的架构,允许随机的XML。很遗憾,这不是我的错,我只是尝试将此RELAX NG schema从Adobe UCF specifications手动转换为我可以与JAXB一起使用的XML schema。问题是this wording,它允许META-INF / container.xml中的任何外来XML元素和属性:
遵守UCF用户代理必须忽略container.xml文件中无法识别的元素(及其内容)和无法识别的属性,包括无法识别的元素和来自其他命名空间的无法识别的属性。
在删除所有元素(以及这些元素的子节点)和其他名称空间的属性后,符合container.xml文件必须符合RELAX NG UCF模式,元素作为根元素。
现在我当然可以删除任何这样的元素,因为它说我可以忽略它们,但我认为如果将来或某些扩展它们意味着什么,至少我可以正确保存这些元素..但是我发现这个难以使用JAXB。
对于我如何实现这一点有什么建议,比如Marshaller / Unmarshaller的一些魔法属性?
答案 0 :(得分:4)
您可以将@XmlAnyElement
与@XmlElementRef
或@XmlElementRefs
合并。您的注释看起来像:
@XmlElementRef(name="rootFile")
@XmlAnyElement
protected List<Object> beforeOrRootFileOrAfter;
在XML Schema中,尝试<xs:choice maxOccurs="unbounded" .../>
。