Details
Description
I am using a Castor mapping file to marshal java objects to XML. I have read in forums that using a mapping file ensures that elements in the resulting xml will be exactly in the same order as they have been defined in the mapping file. But I see different ordering in different cases. Additionally, I sometimes see that attributes disappear from the resulting xml.
This is my mapping file:
-----------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<cst:mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cst="http://castor.exolab.org/"
xmlns="http://ACORD.org/Standards/Life/2"
xsi:schemaLocation="http://castor.exolab.org/ mapping.xsd">
<cst:class name="com.test.model.Person">
<cst:field name="firstName" type="java.lang.String">
<cst:bind-xml name="FirstName" node="element"/>
</cst:field>
<cst:field name="middleName" type="java.lang.String">
<cst:bind-xml name="MiddleName" node="element"/>
</cst:field>
<cst:field name="lastName" type="java.lang.String">
<cst:bind-xml name="LastName" node="element"/>
</cst:field>
<cst:field name="prefix" type="java.lang.String">
<cst:bind-xml name="Prefix" node="element"/>
</cst:field>
<cst:field name="suffix" type="java.lang.String">
<cst:bind-xml name="Suffix" node="element"/>
</cst:field>
<cst:field name="birthDate" type="java.lang.String" handler="com.test.fieldhandler.DateHandler">
<cst:bind-xml name="BirthDate" node="element"/>
</cst:field>
</cst:class>
<cst:class name="com.test.model.Party">
<cst:field name="id" type="java.lang.String">
<cst:bind-xml name="id" node="attribute"/>
</cst:field>
<cst:field name="partyTypeCode" type="java.lang.String">
<cst:bind-xml name="PartyTypeCode" node="element"/>
</cst:field>
<cst:field name="partyTypeCodeCode" type="java.lang.String">
<cst:bind-xml name="tc" node="attribute" location="PartyTypeCode"/>
</cst:field>
<cst:field name="fullName" type="java.lang.String">
<cst:bind-xml name="FullName" node="element"/>
</cst:field>
<cst:field name="govtID" type="java.lang.String">
<cst:bind-xml name="GovtID" node="element"/>
</cst:field>
<cst:field name="govtIDTC" type="java.lang.String">
<cst:bind-xml name="GovtIDTC" node="element"/>
</cst:field>
<cst:field name="govtIDTCCode" type="java.lang.String">
<cst:bind-xml name="tc" node="attribute" location="GovtIDTC"/>
</cst:field>
<cst:field name="residenceState" type="java.lang.String">
<cst:bind-xml name="ResidenceState" node="element"/>
</cst:field>
<cst:field name="person" type="com.test.model.Person">
<cst:bind-xml name="Person" node="element"/>
</cst:field>
</cst:class>
</cst:mapping>
This is the java class that I use for testing:
----------------------------------------------------------
public class MarshallerTest {
public static void main (String[] args) {
Party party = getParty();
try {
Mapping map = new Mapping();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL mappingFileURL = classLoader.getResource("Mapping.xml");
map.loadMapping(mappingFileURL);
Marshaller marshaller = new Marshaller();
marshaller.setMapping(map);
marshaller.setNamespaceMapping("", "http://ACORD.org/Standards/Life/2");
marshaller.setSuppressNamespaces(true);
StringWriter writer = new StringWriter();
marshaller.setWriter(writer);
marshaller.marshal(party);
System.out.println(writer.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
private static Party getParty() {
Party party = new Party();
party.setId("PaidProducerGUID1");
party.setPartyTypeCode("Person");
party.setPartyTypeCodeCode("1");
party.setGovtID("000000000");
party.setGovtIDTC("SSN");
party.setGovtIDTCCode("11");
Person person = new Person();
person.setFirstName("Andy");
person.setMiddleName("S");
person.setLastName("Roddick");
person.setPrefix("Mr.");
party.setPerson(person);
return party;
}
}
This is the result I expect:
--------------------------------------
<party xmlns="http://ACORD.org/Standards/Life/2" id="PaidProducerGUID1">
<PartyTypeCode tc="1"/>
<GovtID>000000000</GovtID>
<GovtIDTC tc="11"/>
<Person>
<FirstName>Andy</FirstName>
<MiddleName>S</MiddleName>
<LastName>Roddick</LastName>
<Prefix>Mr.</Prefix>
</Person>
</party>
But, this is the result I get (elements PartyTypeCode and GovtIDTC are not in their correct position):
---------------------------------------------------------------------------------------------------------------------------------------
<party xmlns="http://ACORD.org/Standards/Life/2" id="PaidProducerGUID1">
<GovtID>000000000</GovtID>
<Person>
<FirstName>Andy</FirstName>
<MiddleName>S</MiddleName>
<LastName>Roddick</LastName>
<Prefix>Mr.</Prefix>
</Person>
<PartyTypeCode tc="1"/>
<GovtIDTC tc="11"/>
</party>
Can you please see what is causing the incorrect element ordering? The xml has a strict ordering as it has to be validated against a schema and validation fails if the order is incorrect.
Many thanks,
Tausif
I'm sorry... this is the test class:
import java.io.StringWriter;
import java.net.URL;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Marshaller;
import com.objectedge.acord.model.Party;
import com.objectedge.acord.model.Person;
public class MarshallerTest {
public static void main (String[] args) {
Party party = getParty();
try { Mapping map = new Mapping(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); URL mappingFileURL = classLoader.getResource("Mapping.xml"); map.loadMapping(mappingFileURL); Marshaller marshaller = new Marshaller(); marshaller.setMapping(map); marshaller.setNamespaceMapping("", "http://ACORD.org/Standards/Life/2"); marshaller.setSuppressNamespaces(true); StringWriter writer = new StringWriter(); marshaller.setWriter(writer); marshaller.marshal(party); System.out.println(writer.toString()); } catch (Exception e) { e.printStackTrace(); }
}
private static Party getParty() { Party party = new Party(); party.setId("PaidProducerGUID1"); party.setPartyTypeCode(null); // DELIBERATELY SETTING NULL HERE party.setPartyTypeCodeCode("1"); party.setGovtID("000000000"); party.setGovtIDTC(null); // DELIBERATELY SETTING NULL HERE party.setGovtIDTCCode("11"); Person person = new Person(); person.setFirstName("Andy"); person.setMiddleName("S"); person.setLastName("Roddick"); person.setPrefix("Mr."); party.setPerson(person); return party; }
}