Hi,
I am using Java 5 and JAXB RI 2.1.7 for my project and XJC utility coming with it for generating java code mapping to the XML schema. I m facing problems marshaling an object which has one of its fields mapping to <xs:any> type. Specifically, the problem arises whenever the XML DOM element mapping the <xs:any> element includes attributes. For the schema mentioned below:
SCHEMA:
<!-- --------------------------------------------------------------------------- -->
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="
http://www.w3.org/2001/XMLSchema"
xmlns="
http://www.company.com/Product/Component/v1.0"
targetNamespace="
http://www.company.com/Product/Component/v1.0"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:complexType name="Element">
<xs:sequence>
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="Description" type="xs:string" minOccurs="0" />
<xs:element name="Data" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:any/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Type" type="xs:string" />
<xs:attribute name="Id" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="ElementSet">
<xs:sequence>
<xs:element name="Element" type="Element" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="ElementSetAny" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Type" type="xs:string"/>
<xs:attribute name="Version" type="xs:long" use="optional"/>
</xs:complexType>
</xs:schema> <!-- schema ends here -->
<!-- --------------------------------------------------------------------------- -->
marshaling produces the following XML data which looks malformed:
<!-- --------------------------------------------------------------------------- -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ElementSet Version="0" Type="es1" xmlns:ns2="
http://www.company.com/Product/Component/v1.0">
<ns2:Element Id="1" Type="e_type1">
<ns2:Name>e1</ns2:Name>
<ns2:Data>
<ns2:someData xmlns="
http://www.company.com/Product/Component/v1.0">
<data1 name="one" xmlns:ns4="
http://www.company.com/Product/Component/v1.0" xmlns="">
<ns4:data2>1234</ns4:data2>
<ns4:data3>1234</ns4:data3>
</data1>
</ns2:someData>
</Data>
</Element>
</ElementSet>
<!-- --------------------------------------------------------------------------- -->
On unmarshaling the above generated XML I get the following exception:
DefaultValidationEventHandler: [FATAL_ERROR]: The element type "ns2:Data" must be terminated by the matching end-tag "</ns2:Data>".
Location: line 1
javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException: The element type "ns2:Data" must be terminated by the matching end-tag "</ns2:Data>".]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:510)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:215)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:190)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:241)
Have referred to
https://jaxb.dev.java.net/guide/Mapping_of__xs_any___.html and but could not get any useful information. Have also included the marshaling/unmarshaling code. Please let me know if any extra information needs to be supplied so that marshaling produces the right XML.
CODE:
/*********************************************************************/
public void testJaxbProcessing() throws Exception, JAXBException {
ElementSet es = new ElementSet();
es.setType("es1");
es.setVersion(Long.valueOf(0L));
Element e = new Element();
e.setName("e1");
e.setType("e_type1");
e.setId("1");
Data data = new Data();
// DOM element with attributes - does not work.
Document anyValue = getDOMfromXML(new StringReader("<someData xmlns=\"
http://www.company.com/Product/Component/v1.0\"><data1 name=\"one\"><data2>1234</data2><data3>1234</data3></data1></someData>"));
/*
* DOM element without attributes - works
* Document anyValue = getDOMfromXML(new StringReader("<someData xmlns=\"
http://www.company.com/Product/Component/v1.0\"><data1><data2>1234</data2><data3>1234</data3></data1></someData>"));
*/
data.setAny(anyValue.getDocumentElement());
e.setData(data);
es.getElement().add(e);
JAXBElement<ElementSet> jaxbElem = new JAXBElement<ElementSet>(
new QName("", ElementSet.class.getSimpleName()),
ElementSet.class, null, es);
// MARSHALLING
String esString = marshal(jaxbElem, ElementSet.class.getPackage().getName(), ElementSet.class.getClassLoader());
System.out.println(esString);
// UNMARSHALLING
es = (ElementSet) unmarshal(new StringReader(esString), ElementSet.class);
System.out.println("Finally element set : " + es.getType() + ", " + es.getVersion());
}
public String marshal(Object object,
String objectGraphPackage, ClassLoader classloader) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(objectGraphPackage,
classloader);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter sw = new StringWriter();
marshaller.marshal(object, sw);
return sw.toString();
}
public Object unmarshal(Reader xmlReader, Class declaredType) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(declaredType.getPackage().getName(),
declaredType.getClassLoader());
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler());
Object object = unmarshaller.unmarshal(new StreamSource(xmlReader), declaredType);
if(object instanceof JAXBElement) {
return ((JAXBElement) object).getValue();
} else {
return object;
}
}
private Document getDOMfromXML(Reader reader) throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(reader);
Document document = builder.parse(is);
return document;
}
/*********************************************************************/
Thanks in advance,
Anand Navale