微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – JAXB:如何将子树附加到对象并创建完整的树

我有一个子树,我想在一个对象上追加,并使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(错误的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个“可编组”类:

> RootElement,
> ContentElement和
> LeafElement.

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

到目前为止,我发现解决这个问题的方法是创建一个额外的类,它将在ContentElement上设置为dummy,并且本身将保存LeafElement,以便JAXB创建适当的intermdiate Node.但我发现这个解决方案非常难看,不能真正维护,并且希望JAXB有办法处理这种情况.

如果您需要更多信息,或者您需要我重新制定我的问题,请不要犹豫.我很难用简单的词语来解释我的问题.

约束如下:

>我无法修改RootElement,ContentElement和LeafElement
>除了JAXB,我不能使用别的东西

解决方法:

如果无法更改任何元素类,则必须创建一个holder对象.

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

你有4个XML元素,所以你必须有4个java类.

ns2:Root
  ns2:Content
    ns2:Header
      ns3:Leaf

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。