Java Jackson - serialize and deserialize XML string with namespaces kept?

118 views
Skip to first unread message

Phạm Hữu Bằng

unread,
May 4, 2020, 10:42:50 AM5/4/20
to jackson-user
I have this long XML string with multiples XML namespaces (this is generated from other sources) and the namespaces are randomly created by the authors.

I use this Maven dependency:

        <dependency>
           
<groupId>com.fasterxml.jackson.dataformat</groupId>
           
<artifactId>jackson-dataformat-xml</artifactId>
           
<version>2.8.7</version>
       
</dependency>


The task is: to **read this XML to a POJO object** and **add some other XML elements** and **serialize the POJO object to new XML string**. The original XML is as below:

   
<lcrmd:LandCoverGridCoverageMD
                           
xmlns:ad="http://inspire.ec.europa.eu/schemas/ad/4.0"
                           
xmlns:base="http://inspire.ec.europa.eu/schemas/base/3.3"
                           
xmlns:base2="http://inspire.ec.europa.eu/schemas/base2/2.0"
                           
xmlns:gco="http://www.isotc211.org/2005/gco"
                           
xmlns:gmd="http://www.isotc211.org/2005/gmd"
                           
xmlns:gn="http://inspire.ec.europa.eu/schemas/gn/4.0"
                           
xmlns:lcn="http://inspire.ec.europa.eu/schemas/lcn/4.0"
                           
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                           
xmlns:lcrmd="http://inspire.ec.europa.eu/schemas/lcrmd/4.0" xsi:schemaLocation="http://inspire.ec.europa.eu/schemas/lcrmd/4.0 http://test.datacove.eu/LandCoverRasterMDExt.xsd">
                           
<lcrmd:inspireId>
                               
<base:Identifier>
                                   
<base:localId>CLC Test</base:localId>
                                   
<base:namespace>Datacove.eu</base:namespace>
                               
</base:Identifier>
                           
</lcrmd:inspireId>
                           
<lcrmd:beginLifespanVersion>2018-07-18T00:00:00</lcrmd:beginLifespanVersion>
                           
<lcrmd:extent>
                               
<gmd:EX_Extent>
                                   
<gmd:geographicElement>
                                   
<gmd:EX_GeographicBoundingBox>
                                   
<gmd:westBoundLongitude>
                                   
<gco:Decimal>1.0</gco:Decimal>
                                   
</gmd:westBoundLongitude>
                                   
<gmd:eastBoundLongitude>
                                   
<gco:Decimal>10.0</gco:Decimal>
                                   
</gmd:eastBoundLongitude>
                                   
<gmd:southBoundLatitude>
                                   
<gco:Decimal>1.0</gco:Decimal>
                                   
</gmd:southBoundLatitude>
                                   
<gmd:northBoundLatitude>
                                   
<gco:Decimal>3.0</gco:Decimal>
                                   
</gmd:northBoundLatitude>
                                   
</gmd:EX_GeographicBoundingBox>
                                   
</gmd:geographicElement>
                               
</gmd:EX_Extent>
                           
</lcrmd:extent>
                           
<lcrmd:name>Corine Land Cover Coverage Test</lcrmd:name>
                           
<lcrmd:nomenclatureDocumentation>
                               
<lcn:LandCoverNomenclature>
                                   
<lcn:inspireId>
                                   
<base:Identifier>
                                   
<base:localId>CLC Nom Test</base:localId>
                                   
<base:namespace>Datacove.eu</base:namespace>
                                   
</base:Identifier>
                                   
</lcn:inspireId>
                                   
<lcn:nomenclatureCodeList/>
                                   
<lcn:responsibleParty>
                                   
<base2:RelatedParty>
                                   
<!-- individual responsible for the vessel -->
                                   
<base2:individualName>
                                   
<gmd:LocalisedCharacterString>Jane Doe</gmd:LocalisedCharacterString>
                                   
</base2:individualName>
                                   
<!-- organization responsible for the nomenclature  -->
                                   
<base2:organisationName>
                                   
<gmd:LocalisedCharacterString>Corine Unlimited</gmd:LocalisedCharacterString>
                                   
</base2:organisationName>
                                   
<base2:contact>
                                   
<base2:Contact>
                                   
<base2:address>
                                   
<ad:AddressRepresentation>
                                   
<ad:adminUnit>
                                   
<gn:GeographicalName>
                                   
<gn:language>eng</gn:language>
                                   
<!-- language of municipality name-->


                                   
<gn:nativeness
                                   
nilReason="missing" xsi:nil="true"/>


                                   
<gn:nameStatus
                                   
nilReason="missing" xsi:nil="true"/>


                                   
<gn:sourceOfName
                                   
nilReason="missing" xsi:nil="true"/>


                                   
<gn:pronunciation
                                   
nilReason="missing" xsi:nil="true"/>
                                   
<gn:spelling>
                                   
<gn:SpellingOfName>
                                   
<!-- municipality name -->
                                   
<gn:text>Corine</gn:text>
                                   
<gn:script>Latn</gn:script>
                                   
</gn:SpellingOfName>
                                   
</gn:spelling>
                                   
</gn:GeographicalName>
                                   
</ad:adminUnit>
                                   
<!-- Street address -->
                                   
<ad:locatorDesignator>Seaside Lane 1</ad:locatorDesignator>
                                   
<!-- Postal Code-->
                                   
<ad:postCode>OC-1234</ad:postCode>
                                   
</ad:AddressRepresentation>
                                   
</base2:address>
                                   
<!-- e-mail of responsible person -->
                                   
<base2:electronicMailAddress>jane...@Corine.eu</base2:electronicMailAddress>
                                   
<!-- phonel of responsible person -->
                                   
<base2:telephoneVoice>+12 3 456 789</base2:telephoneVoice>
                                   
<!-- web URI of responsible organization-->
                                   
<base2:website>http://www.Corine.eu</base2:website>
                                   
</base2:Contact>
                                   
</base2:contact>
                                   
</base2:RelatedParty>
                                   
</lcn:responsibleParty>
                               
</lcn:LandCoverNomenclature>
                           
</lcrmd:nomenclatureDocumentation>
                           
<lcrmd:validFrom>2018-07-18</lcrmd:validFrom>
                           
<lcrmd:validTo>2020-07-18</lcrmd:validTo>
                       
</lcrmd:LandCoverGridCoverageMD>



What I've done so far is, to map this nested XML string with **random child XML elements** to a POJO object with:

    public class CoverageMetadata {


       
@JsonAnyGetter
       
public Map<String, Object> getGlobalAttributesMap() {
           
return this.additionalProperties;
       
}


       
@JsonAnySetter
       
public void setAdditionalProperty(String name, Object value) {
         
this.additionalProperties.put(name, value);
       
}


   
}


and the code to deserialize the XML string to this object:

    XmlMapper xmlMapper = new XmlMapper();
    xmlMapper
.readValue(xmlString, CoverageMetadata.class);


When I try to serialize the xmlMapper to XML, **I got the result without namespaces for XML elements**

       
 <LandCoverGridCoverageMD>
       
<schemaLocation>
    http://inspire.ec.europa.eu/schemas/lcrmd/4.0 http://test.datacove.eu/LandCoverRasterMDExt.xsd
   
</schemaLocation>
       
<inspireId>
           
<Identifier>
               
<localId>CLC Test</localId>
               
<namespace>Datacove.eu</namespace>
           
</Identifier>
       
</inspireId>
       
<beginLifespanVersion>2018-07-18T00:00:00</beginLifespanVersion>
       
<extent>
           
<EX_Extent>
               
<geographicElement>
                   
<EX_GeographicBoundingBox>
                       
<westBoundLongitude>
                           
<Decimal>1.0</Decimal>
                       
</westBoundLongitude>
                       
<eastBoundLongitude>
                           
<Decimal>10.0</Decimal>
                       
</eastBoundLongitude>
                       
<southBoundLatitude>
                           
<Decimal>1.0</Decimal>
                       
</southBoundLatitude>
                       
<northBoundLatitude>
                           
<Decimal>3.0</Decimal>
                       
</northBoundLatitude>
                   
</EX_GeographicBoundingBox>
               
</geographicElement>
           
</EX_Extent>
       
</extent>
       
<name>Corine Land Cover Coverage Test</name>
       
<nomenclatureDocumentation>
           
<LandCoverNomenclature>
               
<inspireId>
                   
<Identifier>
                       
<localId>CLC Nom Test</localId>
                       
<namespace>Datacove.eu</namespace>
                   
</Identifier>
               
</inspireId>
               
<nomenclatureCodeList />
               
<responsibleParty>
                   
<RelatedParty>
                       
<individualName>
                           
<LocalisedCharacterString>Jane Doe</LocalisedCharacterString>
                       
</individualName>
                       
<organisationName>
                           
<LocalisedCharacterString>Corine Unlimited</LocalisedCharacterString>
                       
</organisationName>
                       
<contact>
                           
<Contact>
                               
<address>
                                   
<AddressRepresentation>
                                       
<adminUnit>
                                           
<GeographicalName>
                                               
<language>eng</language>
                                               
<nativeness>
                                                   
<nilReason>missing</nilReason>
                                                   
<nil>true</nil>
                                               
</nativeness>
                                               
<nameStatus>
                                                   
<nilReason>missing</nilReason>
                                                   
<nil>true</nil>
                                               
</nameStatus>
                                               
<sourceOfName>
                                                   
<nilReason>missing</nilReason>
                                                   
<nil>true</nil>
                                               
</sourceOfName>
                                               
<pronunciation>
                                                   
<nilReason>missing</nilReason>
                                                   
<nil>true</nil>
                                               
</pronunciation>
                                               
<spelling>
                                                   
<SpellingOfName>
                                                       
<text>Corine</text>
                                                       
<script>Latn</script>
                                                   
</SpellingOfName>
                                               
</spelling>
                                           
</GeographicalName>
                                       
</adminUnit>
                                       
<locatorDesignator>Seaside Lane 1</locatorDesignator>
                                       
<postCode>OC-1234</postCode>
                                   
</AddressRepresentation>
                               
</address>
                               
<electronicMailAddress>jane...@Corine.eu</electronicMailAddress>
                               
<telephoneVoice>+12 3 456 789</telephoneVoice>
                               
<website>http://www.Corine.eu</website>
                           
</Contact>
                       
</contact>
                   
</RelatedParty>
               
</responsibleParty>
           
</LandCoverNomenclature>
       
</nomenclatureDocumentation>
       
<validFrom>2018-07-18</validFrom>
       
<validTo>2020-07-18</validTo>
   
</LandCoverGridCoverageMD>


 

Tatu Saloranta

unread,
May 4, 2020, 5:33:51 PM5/4/20
to jackson-user
Correct: this will not work -- @JsonAnyGetter and @JsonAnySetter would
not retain namespace information, only local name. So you can not
really use that approach, unfortunately.
The only source for namespace information is use of

@JacksonXmlProperty

on properties.

-+ Tatu +-
Reply all
Reply to author
Forward
0 new messages