2014-02-26 66 views
0

我會馬上說一聲,我毫不懷疑納秒,我的問題在這裏是自我造成的,但我已經跑了從我能想到的每個角度自己修理它,我仍然完全難住 - 任何幫助將非常感謝!JAXB--嘗試在「xsd:any」標記中使用枚舉

我想要完成的不是火箭科學 - 我已經給出了一個模式,我打電話給「提供」來表示這是由第三方提供給我的(即我無法更改/編輯它)。請注意,此架構包含一個xsd:any標籤,用作放置用戶定義數據的地方。

<xsd:schema xmlns="http://somecompany.com/schema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://somecompany.com/schema"> 

<xsd:element name="Parent"> 
    <xsd:complexType> 
     <xsd:sequence> 
      <xsd:element name="UserDefinedArea" type="UserDefinedAreaType"/> 
     </xsd:sequence> 
    </xsd:complexType> 
</xsd:element> 

<xsd:complexType name="UserDefinedAreaType"> 
    <xsd:sequence> 
     <xsd:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> 
    </xsd:sequence> 
</xsd:complexType> 

</xsd:schema> 

使用XJC爲這個模式生成代碼很簡單。 XJC爲UserDefinedAreaType生成一個類,它給了我一個用戶定義數據的List。

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "UserDefinedAreaType", propOrder = { 
"any" 
}) 
public class UserDefinedAreaType { 

    @XmlAnyElement(lax = true) 
    protected List<Object> any; 
} 

一個我想塞進這個UserDefinedArea的事情是一個枚舉(增添一些額外的驗證/類型安全保證)。創建一個模式來表示這個也很簡單。

<xsd:schema xmlns="http://mycompany.com/schema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://mycompany.com/schema"> 

<xsd:simpleType name="MyEnum"> 
    <xsd:restriction base="xsd:string"> 
     <xsd:enumeration value="active"/> 
     <xsd:enumeration value="inactive"/> 
    </xsd:restriction> 
</xsd:simpleType> 

</xsd:schema> 

XJC很高興地爲這個模式創建一個類。

@XmlType(name = "MyEnum", namespace = "http://mycompany.com/schema") 
@XmlEnum 
public enum MyEnum { 

    @XmlEnumValue("active") 
    ACTIVE("active"), 
    @XmlEnumValue("inactive") 
    INACTIVE("inactive"); 
    private final String value; 
} 

現在一些簡單的代碼來測試這個驅動器。

private static final ObjectFactory of = new ObjectFactory(); 

private static final JAXBContext jc; 

static { 
    try { 
     jc = JAXBContext.newInstance(Parent.class); 
    } catch (JAXBException ex) { 
     throw new ExceptionInInitializerError(ex); 
    } 
} 

public static void main(String[] args) { 
    Parent parent = new Parent(); 
    UserDefinedAreaType udat = new UserDefinedAreaType(); 
    parent.setUserDefinedArea(udat); 

    MyEnum myEnum = MyEnum.ACTIVE; 
    udat.getAny().add(myEnum); 

    File file = new File("output.txt"); 
    try { 
     Marshaller m = jc.createMarshaller(); 
     m.marshal(parent, file); 
    } catch (JAXBException ex) { 
     ex.printStackTrace(); 
    } 
} 

這就是我希望得到的。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:Parent xmlns:ns2="http://somecompany.com/schema" xlmns:ns3="http://mycompany.com/schema"> 
<UserDefinedArea> 
    <ns3:MyEnum>active</ns3:MyEnum> 
</UserDefinedArea> 
</ns2:Parent> 

但這是我真正得到的。

javax.xml.bind.MarshalException 
- with linked exception: 
[com.sun.istack.SAXException2: class com.mycompany.schema.MyEnum nor any of its super class is known to this context. 

顯而易見的事情將是MyEnum.class添加到JAXBContext中(即「JC = JAXBContext.newInstance(Parent.class,MyEnum.class);」),但所有的網我的是:

javax.xml.bind.MarshalException 
- with linked exception: 
[com.sun.istack.SAXException2: unable to marshal type "com.mycompany.schema.MyEnum" as an element because it is missing an @XmlRootElement annotation] 

下一個明顯的事情是讓MyEnum(和其他任何我打算塞進這個UserArea)的@XmlRootElement,但我有零次成功實際上使這種情況發生!我要麼缺少創建MyEnum作爲@XmlRootElement的明顯方法,要麼我的方法存在根本性缺陷(即,我正從錯誤的方向接近這個問題)。

非常感謝任何人可能有的想法。

回答

0

解決方法一 -

架構變化:

<xsd:schema xmlns="http://mycompany.com/schema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://mycompany.com/schema"> 
    <xsd:element name="MyEnum" type="MyEnumType"/> 
    <xsd:simpleType name="MyEnumType"> 
     <xsd:restriction base="xsd:string"> 
      <xsd:enumeration value="active"/> 
      <xsd:enumeration value="inactive"/> 
     </xsd:restriction> 
    </xsd:simpleType> 
</xsd:schema> 

這對於 「MyEnumType」 創建一個類:

@XmlType(name = "MyEnumType", namespace = "http://mycompany.com/schema") 
@XmlEnum 
public enum MyEnumType { 

    @XmlEnumValue("active") 
    ACTIVE("active"), 
    @XmlEnumValue("inactive") 
    INACTIVE("inactive"); 
    private final String value; 
} 

而且也是一個有用的ObjectFactory方法創建 「MyEnums」(中類型「MyEnumType」):

@XmlElementDecl(namespace = "http://mycompany.com/schema", name = "MyEnum") 
public JAXBElement<MyEnumType> createMyEnum(MyEnumType value) { 
    return new JAXBElement<MyEnumType>(_MyEnum_QNAME, MyEnumType.class, null, value); 
} 

完整測試驅動器的代碼:

private static final ObjectFactory of = new ObjectFactory(); 

private static final JAXBContext jc; 

static { 
    try { 
     jc = JAXBContext.newInstance(Parent.class, MyEnumType.class); 
    } catch (JAXBException ex) { 
     throw new ExceptionInInitializerError(ex); 
    } 
} 

public static void main(String[] args) { 

    Parent parent = new Parent(); 
    UserDefinedAreaType udat = new UserDefinedAreaType(); 
    parent.setUserDefinedArea(udat); 

    JAXBElement<MyEnumType> goodEnum = of.createMyEnum(MyEnumType.fromValue("active")); 
    udat.getAny().add(goodEnum); 

    File file = new File("output.txt"); 

    try { 
     Marshaller m = jc.createMarshaller(); 
     m.marshal(parent, file); 
    } catch (JAXBException ex) { 
     ex.printStackTrace(); 
    } 
} 

產生具有期望的輸出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:Parent xmlns:ns2="http://somecompany.com/schema"> 
    <UserDefinedArea> 
     <ns3:MyEnum xmlns:ns3="http://mycompany.com/schema">active</ns3:MyEnum> 
    </UserDefinedArea> 
</ns2:Parent> 
0

xsd:any一種爲任何元件的容器,但是您的模式沒有宣佈的任何元件,只一個MyEnum鍵入。如果你寫你的其他架構來delcare MyEnum作爲頂級元素與匿名類型,而不是作爲一個頂級型

<xsd:schema xmlns="http://mycompany.com/schema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://mycompany.com/schema"> 

<xsd:element name="MyEnum"> 
    <xsd:simpleType> 
    <xsd:restriction base="xsd:string"> 
     <xsd:enumeration value="active"/> 
     <xsd:enumeration value="inactive"/> 
    </xsd:restriction> 
    </xsd:simpleType> 
</xsd:simpleType> 

</xsd:schema> 

那麼你應該得到的@XmlRootElement註釋你的需要。

+0

我其實早些時候嘗試過這種方法 - 在一個元素中包裝simpleType最終不會創建一個類型。我唯一得到的是一個帶有這個簽名的ObjectFactory方法:public JAXBElement createMyEnum(String value) – Nick