2013-01-08 35 views
4

我有两个XML文件JAXB出口到模块化的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似乎有我的答案,但唉,当我编组文件,它需要什么是两个,使一个。

回答

0

我想出了一个答案,至少有一项工作。我想这可能是做到这一点的方法。

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

注:我有一个额外的黑客,我会在下面解释,我想你可以做到这一点,但我无法得到它的工作,并在其他人需要这样做的情况下,至少他们会知道。

流程如下。

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

我会尽快用代码更新。

任何其他解决方法?

感谢, 特拉维斯

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

    } 

}