users@jaxb.java.net

Re: Wrong marshalling of xsd:any type

From: Wolfgang Laun <wolfgang.laun_at_gmail.com>
Date: Wed, 4 Nov 2009 10:12:37 +0100

The exact Java representation of StatusDetailType need not have a
List<Object> since <any/> does not have maxOccurs /= 1.

Answer #1:
In the Java code, there is no explicit information about the XML element tag
to use for an element of schema type
MissingAttributeDetailType. You must have prepared a document by

StatusDetailType sd = ...;
MissingAttributeDetailType mad = ...;
sd.getContent().add( mad );

Thus, the only information for the marshaller about the XML element to take
the place of the <any/> wildcard is object mad's class, which happens to be
MissingAttributeDetailType.

To get the correct XML element tag, you must create an object of class
JAXBElement<MissingAttributeDetailType> which contains an Object field
"value" (set to a MissingAttributeDetailType, defining all the children of
the element), and a
javax.xml.namespace.QName field "name" defining the tag's namespace and
local name.

The easiest way for obtaining code creating the JAXBElement<?> would be to
xjc-compile the schema with the complex types and an additional
  <xs:element name="MissingAttributeDetail"
type="MissingAttributeDetailType"/>
The ObjectFactory.java contains a suitable method
createMissingAttributeDetail(...)

Or see https://jaxb.dev.java.net/tutorial/section_4_5-Calling-marshal.html
the method wrap to create an arbitrary JAXBElement.

Answer #2:
Then, you won't need @XmlRootElement for class MissingAttributeDetailType
any more, because, being wrapped in an JAXBElement object, it won't be a
class for a "root" element any more.

-W

On Tue, Nov 3, 2009 at 5:53 PM, Florian Huonder <fhuonder_at_herasaf.org>wrote:

> Hi all,
>
>
>
> I have the following schema fragment:
>
>
>
> <complexType name="StatusDetailType">
>
> <complexContent>
>
> <restriction base="{http://www.w3.org/2001/XMLSchema}anyType<http://www.w3.org/2001/XMLSchema%7DanyType>
> ">
>
> <sequence>
>
> <any/>
>
> </sequence>
>
> </restriction>
>
> </complexContent>
>
> </complexType>
>
>
>
>
>
> The corresponding java class looks like this:
>
>
>
> @XmlAccessorType(XmlAccessType.*FIELD*)
>
> @XmlType(name = "StatusDetailType", propOrder = {
>
> "content"
>
> })
>
> *public* *class* StatusDetailType
>
> *implements* Serializable
>
> {
>
>
>
> *private* *final* *static* *long* *serialVersionUID* = 632768732L;
>
>
>
> @XmlAnyElement(lax = *true*)
>
> *protected* List<Object> content;
>
>
>
> *public* List<Object> getContent() {
>
> *if* (content == *null*) {
>
> content = *new* ArrayList<Object>();
>
> }
>
> *return* *this*.content;
>
> }
>
> }
>
>
>
> A type that can be placed into the any attribute is e.g. the
> MissingAttributeDetailType.
>
> Schema of this type looks like:
>
> <complexType name="MissingAttributeDetailType">
>
> <complexContent>
>
> <restriction base="{http://www.w3.org/2001/XMLSchema}anyType <http://www.w3.org/2001/XMLSchema%7DanyType>">
>
> <sequence>
>
> <element ref="{urn:oasis:names:tc:xacml:2.0:context:schema:os}AttributeValue" maxOccurs="unbounded" minOccurs="0"/>
>
> </sequence>
>
> <attribute name="AttributeId" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI <http://www.w3.org/2001/XMLSchema%7DanyURI>" />
>
> <attribute name="DataType" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI <http://www.w3.org/2001/XMLSchema%7DanyURI>" />
>
> <attribute name="Issuer" type="{http://www.w3.org/2001/XMLSchema}string <http://www.w3.org/2001/XMLSchema%7Dstring>" />
>
> </restriction>
>
> </complexContent>
>
> </complexType>
>
>
>
> And the corresponding java class is:
>
> @XmlRootElement
>
> @XmlAccessorType(XmlAccessType.*FIELD*)
>
> @XmlType(name = "MissingAttributeDetailType", propOrder = {
> "attributeValues" })
>
> *public* *class* MissingAttributeDetailType *implements* Serializable {
>
>
>
> *private* *final* *static* *long* *serialVersionUID* = 632768732L;
>
> @XmlElement(name = "AttributeValue")
>
> *protected* List<AttributeValueType> attributeValues;
>
> @XmlAttribute(name = "AttributeId", required = *true*)
>
> @XmlSchemaType(name = "anyURI")
>
> *protected* String attributeId;
>
> @XmlAttribute(name = "DataType", required = *true*)
>
> @XmlJavaTypeAdapter(URNToDataTypeConverter.*class*)
>
> @XmlSchemaType(name = "anyURI")
>
> *protected* DataTypeAttribute<?> dataType;
>
> @XmlAttribute(name = "Issuer")
>
> *protected* String issuer;
>
>
>
> …
>
> …
>
>
>
> }
>
>
>
> Now when I marshall the StatusDetailType class this results in:
>
> <StatusDetail>
>
> <missingAttributeDetailType DataType="
> http://www.w3.org/2001/XMLSchema#string"
> AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"/>
>
> </StatusDetail>
>
>
>
> But this is wrong because it should marshallt to:
>
> <StatusDetail>
>
> <MissingAttributeDetail DataType="
> http://www.w3.org/2001/XMLSchema#string"
> AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id"/>
>
> </StatusDetail>
>
>
>
>
>
> I use JAXB 2.1.12.
>
> A second question: Why is the @XmlRootElement needed in the
> MissingAttributeDetailType class? Without it, there is an exception asking
> for this annotation.
>
>
>
> I hope somebody can help me.
>
> Thanks a lot in advance.
>
>
>
> Regards
>
> Florian
>