代码之家  ›  专栏  ›  技术社区  ›  Stian Soiland-Reyes

使用@xmlanyement使用JAXB保存多个xsd:any

  •  1
  • Stian Soiland-Reyes  · 技术社区  · 15 年前

    我怎么能支持 交错 未知的 使用JAXB的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>
    

    其他名称空间中的任何XML都应该在之前和之后被允许 <rootFile> .


    在模式方面这是非常直接的使用 <xsd:any> 元素之前和之后 <xsd:element> 对于 <根文件> . 交错在可选元素周围比较麻烦,但那是一个单独的帖子。诀窍是让包装组变成可选的: <xsd:sequence minOccurs="0"><xsd:element minOccurs="1" .. /><xsd:any /></xsd:sequence>

    我又加了一句 jaxb:属性 为任何前/后属性指定不同的属性名称。我这样做是为了避免XJC抱怨 属性“Any”已定义 .

    问题是JAXB似乎把 无论如何 属性,当再次封送未封送的元素时可以看到 example Maven Project ):

    <?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>
    

    这样就不可能检查了 rootFiles.getAnyAfter() 要想知道哪些未知信息出现在哪里,但对我来说更为严重的是,如果不搞乱交错的XML,就不可能再次序列化XML。

    XJC确实正确地创建了两个 任何 -属性:

        @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;
    

    的JavaDoc XmlAnyElement 说:

    此批注与xmlement、XmlAttribute、XmlValue、xmlements、XmlID和XmlIDREF互斥。 类及其超级类中只能有一个带xmlanyement注释的JavaBean属性。

    由此我得出结论,JAXB并不真正关心第二个 @XmlAnyElement ,并将所有直接未知信息放入第一个 任何 财产。我不知道该怎么办。

    请注意,我主要关心的是将未知元素保留在正确的位置(顺序似乎被保留),我并不特别关心解析它们,只是在对 元素。


    现在您可能想知道为什么我要设计这样一个愚蠢的模式,允许到处都是随机XML。不幸的是这不是我的错,我只是想手动转换这个 RELAX NG schema Adobe UCF specifications 给一个 XML schema 我可以和JAXB一起使用。问题是 this wording 它允许META-INF/container.XML中的任何外部XML元素和属性:

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

    一致的container.xml文件在从其他名称空间中移除所有元素(以及这些元素的子节点)和属性之后,必须根据RELAX NG UCF模式是有效的,其中元素是根元素。

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

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

    1 回复  |  直到 15 年前
        1
  •  4
  •   lexicore    15 年前

    你可以合并 @XmlAnyElement 具有 @XmlElementRef @XmlElementRefs . 您的注释将如下所示:

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

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