Java JAXB—尝试在“中使用枚举”;xsd:any";标签

Java JAXB—尝试在“中使用枚举”;xsd:any";标签,java,jaxb,Java,Jaxb,我会马上说,我毫不怀疑我的问题是自己造成的,但我已经尝试从我能想到的每个角度自己解决它,我仍然完全被难住了——任何帮助都将不胜感激 我试图完成的不是火箭科学——我得到了一个我称之为“提供”的模式,表示这是由第三方提供给我的(即,我无法更改/编辑它)。请注意,此模式包含一个xsd:any标记,用作放置用户定义数据的位置 <xsd:schema xmlns="http://somecompany.com/schema" xmlns:xsd="http://www.w3.org/2001/XML

我会马上说,我毫不怀疑我的问题是自己造成的,但我已经尝试从我能想到的每个角度自己解决它,我仍然完全被难住了——任何帮助都将不胜感激

我试图完成的不是火箭科学——我得到了一个我称之为“提供”的模式,表示这是由第三方提供给我的(即,我无法更改/编辑它)。请注意,此模式包含一个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>
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "UserDefinedAreaType", propOrder = {
"any"
})
public class UserDefinedAreaType {

    @XmlAnyElement(lax = true)
    protected List<Object> any;
}
现在用一些简单的代码来测试这个

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>
显然要做的事情是将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(以及我计划填充到此用户区域的任何其他内容)设置为@XmlRootElement,但实际上我没有成功实现这一点!我要么缺少将MyEnum创建为@XmlRootElement的明显方法,要么我的方法存在根本性缺陷(即,我从错误的方向处理这个问题)

非常感谢任何人提出的任何想法。

解决方案一-

架构更改:

<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>
也是一种有用的ObjectFactory方法,用于创建“MyEnums”(类型为“MyEnumType”):

@xmlementdecl(命名空间=”http://mycompany.com/schema“,name=“MyEnum”)
公共JAXBElement createMyEnum(MyEnumType值){
返回新的JAXBElement(_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();
    }
}
private static final ObjectFactory of=new ObjectFactory();
私有静态最终jaxbcontextjc;
静止的{
试一试{
jc=JAXBContext.newInstance(Parent.class,MyEnumType.class);
}捕获(JAXBEException-ex){
抛出新异常InInitializeRerror(ex);
}
}
公共静态void main(字符串[]args){
父项=新父项();
UserDefinedAreaType udat=新的UserDefinedAreaType();
父.setUserDefinedArea(udat);
JAXBElement goodEnum=of.createMyEnum(MyEnumType.fromValue(“活动”));
udat.getAny().add(goodEnum);
File File=新文件(“output.txt”);
试一试{
Marshaller m=jc.createMarshaller();
m、 封送员(父级、文件);
}捕获(JAXBEException-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>

积极的

一个
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
注释。

我之前确实尝试过这种方法-将simpleType包装到元素中,结果根本不创建类型。我唯一得到的是一个具有以下签名的ObjectFactory方法:public-JAXBElement-CreateMeyEnum(字符串值)
@XmlType(name = "MyEnumType", namespace = "http://mycompany.com/schema")
@XmlEnum
public enum MyEnumType {

    @XmlEnumValue("active")
    ACTIVE("active"),
    @XmlEnumValue("inactive")
    INACTIVE("inactive");
    private final String value;
}
@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>
<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>