如何在不知道引用的元素/类时处理XmlIDREF

时间:2013-07-23 00:20:34

标签: jaxb

当您不知道引用的元素类型是什么时,如何处理引用?

我有一个元素<input>,它是一个数据接收器。元素<input>具有属性source,其指定(XmlIDREF引用)数据来自何处。 source引用的元素可以是多个元素之一。

以下是我正在使用的测试文档中的示例,其中<input>的{​​{1}}有时会引用source元素,有时会引用<source>(和那些不一定是它可以参考的唯一元素):

<vertices>

如果我这样做

    <source id="position">
      <float_array id="arrayPosition" count="78">...</float_array>
      ...
    </source>
    <source id="normal">
      <float_array id="arrayNormal" count="144">...</float_array>
      ...
    </source>
    <vertices id="vertex">
      <input semantic="POSITION" source="position"/>
    </vertices>
    <polylist material="MyMaterial" count="40">
      <input semantic="VERTEX" source="vertex" offset="0"/>
      <input semantic="NORMAL" source="normal" offset="1"/>
      ...
    </polylist>

然后对class Input { Source source; } 元素的所有引用都能正常工作,但对于其余元素,它们的来源是<source>。也就是说,如果我要设置一个null来显示类和id并打印上面的输入,我会得到

toString()

第一行将正确引用第一个Source: position null Source: normal 元素,第二行(我想引用<source>元素)将是<vertices>,第三行将引用第二个null元素。

如果我要更改<source>以改为使用字段Input,那么我会改为Vertices source nullVertices vertex。这是有道理的。

我如何构建我的Java代码来处理这个问题?

我已经研究过XmlAdapter,想想也许我可以给课程null一个字段InputObject source(同时创建MySuperClass sourceSource子类它)或Vertices,然后尝试转换适配器代码中的东西,但我怎么保留id引用?

我研究了JAXBElement source和工厂用法,但这似乎根本不是我想要的,或者至少我看不出它是如何应用的,尽管它起初听起来像是一个好的候选人。

谷歌搜索相关术语产生了其他人没有相关的各种引用问题。

我在想,无论如何,两件事中的一件必须是真的: 1)XmlTypeSource(以及Vertices可以使用其Input字段引用的所有其他内容)将必须扩展一个公共超类。 要么 2)source将有一个Input和一个Source source1(依此类推,到Vertices source2),其中一个会引用一些内容而其他所有内容都将为null

我很满意这两种情况中的任何一种,也可以选择替代方案,只要它解组所有数据并保留引用,这样我就可以获得所有信息。我只是想不出正确的方法来解组它。

我无法控制我得到的xml。 xml文档由其他程序创建,模式遵循大规范(http://www.khronos.org/files/collada_spec_1_4.pdf)。我只编写解组xml所需的Java代码并使用这些文件中的数据。

昨晚我刚刚开始使用jaxb,它的效果非常强(再次向开发者致敬),但有一些挥之不去的事情仍然需要解决。

1 个答案:

答案 0 :(得分:1)

<强>根

@XmlIDREF引用的每个对象也需要通过嵌套关系进行引用。它们并不都需要与本例中的同一类引用。

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlElementWrapper
    @XmlElement(name="foo")
    private List<Foo> foos;

    @XmlElementWrapper
    @XmlElement(name="bar")
    private List<Foo> bars;

}

<强>富

使用@XmlIDREF注释的属性将匹配任何类型的任何元素,无论它在文档中出现的位置。

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

    @XmlID
    @XmlAttribute
    private String id;

    @XmlIDREF
    @XmlAttribute
    private Object reference;

}

<强>酒吧

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Bar {

    @XmlID
    @XmlAttribute
    private String id;

}

<强>演示

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum17799549/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

<强> input.xml中/输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <foos>
        <foo id="B" reference="C"/>
        <foo id="A" reference="B"/>
    </foos>
    <bars>
        <bar id="C"/>
    </bars>
</root>

了解更多信息