JAXB使用xi:include导出到模块化xml文件

时间:2013-01-08 02:42:14

标签: xml jaxb include modular

我有两个XML文件

tree.xml

<tree>
    <xi:include href="fruit.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <xi:fallback>
            <fruit/>
        </xi:fallback>
    </xi:include>
</tree>

fruit.xml

<fruit>
     ...
</fruit>

我继承了解组文件的代码,它返回一个java对象。我现在需要将单个java对象编组回两个文件。我意识到还有其他解决方案(即使用两个对象而不是一个,这是一个选项)但我需要知道是否可以编组单个对象并维护xi:include(或重新引入它)并导出为两个(或者更多)xml文件。

这甚至可能吗?如果有任何提示/想法?

由于

更新

我一直在研究这个问题(我在询问之前进行了研究)。我确实找到了这个教程http://tutorial.waycoolsearch.com/java/jaxb2.php似乎有我的答案,但是当我把文件编组时它需要两个并制作一个。

2 个答案:

答案 0 :(得分:3)

下面我将演示如何使用XmlAdapter来支持此用例的编组和解组。

XmlAdapter(IncludeFruitAdapter)

XmlAdapter可以用于此用例。

import java.io.File;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class IncludeFruitAdapter extends XmlAdapter<IncludeFruitAdapter.Include, Fruit> {

    private JAXBContext jc;
    private String href = "fruit.xml";

    public IncludeFruitAdapter() {
        try {
            jc = JAXBContext.newInstance(Fruit.class);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }


    public static class Include {

        @XmlAttribute
        public String href;

        @XmlElement(namespace="http://www.w3.org/2001/XInclude")
        public Fallback fallback;

    }

    public static class Fallback {

        @XmlElementRef
        public Fruit value;

    }

    @Override
    public Include marshal(Fruit fruit) throws Exception {
        File xml = new File(href);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(fruit, xml);

        Include include = new Include();
        include.href = href;
        include.fallback = new Fallback();
        include.fallback.value = new Fruit();
        return include;
    }

    @Override
    public Fruit unmarshal(Include include) throws Exception {
        File xml = new File(include.href);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        try {
            return (Fruit) unmarshaller.unmarshal(xml);
        } catch(Exception e) {
            return include.fallback.value;
        }
    }

}

<强>树

@XmlJavaTypeAdapter用于引用XmlAdapter

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

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

    @XmlJavaTypeAdapter(IncludeFruitAdapter.class)
    @XmlElement(name="include", namespace="http://www.w3.org/2001/XInclude")
    private Fruit fruit;

}

<强>水果

import javax.xml.bind.annotation.*;

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

    private String name;

}

<强>演示

下面是一些可以运行的演示代码,以证明一切正常:

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

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("input.xml");
        Tree tree = (Tree) unmarshaller.unmarshal(xml);

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

    }

}

答案 1 :(得分:0)

我找到了答案,至少是一个解决方法。我想这可能就是这样做的方法。

我希望JAXB有某种方法来定义一个对象的一部分作为编组的包含,但我找不到任何东西。

注意:我有一个额外的黑客攻击,我将在下面解释,我想你可以在没有但我无法工作的情况下完成它,并且在其他人需要这样做的情况下,至少他们会知道。< / p>

流程如下。

  1. XI:Include的一个XML文件被解组到java对象。该对象包含2个文件(父文件和包含文件)的内容。
  2. 对象已更新。
  3. 将对象编组回一个临时文件(这是黑客)。
  4. 将单个临时文件umarshalled到DOM文档。 (我想直接编写一个DOM文档,但我总是有一个空的DOM文档,没有例外)。
  5. 然后我通过首先删除需要进入XI的节点来操作DOM文档:Include然后插入一个新的XI:include文件。
  6. 将DOM文档转换为xml文件。请注意,在我的情况下,XI的内容:include不会改变,但我想这个节点可以放在一个新文档中并进行转换。
  7. 我很快会用代码更新。

    还有其他方法可以解决这个问题吗?

    谢谢, 特拉维斯