Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XML mapping with @XmlAnyElement

Tags:

java

xml

jaxb

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)
})
like image 836
humansg Avatar asked Nov 19 '25 23:11

humansg


1 Answers

Mapping your Use Case

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

  • Why doesn't JAXB writes out SWT Widgets?

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.

  • http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html

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:

  • http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html

@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.

  • http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html
like image 110
bdoughan Avatar answered Nov 21 '25 12:11

bdoughan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!