java - JAXB unmarshalling from XmlStreamReader results in null object -
i created java procedure unmarshalling xml message "starttag" can provided start unmarshalling @ particular element within message. used xmlstreamreader
make selection.
a complete copy-pastable demo of problem run below. 'xml' message need work with. unfortunately yields null
car object in result, while 'xmlstripped' message yields unmarshalled result.
i isolated problem xmlns="http://www.example.com/type"
namespace in <response>
element. when remove this, 'xml' unmarshalled.
i have no control on xml. 'xml' variable need work with. have little control on xsd/objectfactory
, first course of action solution in unmarshalling procedure.
please let me know if know why fails , if have solution. thanks!
import javax.xml.bind.jaxbcontext; import javax.xml.bind.jaxbelement; import javax.xml.bind.jaxbexception; import javax.xml.bind.unmarshaller; import javax.xml.bind.annotation.*; import javax.xml.namespace.qname; import javax.xml.stream.xmlinputfactory; import javax.xml.stream.xmlstreamexception; import javax.xml.stream.xmlstreamreader; import java.io.reader; import java.io.stringreader; public class xmlstreamreaderunmarshallingtest { private static jaxbcontext jaxbcontext; static { try { jaxbcontext = jaxbcontext.newinstance(objectfactory.class); } catch (jaxbexception e) { e.printstacktrace(); } } private static string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<soapenv:envelope xmlns:xsd=\"http://www.w3.org/2001/xmlschema\" \n" + "\txmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" \n" + "\txmlns:xsi=\"http://www.w3.org/2001/xmlschema-instance\">\n" + "\t<soapenv:body>\n" + "\t\t<response xmlns=\"http://www.example.com/type\">\n" + "\t\t\t<type:serviceresponse xmlns:type=\"http://www.example.com/type\">\n" + "\t\t\t\t<body>\n" + "\t\t\t\t\t<car>\n" + "\t\t\t\t\t\t<brand>mitsubishi</brand>\n" + "\t\t\t\t\t\t<color>red</color>\n" + "\t\t\t\t\t</car>\n" + "\t\t\t\t</body>\n" + "\t\t\t</type:serviceresponse>\n" + "\t\t</response>\n" + "\t</soapenv:body>\n" + "</soapenv:envelope>"; private static string xmlstripped = "<type:serviceresponse xmlns:type=\"http://www.example.com/type\">\n" + "\t\t\t\t<body>\n" + "\t\t\t\t\t<car>\n" + "\t\t\t\t\t\t<brand>mitsubishi</brand>\n" + "\t\t\t\t\t\t<color>red</color>\n" + "\t\t\t\t\t</car>\n" + "\t\t\t\t</body>\n" + "\t\t\t</type:serviceresponse>"; public static void main(string[] args) throws jaxbexception, xmlstreamexception { readxml(xml, "serviceresponse"); readxml(xmlstripped, "serviceresponse"); } private static void readxml(string inputxml, string startfromelement) throws jaxbexception, xmlstreamexception { final xmlinputfactory xmlinputfactory = xmlinputfactory.newfactory(); final reader reader = new stringreader(inputxml); final xmlstreamreader xmlstreamreader = xmlinputfactory.createxmlstreamreader(reader); final xmlstreamreader streamreader = skiptoelement(xmlstreamreader, startfromelement); final myserviceresponse serviceresponse = (myserviceresponse) unmarshal(streamreader); if(serviceresponse.getbody().getcar() == null) { system.out.println("it didn't work :-("); } else { system.out.println("it worked"); } } private static xmlstreamreader skiptoelement(final xmlstreamreader xsr, final string startatelement) throws xmlstreamexception { while (startatelement != null && xsr.hasnext()) { xsr.next(); if (xsr.hasname()) { final string name = xsr.getname().getlocalpart(); if (name.equals(startatelement)) { return xsr; } } } throw new illegalargumentexception(string.format("could not find element %s in response", startatelement)); } private static object unmarshal(final xmlstreamreader xsr) throws jaxbexception { final object entity = unmarshaller(jaxbcontext).unmarshal(xsr); return (entity instanceof jaxbelement ? ((jaxbelement) entity).getvalue() : entity); } // create unmarshaller every time private static unmarshaller unmarshaller(jaxbcontext context) throws jaxbexception { return context.createunmarshaller(); } } @xmlaccessortype(xmlaccesstype.field) @xmltype(name = "myserviceresponse", proporder = { }) class myserviceresponse { @xmlelement(name = "body") protected myserviceresponse.body body; /** * gets value of body property. * * @return * possible object * {@link myserviceresponse.body } * */ public myserviceresponse.body getbody() { return body; } /** * sets value of body property. * * @param value * allowed object * {@link myserviceresponse.body } * */ public void setbody(myserviceresponse.body value) { this.body = value; } /** * <p>java class anonymous complex type. * * <p>the following schema fragment specifies expected content contained within class. * * <pre> * <complextype> * <complexcontent> * <restriction base="{http://www.w3.org/2001/xmlschema}anytype"> * <all> * <element name="car" minoccurs="0"> * <complextype> * <complexcontent> * <restriction base="{http://www.w3.org/2001/xmlschema}anytype"> * <all> * <element name="brand" type="{http://www.w3.org/2001/xmlschema}string" minoccurs="0"/> * <element name="color" type="{http://www.w3.org/2001/xmlschema}string" minoccurs="0"/> * </all> * </restriction> * </complexcontent> * </complextype> * </element> * </all> * </restriction> * </complexcontent> * </complextype> * </pre> * * */ @xmlaccessortype(xmlaccesstype.field) @xmltype(name = "", proporder = { }) public static class body { @xmlelement(name = "car") protected myserviceresponse.body.car car; /** * gets value of car property. * * @return * possible object * {@link myserviceresponse.body.car } * */ public myserviceresponse.body.car getcar() { return car; } /** * sets value of car property. * * @param value * allowed object * {@link myserviceresponse.body.car } * */ public void setcar(myserviceresponse.body.car value) { this.car = value; } /** * <p>java class anonymous complex type. * * <p>the following schema fragment specifies expected content contained within class. * * <pre> * <complextype> * <complexcontent> * <restriction base="{http://www.w3.org/2001/xmlschema}anytype"> * <all> * <element name="brand" type="{http://www.w3.org/2001/xmlschema}string" minoccurs="0"/> * <element name="color" type="{http://www.w3.org/2001/xmlschema}string" minoccurs="0"/> * </all> * </restriction> * </complexcontent> * </complextype> * </pre> * * */ @xmlaccessortype(xmlaccesstype.field) @xmltype(name = "", proporder = { }) public static class car { @xmlelement(name = "brand") protected string brand; @xmlelement(name = "color") protected string color; /** * gets value of brand property. * * @return * possible object * {@link string } * */ public string getbrand() { return brand; } /** * sets value of brand property. * * @param value * allowed object * {@link string } * */ public void setbrand(string value) { this.brand = value; } /** * gets value of color property. * * @return * possible object * {@link string } * */ public string getcolor() { return color; } /** * sets value of color property. * * @param value * allowed object * {@link string } * */ public void setcolor(string value) { this.color = value; } } } } @xmlregistry class objectfactory { private final static qname _serviceresponse_qname = new qname("http://www.example.com/type", "serviceresponse"); /** * create new objectfactory can used create new instances of schema derived classes package: com.example.type * */ public objectfactory() { } /** * create instance of {@link myserviceresponse } * */ public myserviceresponse createmyserviceresponse() { return new myserviceresponse(); } /** * create instance of {@link myserviceresponse.body } * */ public myserviceresponse.body createmyserviceresponsebody() { return new myserviceresponse.body(); } /** * create instance of {@link myserviceresponse.body.car } * */ public myserviceresponse.body.car createmyserviceresponsebodycar() { return new myserviceresponse.body.car(); } /** * create instance of {@link jaxbelement }{@code <}{@link myserviceresponse }{@code >}} * */ @xmlelementdecl(namespace = "http://www.example.com/type", name = "serviceresponse") public jaxbelement<myserviceresponse> createserviceresponse(myserviceresponse value) { return new jaxbelement<myserviceresponse>(_serviceresponse_qname, myserviceresponse.class, null, value); } }
you can set elementformdefault="qualified" model creating package-info.java , adding:
package-info.java
@xmlschema(namespace="http://www.example.com/type", elementformdefault=xmlnsform.qualified) package mypkg; import javax.xml.bind.annotation.*;
this allow regular xml, not "stripped" xml, work. difference between two, besides "stripping" of outer, wrapper elements, fact original xml has default namespace set, while stripped xml not.
Comments
Post a Comment