使用@XmlAnyElement使用JAXB保留多个xsd:any

时间:2010-11-24 14:42:50

标签: xml schema xsd jaxb

如何使用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 schemaAdobe UCF specifications手动转换为我可以与JAXB一起使用的XML schema。问题是this wording,它允许META-INF / container.xml中的任何外来XML元素和属性:

  

遵守UCF用户代理必须忽略container.xml文件中无法识别的元素(及其内容)和无法识别的属性,包括无法识别的元素和来自其他命名空间的无法识别的属性。

     

在删除所有元素(以及这些元素的子节点)和其他名称空间的属性后,符合container.xml文件必须符合RELAX NG UCF模式,元素作为根元素。

现在我当然可以删除任何这样的元素,因为它说我可以忽略它们,但我认为如果将来或某些扩展它们意味着什么,至少我可以正确保存这些元素..但是我发现这个难以使用JAXB。

对于我如何实现这一点有什么建议,比如Marshaller / Unmarshaller的一些魔法属性?

1 个答案:

答案 0 :(得分:4)

您可以将@XmlAnyElement@XmlElementRef@XmlElementRefs合并。您的注释看起来像:

@XmlElementRef(name="rootFile")
@XmlAnyElement
protected List<Object> beforeOrRootFileOrAfter;

在XML Schema中,尝试<xs:choice maxOccurs="unbounded" .../>