Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use JAXB @XmlValue on a subclass?

Tags:

jaxb

I want XML like this:

<simple>Foo</simple>

I can do this successfully via a JAXB class that looks like this:

@XmlRootElement(name="simple")
class Simple {
    @XmlValue
    public String contents;
}

But now I need to make the Simple class be a subclass of another class like so:

@XmlRootElement(name="simple")
class Simple extends OtherClass {
    @XmlValue
    public String contents;
}

That fails with @XmlValue is not allowed on a class that derives another class. I can't easily refactor the superclass away (because of the way we're using @XmlElementRef on a wrapper class). Is there a workaround that will let me annotate my subclass to generate that simple XML?

like image 735
Chris Dolan Avatar asked Nov 11 '11 18:11

Chris Dolan


2 Answers

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.

This use case is supported by MOXy, and IMHO should be supported by the JAXB RI as well:

Simple

This class has a field mapped with @XmlValue and extends OtherClass:

package forum809827;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement(name="simple")
class Simple extends OtherClass {

    @XmlValue
    // @XmlValueExtension
    // As of moxy 2.6, XmlValueExtension needs to be added for this to work
    public String contents;

}

OtherClass

This is the super class. In MOXy the subclass can map a field/property with @XmlValue as long as the super class does not have any mappings to an XML element:

package forum809827;

import javax.xml.bind.annotation.XmlAttribute;

public class OtherClass {

    @XmlAttribute
    public String other;

}

Demo

package forum809827;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Simple.class);

        Simple simple = new Simple();
        simple.contents = "FOO";
        simple.other = "BAR";

        Marshaller marshaller = jc.createMarshaller();
        marshaller.marshal(simple, System.out);
    }

}

Output

<?xml version="1.0" encoding="UTF-8"?>
<simple xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" other="BAR">FOO</simple>

For More Information on Specifying MOXy as Your JAXB Provider

  • http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
like image 45
bdoughan Avatar answered Sep 28 '22 06:09

bdoughan


The accepted answer didn't work for me.

Everything is fine as described but I also needed to add the @XmlTransient to the superclass

like image 123
gatti Avatar answered Sep 28 '22 04:09

gatti