Another Jaxb binding question
I think I have finally narrowed down one of my problems. I am using Jaxb w/Moxy implementation. I am using Xpath notation in my binding file. I am not getting the desired results.
The original jaxb generated class is heavily nested, for the sake of testing, I slimmed down the code to the below Condition.java.
Condition.java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "condition", propOrder = {
"diagnosisPriority",
"problemDate",
"problemType",
"problemName",
"problemCode",
"ageAtOnset",
"problemStatus",
"comment"
})
public class Condition {
protected BigInteger diagnosisPriority;
protected IvlTs problemDate;
protected Cd problemType;
@XmlElement(required = true)
protected Object problemName;
protected Cd problemCode;
protected BigInteger ageAtOnset;
protected Ce problemStatus;
protected List<Comment> comment;
//ommitted getters and setters
Class I created: conditionConnect.java
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class conditionConnect {
private Condition connectX;
public Condition getconditionConnect() {
return connectX;
}
public void setconditionConnect(Condition connectX) {
this.connectX = connectX;
}
}
My first test was to create an object model, and marshall it to xml. This was done successfully with the code below:
public static void main(String[] args) {
try {
int AgeInt = 36;
int DiagnoseInt = 5;
Condition InstCon = new Condition();
Cd myProblem = new Cd();
InstCon.setDiagnosisPriority(BigInteger.valueOf(DiagnoseInt));
InstCon.setProblemType(myProblem);
InstCon.setProblemName("I have Asthma");
InstCon.setAgeAtOnset(BigInteger.valueOf(AgeInt));
myProblem.setCode("1223343");
myProblem.setCodeSystem("23433.23232.23232");
myProblem.setDisplayName("Asthma");
myProblem.setCodeSystemName("ICD-9");
JAXBContext jc1 = JAXBContext.newInstance(conditionConnect.class);
Marshaller marshaller1 = jc1.createMarshaller();
marshaller1.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
conditionConnect conVar = new conditionConnect();
conVar.setconditionConnect(InstCon);
marshaller1.marshal(conVar, System.out);
Output is so (success!):
<conditionConnect>
<diagnosisPriority>5</ns0:diagnosisPriority>
<problemType code="1223343" displayName="Asthma" codeSystem="23433.23232.23232" codeSystemName="ICD-9"/>
<problemName>I have Asthma</ns0:problemName>
<ageAtOnset>36</ageAtOnset>
</conditionConnect>
As I will be receiving data via xml string/file, I opted to use a binding file. An excerpt supplied for the Condition class is as follows
problem.xml - data input
<PROBLEM_MODULE>
<ID>91</ID>
<PR_ID>124</PR_ID>
<PROBLEM_TYPE>T</PROBLEM_TYPE>
<PROBLEM_NAME>Asthma</PROBLEM_NAME>
<PROBLEM_CODE>244.9</PROBLEM_CODE>
<PATIENT_AWARENESS>N</PATIENT_AWARENESS>
<TREATING_PROVIDER_ID>23456</TREATING_PROVIDER_ID>
<PROBLEM_CS>ICD9</PCM_PROBLEM_CS>
</PROBLEM_MODULE>
my binding file (conditionsBinding.xml)
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="hl7.astm.greenccd.org"
xml-mapping-metadata-complete="true">
<java-types>
<java-type name="Condition" >
<xml-root-element name="PROBLEM_MODULE" />
<xml-type prop-order="diagnosisPriority problemDate problemType problemName problemCode ageAtOnset problemStatus comment"/>
<java-attributes>
<xml-element java-attribute="diagnosisPriority" xml-path="ID/text()" />
<xml-element java-attribute="problemDate" />
<xml-element java-attribute="problemType" name="PROBLEM_TYPE" type="Cd"/>
<xml-element java-attribute="problemName" />
<xml-element java-attribute="problemCode" />
<xml-element java-attribute="ageAtOnset" xml-path="PCM_TREATING_PROVIDER_ID/text()" />
<xml-element java-attribute="problemStatus" />
<xml-element java-attribute="comment" />
</java-attributes>
</java-type>
<java-type name="Cd">
<xml-type prop-order="code codeSystem displayName codeSystemName"/>
<java-attributes>
<xm开发者_运维问答l-attribute java-attribute="code" xml-path="PR_ID/text()"/>
<xml-attribute java-attribute="codeSystem" xml-path="PROBLEM_CODE/text()"/>
<xml-attribute java-attribute="displayName" xml-path="PROBLEM_NAME/text()"/>
<xml-attribute java-attribute="codeSystemName" xml-path="PCM_PROBLEM_CS/text()"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
The Main Code w/ binding and xml input:
public static void main(String[] args) {
try {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, new File("src/conditions/exec/conditionsBinding.xml"));
JAXBContext jc = JAXBContext.newInstance(new Class[] {Condition.class, Cd.class}, properties);
Unmarshaller u = jc.createUnmarshaller();
Condition conditionInput = (Condition) u.unmarshal(
new File("src/conditions/exec/problems.xml"));
//Marshall Code
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, new File("src/conditions/exec/binding.xml"));
JAXBContext resultJC = JAXBContext.newInstance(new Class[] {Condition.class}, properties);
Marshaller resultMarshaller = resultJC.createMarshaller();
resultMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
resultMarshaller.marshal(conditionInput, System.out);
Output from above main code:
<Condition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<diagnosisPriority>91</diagnosisPriority>
<problemType/>
<ageAtOnset>23456</ageAtOnset>
</Condition>
THE PROBLEM: When doing the binding, the tag
<problemType/>
Comes out empty, I am attempting to link Cd to problemType, so the xml output from problemType should be as so:
<problemType code="1223343" displayName="Asthma" codeSystem="23433.23232.23232" codeSystemName="ICD-9"/>
Please advise what I am missing from the binding file.
EDIT: binding.xml file. I use this file to marshal the xml element names to the variable names in the java objects:
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="hl7.astm.greenccd.org"
xml-mapping-metadata-complete="true">
<java-types>
<java-type name="Condition" xml-accessor-type="FIELD">
<xml-root-element name="Condition"/>
</java-type>
<java-type name="Cd" xml-accessor-type="FIELD">
<xml-root-element name="problemType"/>
</java-type>
</java-types>
</xml-bindings>
Note: I have tested the code without binding.xml, and it gave me the same results w/ different element names. The Main.java code without the binding.xml is as follows:
public static void main(String[] args) {
try {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, new File("src/conditions/exec/conditionsBinding.xml"));
JAXBContext jc = JAXBContext.newInstance(new Class[] {Condition.class, Cd.class}, properties);
// create an Unmarshaller
Unmarshaller u = jc.createUnmarshaller();
Condition conditionInput = (Condition) u.unmarshal(
new File("src/conditions/exec/problems.xml"));
Marshaller resultMarshaller = jc.createMarshaller();
resultMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
resultMarshaller.marshal(conditionInput, System.out);
} catch (JAXBException je) {
je.printStackTrace();
}
}
Output without the binding.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<PROBLEM_MODULE>
<ID>91</ID>
<PROBLEM_TYPE/>
<TREATING_PROVIDER_ID>23456</TREATING_PROVIDER_ID>
</PROBLEM_MODULE>
The mapping of the Java Class / Field names to the problems.xml file is as follows:
<PROBLEM_MODULE>
<ID>91</ID> /* maps to class Condition: diagnosisPriority */
<PR_ID>124</PR_ID> /* maps to class Cd: code */
<PROBLEM_TYPE>T</PROBLEM_TYPE> /* class Condition: problemType - problemType is of type Cd.java - Cd.java is a list of attributes only
<PROBLEM_NAME>Asthma</PROBLEM_NAME> /* maps to class Cd: displayName*/
<PROBLEM_CODE>244.9</PROBLEM_CODE>/* maps to class Cd: codeSystem*/
<PATIENT_AWARENESS>N</PATIENT_AWARENESS>
<TREATING_PROVIDER_ID>23456</TREATING_PROVIDER_ID> /* maps to Condition: ageAtOnset */
<PROBLEM_CS>ICD9</PCM_PROBLEM_CS> /* maps to class Cd: codeSystemName*/
</PROBLEM_MODULE>
Further Note in the problems.xml file, for:
<PROBLEM_TYPE>T</PROBLEM_TYPE> /* class Condition: problemType - problemType is of type Cd.java - Cd.java is a list of attributes only
In my conditionsBinding.xml file, I have Problem_Type coded as follows:
<xml-element java-attribute="problemType" name="PROBLEM_TYPE" type="Cd"/>
The reason I did this is that Problem_Type has no root element or name="some_field", I initially tried doing in conditionsBinding.xml:
<xml-element java-attribute="problemType" type="Cd"/>
When I did that, I got no line of code for problemType, so I added a name="some_field" to test perhaps that may be my problem. I am following the examples in the moxy wiki, but there is something obvious that I am missing but I can't pinpoint it.
ADDITIONAL EDIT:
After changing the conditionsBinding.xml via the below supplied answer, I was able to get the same xml output. However, problemType should be a list of attributes, so I changed the code to the following: conditionsBinding.xml
<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="hl7.astm.greenccd.org" xml-mapping-metadata-complete="true">
<java-types>
<java-type name="Condition">
<xml-root-element name="PROBLEM_MODULE" />
<xml-type
prop-order="diagnosisPriority problemDate problemType problemName problemCode ageAtOnset problemStatus comment" />
<java-attributes>
<xml-element java-attribute="diagnosisPriority"
xml-path="ID/text()" />
<xml-element java-attribute="problemDate" />
<xml-element java-attribute="problemType" name="PROBLEM_TYPE"
xml-path="." />
<xml-element java-attribute="problemName" />
<xml-element java-attribute="problemCode" />
<xml-element java-attribute="ageAtOnset" name="PCM_TREATING_PROVIDER_ID" />
<xml-element java-attribute="problemStatus" />
<xml-element java-attribute="comment" />
</java-attributes>
</java-type>
<java-type name="Cd">
<xml-type prop-order="code codeSystem displayName codeSystemName" />
<java-attributes>
<xml-attribute java-attribute="code" name="PR_ID" />
<xml-attribute java-attribute="codeSystem" name="PROBLEM_CODE" />
<xml-attribute java-attribute="displayName" name="PROBLEM_NAME" />
<xml-attribute java-attribute="codeSystemName" name="PCM_PROBLEM_CS" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
The output came as follows (empty problemType tag):
<?xml version="1.0" encoding="UTF-8"?>
<Condition>
<diagnosisPriority>91</diagnosisPriority>
<problemType />
<ageAtOnset>23456</ageAtOnset>
</Condition>
Excerpt of Cd.java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "cd", propOrder = {
"originalText",
"qualifier"
})
public class Cd {
protected Object originalText;
protected List<Qualifier> qualifier;
@XmlAttribute(name = "code")
@XmlSchemaType(name = "anySimpleType")
protected String code;
@XmlAttribute(name = "displayName")
@XmlSchemaType(name = "anySimpleType")
protected String displayName;
@XmlAttribute(name = "codeSystem")
@XmlSchemaType(name = "anySimpleType")
protected String codeSystem;
@XmlAttribute(name = "codeSystemName")
@XmlSchemaType(name = "anySimpleType")
protected String codeSystemName;
@XmlAttribute(name = "nullFlavor")
protected NullFlavorType nullFlavor;
On another note, I realize is that I will need to later annotate problemCode, which is also a field in Conditions.java AND of type Cd, but will be mapped to different xml element names. Which would require another annotation block of Cd.java in the conditionsBinding.xml file. (Mappings are not real, but it will reflect something like the following:
Pseudo conditionsBinding.xml:
<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="hl7.astm.greenccd.org" xml-mapping-metadata-complete="true">
<java-types>
<java-type name="Condition">
<xml-root-element name="PROBLEM_MODULE" />
<xml-type
prop-order="diagnosisPriority problemDate problemType problemName problemCode ageAtOnset problemStatus comment" />
<java-attributes>
<xml-element java-attribute="diagnosisPriority"
xml-path="ID/text()" />
<xml-element java-attribute="problemDate" />
<xml-element java-attribute="problemType" name="PROBLEM_TYPE"
xml-path="." />
<xml-element java-attribute="problemName" />
<xml-element java-attribute="problemCode" name="PROBLEM_CODE_PSEUDO"
xml-path="."/>
<xml-element java-attribute="ageAtOnset" name="PCM_TREATING_PROVIDER_ID" />
<xml-element java-attribute="problemStatus" />
<xml-element java-attribute="comment" />
</java-attributes>
</java-type>
<java-type name="Cd">
<xml-type prop-order="code codeSystem displayName codeSystemName" />
<java-attributes>
<xml-element java-attribute="code" name="PR_ID" />
<xml-element java-attribute="codeSystem" name="PROBLEM_CODE" />
<xml-element java-attribute="displayName" name="PROBLEM_NAME" />
<xml-element java-attribute="codeSystemName" name="PCM_PROBLEM_CS" />
</java-attributes>
</java-type>
/* java-type name = Cd will be mapped to different xml elements for problemCode */
<java-type name="Cd">
<xml-type prop-order="code codeSystem displayName codeSystemName" />
<java-attributes>
<xml-element java-attribute="code" name="PR_ID_PSEUDO" />
<xml-element java-attribute="codeSystem" name="PROBLEM_CODE_PSEUDO" />
<xml-element java-attribute="displayName" name="PROBLEM_NAME_PSEUDO" />
<xml-element java-attribute="codeSystemName" name="PCM_PROBLEM_CS_PSEUDO" />
</java-attributes>
</java-type>
</java-types>
It is making me think my approach needs to be tweaked (not soley depending on binding). I was reading through the moxy user guide at http://wiki.eclipse.org/EclipseLink/UserGuide/MOXy . I have studied and considered the following options: JPA (using SAX/DOM - meet in the middle mapping), xml-join-nodes, and xml-adapter. I am not totally clear which of these options (if any) would help with my issue, your expert advice is highly appreciated.
UPDATE
In your example you are using binding.xml
to control the mapping for marshalling. In this binding file you have set xml-mapping-metadata-complete="true"
. This flags to MOXy that the annotations should be ignored and that the binding file specifies the complete metadata. It this flag is set to false or not specified then the binding file is used to augment the annotations.
binding.xml
Below I have removed xml-mapping-metadata-complete="true"
:
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="hl7.astm.greenccd.org">
<java-types>
<java-type name="Condition" xml-accessor-type="FIELD">
<xml-root-element name="Condition" />
</java-type>
<java-type name="Cd" xml-accessor-type="FIELD">
<xml-root-element name="problemType" />
</java-type>
</java-types>
</xml-bindings>
Output
Now the problemType data appears as attributes:
<?xml version="1.0" encoding="UTF-8"?>
<Condition>
<diagnosisPriority>91</diagnosisPriority>
<problemType code="124" displayName="Asthma" codeSystem="244.9" codeSystemName="ICD9"/>
</Condition>
The following should help:
conditionsBinding.xml
<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="hl7.astm.greenccd.org" xml-mapping-metadata-complete="true">
<java-types>
<java-type name="Condition">
<xml-root-element name="PROBLEM_MODULE" />
<xml-type
prop-order="diagnosisPriority problemDate problemType problemName problemCode ageAtOnset problemStatus comment" />
<java-attributes>
<xml-element java-attribute="diagnosisPriority"
xml-path="ID/text()" />
<xml-element java-attribute="problemDate" />
<xml-element java-attribute="problemType" name="PROBLEM_TYPE"
xml-path="." />
<xml-element java-attribute="problemName" />
<xml-element java-attribute="problemCode" />
<xml-element java-attribute="ageAtOnset" name="PCM_TREATING_PROVIDER_ID" />
<xml-element java-attribute="problemStatus" />
<xml-element java-attribute="comment" />
</java-attributes>
</java-type>
<java-type name="Cd">
<xml-type prop-order="code codeSystem displayName codeSystemName" />
<java-attributes>
<xml-element java-attribute="code" name="PR_ID" />
<xml-element java-attribute="codeSystem" name="PROBLEM_CODE" />
<xml-element java-attribute="displayName" name="PROBLEM_NAME" />
<xml-element java-attribute="codeSystemName" name="PCM_PROBLEM_CS" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
When I use it with your code I get:
<?xml version="1.0" encoding="UTF-8"?>
<Condition>
<diagnosisPriority>91</diagnosisPriority>
<problemType>
<code>124</code>
<codeSystem>244.9</codeSystem>
<displayName>Asthma</displayName>
<codeSystemName>ICD9</codeSystemName>
</problemType>
</Condition>
精彩评论