java - Using JAXB to unmarshal xml with map-like structure to object -
i'm trying unmarshal poorly designed xml object. xml built using generic type
element can have number of items
name
. depending on value of type
in something
below, include properties different. it's bypassing xsd rulse (yes, has xsd, it's utterly useless).
the xml get:
<something type="actualtype"> <property name="prop1">value1</property> <property name="prop2">value2</property> ... </something>
what should have been:
<actualtype> <prop1>value1</prop1> <prop2>value2</prop1> </actualtype>
how should represented in java:
@xmltype(name="actualtype") public class actualtype { @xmlelement public x prop1 @xmlelement public y prop2 }
the actual question(s):
is there basic support in jaxb (without external dependencies)? if not, can write custom annotations such able reuse same logic other services using schema?
there couple of ways support use case:
option #1 - jaxb (jsr-222) implementation
if need read xml objects, leverage streamreaderdelegate
, following. makes bad xml appear if xml:
import javax.xml.bind.*; import javax.xml.stream.*; import javax.xml.stream.util.streamreaderdelegate; import javax.xml.transform.stream.streamsource; public class demo { public static void main(string[] args) throws exception { xmlinputfactory xif = xmlinputfactory.newfactory(); xmlstreamreader xsr = xif.createxmlstreamreader(new streamsource("src/forum16529016/input.xml")); xsr = new streamreaderdelegate(xsr) { @override public string getlocalname() { string localname = super.getlocalname(); if(!"property".equals(localname) && super.geteventtype() == xmlstreamreader.start_element) { return localname; } if(super.geteventtype() == xmlstreamreader.start_element) { return super.getattributevalue(null, "name"); } return localname; } }; jaxbcontext jc = jaxbcontext.newinstance(actualtype.class); unmarshaller unmarshaller = jc.createunmarshaller(); actualtype actualtype = unmarshaller.unmarshal(xsr, actualtype.class).getvalue(); system.out.println(actualtype.prop1); system.out.println(actualtype.prop2); } }
option #2 - eclipselink jaxb (moxy's) @xmlpath extension
note: i'm eclipselink jaxb (moxy) lead , member of jaxb (jsr-222) expert group.
moxy has @xmlpath
extension enables map use case.
import javax.xml.bind.annotation.xmltype; import org.eclipse.persistence.oxm.annotations.xmlpath; @xmltype(name="actualtype") public class actualtype { @xmlpath("property[@name='prop1']/text()) public x prop1 @xmlpath("property[@name='prop1']/text()) public y prop2 }
for more information
Comments
Post a Comment