Reputation: 1526
I am trying to use JAXB
to parse the following XML
. I removed irrelevant parts. Unfortunately the original XML
is generated by a third party application and I do not have the DTD
or an XSD
file available, so I am building my JAXB
code by hand.
<add>
<add-attr attr-name="UserName">
<value type="string">User1</value>
</add-attr>
<add-attr attr-name="Name">
<value type="structured">
<component name="familyName">Doe</component>
<component name="givenName">John</component>
</value>
</add-attr>
</add>
The problem is of course the <value>
element. This can be a element with plain text, or if its attribute type is "structured, a list of <component>
elements.
I have created two classes (value1 and value2) which implement the two options, but I cannot tell JAXB
which one to use, because the elements are both named "value". Is there any solution?
Upvotes: 1
Views: 469
Reputation: 149047
Option #1 - One Value Class
You could have one Value
class that includes a String
property annotated with @XmlMixed
.
package forum13232991;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Value {
@XmlAttribute
String type;
@XmlMixed
List<String> value;
@XmlElement(name="component")
List<Component> components;
}
Option #2 - Multiple value Classes Via XmlAdapter
If you want them to be separate classes you could leverage an XmlAdapter
for this:
ValueAdapter
package forum13232991;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class ValueAdapter extends XmlAdapter<Value, Object> {
@Override
public Value marshal(Object object) throws Exception {
Value value = new Value();
if(object instanceof StructuredValue) {
StructuredValue structuredValue = (StructuredValue) object;
value.type = "structured";
value.components = structuredValue.components;
} else {
StringValue stringValue = (StringValue) object;
value.value.add(stringValue.value);
}
return value;
}
@Override
public Object unmarshal(Value value) throws Exception {
if("string".equals(value.type)) {
StringValue stringValue = new StringValue();
StringBuilder strBldr = new StringBuilder();
for(String string : value.value) {
strBldr.append(string);
}
stringValue.value = strBldr.toString();
return stringValue;
} else {
StructuredValue structuredValue = new StructuredValue();
structuredValue.components = value.components;
return structuredValue;
}
}
}
AddAttr
package forum13232991;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
public class AddAttr {
@XmlJavaTypeAdapter(ValueAdapter.class)
Object value;
}
For More Information
Upvotes: 2
Reputation: 43937
One approach would be to create an XSL transformation which added an xsi:type attribute to the value elements based on the type attribute. All your Value elements could then extend from the same BaseValue class and the add-attr element could have a reference to this BaseValue.
Upvotes: 1