5

我有一个子树,我想将它附加到一个对象上,并使 JAXB 将所有事物编组为一棵树(并带有适当的标签)。但是目前,子树的根标签被另一个对象的标签替换

不幸的是,我不允许在这里发布原始代码,所以我在测试代码中重现了我的问题(如果你觉得这很愚蠢,请耐心等待)。

这个想法是我想输出以下结构:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1">
    <Content>
        <Header>
            <ns3:Leaf/>
        </Header>
    </Content>
</ns2:Root>

但目前,我得到的只是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:Root xmlns:ns2="urn:my:foo:bar:1.0" xmlns:ns3="urn:other:foo:bar:1.1">
    <Content>
        <Header/>
    </Content>
</ns2:Root>

我有两个 XSD 来生成所有必要的类,所以我在那边没问题(但由于这些类是生成的,我无法修改它们)。

这是生成第二个 XML(错误的)的示例代码:

package foo.bar;

import java.io.OutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

public class Test {

    private JAXBContext context;

    public Test() throws JAXBException {
        context = JAXBContext.newInstance(RootElement.class, LeafElement.class);
    }

    @XmlRootElement(name = "Root", namespace = "urn:my:foo:bar:1.0")
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Root", propOrder = { "content" })
    public static class RootElement {
        @XmlElement(name = "Content")
        protected ContentElement content;

        public ContentElement getContent() {
            return content;
        }

        public void setContent(ContentElement content) {
            this.content = content;
        }
    }

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Content", propOrder = { "dummy" })
    public static class ContentElement {
        @XmlElement(name = "Header")
        protected Object dummy;

        public Object getDummy() {
            return dummy;
        }

        public void setDummy(Object dummy) {
            this.dummy = dummy;
        }
    }

    @XmlRootElement(name = "Leaf", namespace = "urn:other:foo:bar:1.1")
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Leaf")
    public static class LeafElement {

    }

    public Node marshal(Object obj) throws JAXBException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = null;
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            doc = db.newDocument();
        } catch (ParserConfigurationException ex) {
            throw new JAXBException(ex);
        }

        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.marshal(obj, doc);
        return doc.getDocumentElement();
    }

    public void marshal(Object obj, OutputStream stream) throws JAXBException {
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.marshal(obj, stream);
    }

    public void test() throws JAXBException {
        RootElement root = new RootElement();
        ContentElement content = new ContentElement();
        root.setContent(content);
        LeafElement leaf = new LeafElement();
        content.setDummy(marshal(leaf));
        marshal(root, System.out);
    }

    public static void main(String[] args) throws JAXBException {
        new Test().test();
    }

}

在该代码中,您会找到 3 个“可编组”类:

  1. RootElement,
  2. ContentElement
  3. LeafElement.

前两个类来自一个 XSD(具有给定的命名空间),最后一个来自另一个 XSD(具有另一个命名空间),如示例代码所示。

到目前为止,我发现要解决这个问题的方法是创建一个附加类,该类将设置为dummyContentElement 上的内容,并且本身将包含 LeafElement,以便 JAXB 创建适当的中间节点。但是我发现这个解决方案非常丑陋,不是真正可维护的,并且希望 JAXB 有一些方法来处理这种情况。

如果您需要更多信息,或者您需要我重新提出我的问题,请不要犹豫。我很难用简单的话来解释我的问题。

约束如下:

  • 我无法修改 RootElement、ContentElement 或 LeafElement
  • 我不能使用除 JAXB 以外的其他东西
4

1 回答 1

2

如果你不能改变任何元素类,那么你必须创建一个持有者对象来叶子。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class LeafElementHolder {
    @XmlAnyElement
    private Object leaf;

    public Object getLeaf() {
        return leaf;
    }

    public void setLeaf(Object leaf) {
        this.leaf = leaf;
    }
}

将此类添加到上下文中

public Test() throws JAXBException {
    context = JAXBContext.newInstance(RootElement.class, LeafElement.class, LeafElementHolder.class);
}

并在你的 test() 方法中使用它

    LeafElement leaf = new LeafElement();
    LeafElementHolder holder = new LeafElementHolder();
    holder.setLeaf(leaf);
    content.setDummy(marshal(holder));

XML 中有 4 个元素,因此 Java 中必须有 4 个类。

ns2:Root
  ns2:Content
    ns2:Header
      ns3:Leaf
于 2012-09-23T00:32:50.070 回答