我会马上说,我毫不怀疑我的问题在一个纳秒内,我的问题是自己造成的,但我已经从我能想到的每一个角度自己解决了这个问题而且我'我仍然完全难过 - 任何帮助都会非常感激!
我想要完成的不是火箭科学 - 我已经给出了一个我称之为“提供”的模式,表示这是由第三方提供给我的(即我无法更改/编辑它)。请注意,此架构包含一个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生成一个类,它为我提供了一个用户定义数据的列表。
@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 :(得分: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>
答案 1 :(得分: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
注释。