2012-06-25 75 views
4

使用JAXB时,我想在使用Generics时从我的XML元素中删除多余的名称空间/类型。我该怎么做,或者我做错了什么?我想使用泛型,这样我只需编写一段代码即可。从JAXB中删除xsi:type,xmlns:xs和xmlns:xsi Generics

示例代码:

public static void main(String[] args) { 
    try { 
     TestRoot root = new TestRoot(); 
     root.name.value = "bobby"; 
     root.age.value = 102; 
     root.color.value = "blue"; 

     JAXBContext context = JAXBContext.newInstance(root.getClass()); 
     Marshaller marsh = context.createMarshaller(); 
     marsh.setProperty(Marshaller.JAXB_ENCODING,"UTF-8"); 
     marsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE); 

     StringWriter sw = new StringWriter(); 
     PrintWriter pw = new PrintWriter(sw); 
     marsh.marshal(root,pw); 
     System.out.println(sw.toString()); 
    } 
    catch(Throwable t) { 
     t.printStackTrace(); 
    } 
} 

@XmlRootElement 
static class TestRoot { 
    @XmlElement public TestGeneric<String> name = new TestGeneric<String>(true); 
    @XmlElement public TestGeneric<Integer> age = new TestGeneric<Integer>(true); 
    @XmlElement public TestWhatIWouldLike color = new TestWhatIWouldLike(true); 
} 

@XmlAccessorType(XmlAccessType.NONE) 
static class TestGeneric<T> { 
    @XmlAttribute public boolean isRequired; 
    @XmlElement public T value; 

    public TestGeneric() { 
    } 

    public TestGeneric(boolean isRequired) { 
     this.isRequired = isRequired; 
    } 
} 

@XmlAccessorType(XmlAccessType.NONE) 
static class TestWhatIWouldLike { 
    @XmlAttribute public boolean isRequired; 
    @XmlElement public String value; 

    public TestWhatIWouldLike() { 
    } 

    public TestWhatIWouldLike(boolean isRequired) { 
     this.isRequired = isRequired; 
    } 
} 

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<testRoot> 
    <name isRequired="true"> 
     <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">bobby</value> 
    </name> 
    <age isRequired="true"> 
     <value xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">102</value> 
    </age> 
    <color isRequired="true"> 
     <value>blue</value> 
    </color> 
</testRoot> 

回答

2

测试通用

你JAXB(JSR-222)实施将创建每个类的映射(即TestGeneric,不是键入的(即TestGeneric<Integer>)。因此,它会将value字段视为类型。这将导致xsi:type属性,因为您的JAXB实现正在添加足够的信息来解组相同的类型。

@XmlAccessorType(XmlAccessType.NONE) 
static class TestGeneric<T> { 
    @XmlAttribute public boolean isRequired; 
    @XmlElement public T value; 

    public TestGeneric() { 
    } 

    public TestGeneric(boolean isRequired) { 
     this.isRequired = isRequired; 
    } 
} 

演示

以下是你可以使用的方法。我已经介绍了TestGeneric的子类来表示不同的可能类型。

package forum11192623; 

import java.io.PrintWriter; 
import java.io.StringWriter; 

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

public class Demo { 

    public static void main(String[] args) { 
     try { 
      TestRoot root = new TestRoot(); 
      root.name.value = "bobby"; 
      root.age.value = 102; 
      root.color.value = "blue"; 

      JAXBContext context = JAXBContext.newInstance(root.getClass()); 
      Marshaller marsh = context.createMarshaller(); 
      marsh.setProperty(Marshaller.JAXB_ENCODING,"UTF-8"); 
      marsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE); 

      StringWriter sw = new StringWriter(); 
      PrintWriter pw = new PrintWriter(sw); 
      marsh.marshal(root,pw); 
      System.out.println(sw.toString()); 
     } 
     catch(Throwable t) { 
      t.printStackTrace(); 
     } 
    } 

    @XmlRootElement 
    static class TestRoot { 
     @XmlElement public TestString name = new TestString(true); 
     @XmlElement public TestInteger age = new TestInteger(true); 
     @XmlElement public TestString color = new TestString(true); 
    } 

    @XmlAccessorType(XmlAccessType.NONE) 
    @XmlTransient 
    @XmlSeeAlso({TestInteger.class, TestString.class}) 
    static class TestGeneric<T> { 
     @XmlAttribute 
     public boolean isRequired; 
     public T value; 

     public TestGeneric() { 
     } 

     public TestGeneric(boolean isRequired) { 
      this.isRequired = isRequired; 
     } 
    } 

    static class TestInteger extends TestGeneric<Integer> { 
     public TestInteger() { 
     } 
     public TestInteger(boolean b) { 
      super(b); 
     } 
     @XmlElement 
     public Integer getValue() { 
      return value; 
     } 
     public void setValue(Integer value) { 
      this.value = value; 
     } 
    } 

    static class TestString extends TestGeneric<String> { 
     public TestString() { 
     } 
     public TestString(boolean b) { 
      super(b); 
     } 
     @XmlElement 
     public String getValue() { 
      return value; 
     } 
     public void setValue(String value) { 
      this.value = value; 
     } 
    } 

} 
+0

这会工作,但我觉得它打败了泛型的目的 - 这对我来说是编写和维护一个代码块,可用于任何对象而无需创建新类。 我想我只需要处理指定的类型,除非别人有任何其他好主意? – RedHackTea

0

我能够在属性上使用@XmlAnyElement(lax = true),该属性由于泛型参数而导致我遇到问题,于是不得不在实际正在编组的类上添加@XmlRootElement,并且声明已去远!太棒了!

相关问题