1

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

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

这是我正在使用的测试文档中的一个示例,其中<input>'source有时引用一个<source>元素,有时引用 a <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. 也就是说,如果我要设置一个toString()来显示类和 id 并打印上面的输入,我会得到

Source: position
null
Source: normal

第一行将正确引用第一个<source>元素,第二行,我想引用该<vertices>元素,将是null,第三行将引用第二个<source>元素。

如果我要Input改为拥有一个字段Vertices source,那么我会得到null Vertices vertexand null。这是有道理的。

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

我研究了 XmlAdapter,想也许我可以给类Input一个字段Object sourceMySuperClass source(并同时创建它SourceVertices子类)或者JAXBElement source然后尝试在适配器代码中转换东西,但是我将如何保留 id 引用?

我调查了XmlType工厂的使用情况,但这似乎根本不是我想要的,或者至少我不知道它是如何应用的,尽管它起初听起来像是一个很好的候选人。

谷歌搜索相关术语会产生其他人遇到的各种不相关的引用问题。

我在想,无论怎么做,两件事中的一件都必须是真实的:1)Source和(以及可以用它的字段引用的Vertices所有其他东西)必须扩展一个通用的超类。或 2)将有 a和 a (等等,to ),其中 1 个将引用某些东西,而所有其他都将为空。InputsourceInputSource source1Vertices source2ClassN sourcen

我对这两种情况以及替代方案都很好,只要它解组所有数据并保留引用,以便我可以获得所有信息。我只是想不出将其解组的正确方法。

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

我昨晚刚开始使用 jaxb,效果很好(再次向开发人员致敬),但是还有一些像这样的挥之不去的事情我仍然需要解决。

4

1 回答 1

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);
    }

}

输入.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>

了解更多信息

于 2013-07-23T09:46:37.297 回答