CLASS FIELD BECOME A TAG NAME USING JAXB

Kamlakar Singh

Total Post:194

Points:1396
Posted by  Kamlakar Singh
Java  XML 
 1104  View(s)
Ratings:
Rate this:

I am using Java and JAXB for XML processing.

I have the following class:

    public class Characteristic {

 

        private String characteristic;

        private String value;

 

        @XmlAttribute

        public String getCharacteristic() {

            return characteristic;

        }

 

        public void setCharacteristic(String characteristic) {

            this.characteristic = characteristic;

        }

 

        @XmlValue

        public String getValue() {

            return value;

        }

 

        public void setValue(String value) {

            this.value = value;

        }

    }

 

    public static void main(String[] args) {

        Characteristic c = new Characteristic();

        c.setCharacteristic("store_capacity");

        c.setValue(40);

        Characteristic c2 = new Characteristic();

        c2.setCharacteristic("number_of_doors");

        c2.setValue(4);

    }

This is the result that I get:

<characteristics characteristic="store_capacity">40</characteristics>

<characteristics characteristic="number_of_doors">4</characteristics>

I want to get the following result:

<store_capacity>40</store_capacity>

<number_of_doors>4</number_of_doors>

How can I achieve this?

  1. Pawan Shukla

    Post:38

    Points:274
    Re: class field become a tag name using JAXB

    You can use a combination of @XmlElementRef and JAXBElement to produce dynamic element names.

     

    The idea is:

     

    1.       Make Characteristic a subclass of JAXBElement and override the getName() method to return the name based on the characteristic property.

    2.       Annotate characteristics with @XmlElementRef.

    3.       Provide the @XmlRegistry (ObjectFactory) with an @XmlElementDecl(name = "characteristic").

    Below is a working test.

     

    The test itself (nothing special):

    @Test

            public void marshallsDynamicElementName() throws JAXBException {

                JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);

                final Characteristics characteristics = new Characteristics();

                final Characteristic characteristic = new Characteristic(

                        "store_capacity", "40");

                characteristics.getCharacteristics().add(characteristic);

                context.createMarshaller().marshal(characteristics, System.out);

            }

    Produces:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <characteristics><store_capacity>40</store_capacity></characteristics>

    Let's start with the characteristics root element class. It has a characteristics property which is annotated with @XmlElementRef. This means that the contents should be either JAXBElements or @XmlRootElement-annotated class instances.

    @XmlRootElement(name = "characteristics")

            public static class Characteristics {

     

                private final List<Characteristic> characteristics = new LinkedList<Characteristic>();

     

                @XmlElementRef(name = "characteristic")

                public List<Characteristic> getCharacteristics() {

                    return characteristics;

                }

     

            }

    In order for this to work you also need an ObjectFactory or something annotated with @XmlRegistry having a corresponding @XmlElementDecl:

    @XmlRegistry

        public static class ObjectFactory {

     

            @XmlElementDecl(name = "characteristic")

            public JAXBElement<String> createCharacteristic(String value) {

                return new Characteristic(value);

            }

     

        }

    Recall, the characteristics property must contain either @XmlRootElement-annotated class instances or JAXBElements. @XmlRootElement is not suitable since it's static. But JAXBElement is dynamic. You can subclass JAXBElement and override the getName() method:

        public static class Characteristic extends JAXBElement<String> {

     

            private static final long serialVersionUID = 1L;

            public static final QName NAME = new QName("characteristic");

     

            public Characteristic(String value) {

                super(NAME, String.class, value);

            }

     

            public Characteristic(String characteristic, String value) {

                super(NAME, String.class, value);

                this.characteristic = characteristic;

            }

     

            @Override

            public QName getName() {

                final String characteristic = getCharacteristic();

                if (characteristic != null) {

                    return new QName(characteristic);

                }

                return super.getName();

            }

     

            private String characteristic;

     

            @XmlTransient

            public String getCharacteristic() {

                return characteristic;

            }

     

            public void setCharacteristic(String characteristic) {

                this.characteristic = characteristic;

            }

        }

    }

    In this case I've overridden the getName() method to dynamically determine the element name. If characteristic property is set, its value will be used as the name, otherwise the method opts to the default characteristic element.

Answer

NEWSLETTER

Enter your email address here always to be updated. We promise not to spam!