问题描述
我有两个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.xml
<fruit>
...
</fruit>
我继承了解组文件的代码,它返回一个java对象。我现在需要将单个java对象编组回两个文件。我意识到还有其他解决方案(即使用两个对象而不是一个,这是一个选项)但我需要知道是否可以编组单个对象并维护xi:include(或重新引入它)并导出为两个(或者更多)xml文件。
I inherited the code to unmarshall the files, and it returns a single java object. I now need to marshall the single java object back to two files. I realize there are other solutions (i.e. using two objects instead of one, which is an option) but I need to know if its possible to marshall a single object and maintain the xi:include (or reintroduce it) and export to two (or more) xml files.
这甚至可能吗?如果有任何提示/想法?
Is this even possible? If so any tips/ideas?
谢谢
更新:
我一直在研究这个(我在询问前研究过)。我确实找到了这个教程 http://tutorial.waycoolsearch.com/java/jaxb2.php这似乎有我的答案,但唉,当我编辑文件时,它需要两个,并制作一个。
I have been researching this (I researched prior to asking). I did find this tutorial http://tutorial.waycoolsearch.com/java/jaxb2.php which appeared to have my answer, but alas when I marshall the file it takes what was two and makes one.
推荐答案
下面我将演示如何使用 XmlAdapter
支持此用例的编组和解组。
Below I'll demonstrate how an XmlAdapter
could be used to support both marshalling and unmarshalling for this use case.
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;
}
演示
下面是一些演示代码,您可以运行以证明一切正常:
Below is some demo code you can run to prove that everything works:
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);
}
}
这篇关于JAXB使用xi:include导出到模块化xml文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!