humansg
humansg

Reputation: 715

XML mapping with @XmlAnyElement

I would like to achieve something like this.

<zoo>
    <lion> ... </lion>
    <dog> ... </dog>
</zoo> 

I have this class here.

public class MainGroup {
    private List<Widget> widgets;

    @XmlAnyElement
    public List<Widget> getWidgets() {
        return widgets;
    }
    public void setWidgets(List<Widget> widgets) {
        this.widgets = widgets;
    }
}

And this Widget superclass has got subclasses such as Button, Combobox... I would like to achieve something like this.

<MainGroup>
    <Button>...</Button>
    <Combo>...</Combo>
</MainGroup>

I am having this exception

[com.sun.istack.internal.SAXException2: class com.test.Button nor any of its super
  class is known to this context.

I tried adding @XmlElementRef but it is still not working.

@XmlElementRefs({
     @XmlElementRef(name="Button", type=Button.class),
     @XmlElementRef(name="Combo", type=Combo.class)
})

Upvotes: 3

Views: 4362

Answers (2)

humansg
humansg

Reputation: 715

Ok, I am missing quite a lot of things out here. It seems like I add to add this @XmlRootElement annotation to my subclasses of Button and Combo to achieve that.

Can anyone explain to me why I need that annotation in my subclasses... I am confused, I thought an XML would only have a @XmlRootElement which in my case should be in MainGroup class.

Upvotes: 0

bdoughan
bdoughan

Reputation: 149007

Mapping your Use Case

My answer is based on information gathered from one of your related questions:

Since you are mapping classes for which you do not have the source (and therefore can't add JAXB annotations), I would recommend using the @XmlElements mapping.

@XmlElements({
     @XmlElement(name="Button", type=Button.class),
     @XmlElement(name="Combo", type=Combo.class)
})
public List<Widget> getWidgets() {
    return widgets;
}

@XmlElements corresponds to the XML Schema concept of xsd:choice.

About @XmlRootElement

Ok, I am missing quite a lot of things out here. It seems like I add to add this @XmlRootElement annotation to my subclasses of Button and Combo to achieve that.

Can anyone explain to me why I need that annotation in my subclasses... I am confused, I thought an XML would only have a @XmlRootElement which in my case should be in MainGroup class.

@XmlRootElement corresponds to global elements in the XML schema, which involves more that just the root element in the document you are unmarshalling. I'll describe a couple of the roles below:

@XmlElementRef

@XmlElementRef corresponds to the concept of substitution groups. In an XML Schema you can specify that one global element is substitutable for another. In JAXB @XmlRootElement (and @XmlElementDecl) is leveraged to specify global elements:

@XmlAnyElement

@XmlAnyElement corresponds to the concept of xs:any in XML Schena. This is part of the document that is pretty free form. In JAXB when you map a property with @XmlAnyElement(lax=true) it will convert elements matching @XmlRootElement declarations into the corresponding domain objects.

Upvotes: 1

Related Questions