Joe Murray
Joe Murray

Reputation: 125

jaxb mixing XmlElement and XmlValue

I'm attempting to create a single java/jaxb class that can have both elements and a value.

I want to read the attribute of a class in a list of class A and output as the value of Class A itself.

This is the XML:

I have to read:

<data>
    <device id=”DEV123”>
        <error id=”ERR1”/> 
    </device>
</data>

and produce:

<data>
    <device id="DEV123">ERR1</device>
</data>

This is my error class - works fine:

@XmlRootElement(name = "error")
public class Error implements Serializable {
private String id;


@XmlAttribute(name ="id")
public String getId() {

    return id;
}

public void setId(String id ){

    this.id = id;
}

}

My Device class:

@XmlRootElement(name = "device")
public class Device implements Serializable {


    private String id;
    private String device;
    private ArrayList<Error> errorList;


    @XmlElement
    public ArrayList<Error> getErrorList() {
        return errorList;
    }

    @XmlAttribute(name = "id") 
    public String getId() {

        return id;
    }
    public void setId(String id) {
        this.id = id;
    }

    @XmlValue
    public String getDevice(){
        return this.device;
    }



}

Jaxb complains that I can't have both xmlelement ( Error ) and xmlvalue in the same class

"If a class has @XmlElement property, it cannot have @XmlValue property."

How would I correctly model/annotate this to allow me to read the attribute of the error xml tag and produce it as the value of the device tag?

Upvotes: 2

Views: 4098

Answers (1)

bdoughan
bdoughan

Reputation: 149017

You could do the following:

Use @XmlMixed instead of @XmlValue

@XmlMixed
public String getDevice(){
    return this.device;
}

Use a StreamFilter to Remove Whitespace

A property annotated with @XmlMixed is going to pick up any text characters whether it be whitespace or not. If the property is a collection it will pick up everthing if its not each piece of text encountered will wipe out the last. Because of this you need to eliminate the whitespace as you are parsing.

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

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

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(new StreamSource("src/forum22284324/input.xml"));
        xsr = xif.createFilteredReader(xsr, new StreamFilter() {

            @Override
            public boolean accept(XMLStreamReader reader) {
                if(reader.getEventType() == XMLStreamReader.CHARACTERS) {
                    return reader.getText().trim().length() > 0;
                } 
                return true;
            }

        });

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root root = (Root) unmarshaller.unmarshal(xsr);
    }

}

Related Example

Upvotes: 3

Related Questions