@XmlElements tagged with @XmlJavaTypeAdapters?

I have such a situation.

@XmlType(name ="", propOrder={"value"}) @XmlRootElement(name = "compound") public class Compound extends Value { @XmlElements({ @XmlElement(name="simple", type=Simple.class), @XmlElement(name="compound", type=Compound.class) }) protected List<Value> value; // ... } 

Thus, a compound is a list of both simple and / or compound. Both of them extend from a value that is defined as

 public abstract class Value implements Serializable {} 

Simple is the class marked with the adapter for marshal / unmarshal to / from a simple string.

 @XmlJavaTypeAdapter(SimpleAdapter.class) public class Simple extends Value { private java.lang.String simple; // ... } 

The connection does not need an adapter.

The problem is that if I use Simple 'as is', it will correctly marshal / non-marshals like

 <simple>my.text.here</simple> 

but if I use it inside Compound, it outputs something like

 <compound> //... <simple> <value>my.text.here</value> </simple> //... </compound> 

And I'm just wondering why ... Am I missing something? How can I remove this value? It seems to me that the adapter is not used at all, is it possible to use adapters in the types marked inside @XmlElements?

EDIT

After several tests, I found that the problem might be how I handle a simple instance. Therefore, I simplify my initial question in:

Given a simple class like

 @XmlRootElement("simple") public class Simple { private java.lang.String innerText; // getters/setters } 

how can i get marshalled output like

 <simple> my.inner.text.here </simple> 

instead

 <simple> <value>my.inner.text.here</value> </simple> 

?

+7
source share
2 answers

Looks like you want private java.lang.String innerText; was @XmlValue of your Simple class. Try annotating String in Simple with the @XmlValue tag:

 @XmlRootElement("simple") public class Simple { @XmlValue private java.lang.String innerText; //getters/setters } 

Or, if you use annotations for the getter method (which, I believe, based on your XML output in the question, changes the @XmlElement tag to the @XmlValue tag:

 @XmlValue public java.lang.String getInnerText() { return innerText; } 

When I do this, I get the output you are looking for in your edited question.

+2
source

The answer given by bamana is correct, however the exception you see is due to an error in the JAXB reference implementation. This error also existed in EclipseLink JAXB (MOXy) , but was fixed in thread 2.3.0, nightly download can be got here:

As a workaround, you can use the XmlAdapter approach that was in your original question:

Simpleadapter

 import javax.xml.bind.annotation.adapters.XmlAdapter; public class SimpleAdapter extends XmlAdapter<String, Simple> { @Override public Simple unmarshal(String v) throws Exception { Simple simple = new Simple(); simple.setSimple(v); return simple; } @Override public String marshal(Simple v) throws Exception { return v.getSimple(); } } 

Plain

 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlJavaTypeAdapter(SimpleAdapter.class) public class Simple extends Value { private java.lang.String simple; public java.lang.String getSimple() { return simple; } public void setSimple(java.lang.String simple) { this.simple = simple; } } 

Compound

 import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement(name = "compound") @XmlAccessorType(XmlAccessType.FIELD) public class Compound extends Value { @XmlElements({ @XmlElement(name = "simple", type = Simple.class), @XmlElement(name = "compound", type = Compound.class) }) protected List<Value> value; public List<Value> getValue() { return value; } public void setValue(List<Value> value) { this.value = value; } } 

Value

 import java.io.Serializable; public abstract class Value implements Serializable {} 

Demo

 import java.io.File; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Compound.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); Compound compound = (Compound) unmarshaller.unmarshal(new File("input.xml")); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(compound, System.out); } } 

Input.xml

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <compound> <simple> <simple>FOO</simple> </simple> <compound/> </compound> 
0
source

All Articles