Your ADDITION is correct, MOXy isn't unmarshalling wrong property names, it just unmarshals to property names that correspond to what the mapped property/field names would be in the generated classes.
What the Solution Should Be
binding.xml
The default XML Schema to Java naming rules in JAXB is to remove the _
. You can supply a binding file to have this behaviour be different.
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings underscoreBinding="asCharInWord"/>
</jaxb:bindings>
Demo
Using MOXy's Dynamic JAXB, below is an example of how you can leverage the bindings file.
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
StreamSource schemaSource = new StreamSource("src/forum20146935/schema.xsd");
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(DynamicJAXBContextFactory.EXTERNAL_BINDINGS_KEY, new StreamSource("src/forum20146935/binding.xml"));
JAXBContext jc = DynamicJAXBContextFactory.createContextFromXSD(schemaSource, null, Demo.class.getClassLoader(), properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum20146935/input.xml");
DynamicEntity root = (DynamicEntity) unmarshaller.unmarshal(xml);
System.out.println(root.get("foo_bar"));
}
}
Why Didn't it Work?
As I mentioned earlier MOXy will base the dynamic property name based on the corresponding mapped field/property generated by XJC. This happens to look something like where the property name has the _
but the corresponding mapped field does not.
@XmlElement(name = "foo_bar", required = true)
protected String fooBar;
public String getFoo_Bar() {
return fooBar;
}
public void setFoo_Bar(String value) {
this.fooBar = value;
}
What you Could Do Instead
- Use the transformed key name.
You could use the
getValueByXPath
functionality on the MOXyJAXBContext
to interact with the objects in a more XML like way.import java.io.File; import java.util.*; import javax.xml.bind.*; import javax.xml.transform.stream.StreamSource; import org.eclipse.persistence.dynamic.DynamicEntity; import org.eclipse.persistence.jaxb.JAXBHelper; import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory; public class Demo { public static void main(String[] args) throws Exception { StreamSource schemaSource = new StreamSource("src/forum20146935/schema.xsd"); Map<String, Object> properties = new HashMap<String, Object>(1); properties.put(DynamicJAXBContextFactory.EXTERNAL_BINDINGS_KEY, new StreamSource("src/forum20146935/binding.xml")); JAXBContext jc = DynamicJAXBContextFactory.createContextFromXSD(schemaSource, null, Demo.class.getClassLoader(), properties); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum20146935/input.xml"); DynamicEntity root = (DynamicEntity) unmarshaller.unmarshal(xml); String fooBar = JAXBHelper.getJAXBContext(jc).getValueByXPath(root, "foo_bar/text()", null, String.class); System.out.println(fooBar); } }