java - Simple framework skip soap envelope and body -
i'm using retrofit
, simple xml
framework in android model soap
response looks this:
xml:
<soap:envelope xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/xmlschema" soap:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:body> <buslocationresponse xmlns="at_web"> <version>1.0</version> <responsecode>0</responsecode> <input> <route>801</route> <direction>n</direction> </input> <vehicles> <vehicle> <route>801</route> <direction>n</direction> <updatetime>09:42 pm</updatetime> <vehicleid>5007</vehicleid> <block>801-06</block> <adherance>-2</adherance> <adhchange>s</adhchange> <reliable>y</reliable> <offroute>n</offroute> <stopped>n</stopped> <inservice>y</inservice> <speed>20.61</speed> <heading> 3</heading> <routeid>44916</routeid> <positions> <position>30.221222,-97.765007</position> <position>30.218363,-97.766747</position> <position>30.215282,-97.768715</position> <position>30.212505,-97.770485</position> <position>30.204943,-97.774765</position> <position>30.204035,-97.775078</position> </positions> </vehicle> </vehicles> </buslocationresponse> </soap:body> </soap:envelope>
really, care collection of vehicles. seems model buslocationresponse , skip soap envelope , body declaring
java:
@root(strict=false) @path("envelope/body/buslocationresponse") public class buslocationresponse { @element(name="responsecode") public int responsecode; @elementlist @path("envelope/body/buslocationresponse/vehicles") public list<capvehicle> vehicles; }
this yields error:
org.simpleframework.xml.core.valuerequiredexception: unable satisfy @org.simpleframework.xml.element(data=false, name=responsecode, required=true, type=void) on field 'responsecode'
what misunderstanding here?
you can't use @path
on @root
-element:
the path annotation used specify xml path xml element or attribute located.
( source )
since want nested data, somewhere deep in xml, there 2 solutions:
- map whole xml structure
- use converter cut's mapping down few classes , map those
and here's if choose no. 2:
the plan
- a
soapenvelope
class builds root-element (<soap:envelope>...</soap:envelope>
) , holds list of vehicles - a
soapenvelopeconverter
implementsconverter
soapenvelope
- there serialization reduced vehicles list only - a class
vehicle
holds data of elements (incl. classposition
<position>...</position>
elements) - a class
vehicles
mapsvehicles
-tag (= list of vehicle elements).
(names have no convention)
the implementation
i've written implementation reference can see how suggested solution works. please add error checking etc. data fields handled string
's here, replace types proper ones. only vehicles list deserialized, other values ignored. constructors, getter / setter etc. shown required example.
the deserialized vehicles list stored envelope's object. not best way , used example only. please write better implementation here (eg. introduce class soap body can manage contents).
note: classes implemented inner classes - optional, code prefer.
class soapenvelope
/ class soapenvelopeconverter
(inner)
@root(name = "envelope") @namespace(prefix = "soap") // set converter that's used serialization @convert(value = soapenvelope.soapenvelopeconverter.class) public class soapenvelope { // keep content of vehicles list here private vehicles vehicles; public vehicles getvehicles() { return vehicles; } protected void setvehicles(vehicles vehicles) { this.vehicles = vehicles; } // converter implementation soapenvelope public static class soapenvelopeconverter implements converter<soapenvelope> { @override public soapenvelope read(inputnode node) throws exception { soapenvelope envelope = new soapenvelope(); inputnode vehiclesnode = findvehiclesnode(node); // search vehicles list element if( vehiclesnode == null ) { // bad - useful here throw new exception("no vehicles node!"); } /* * default serializer used deserialize full node. * returned object set envelops's object, can * through get()-method. */ serializer ser = new persister(); envelope.setvehicles(ser.read(vehicles.class, vehiclesnode)); return envelope; } @override public void write(outputnode node, soapenvelope value) throws exception { // if read (deserialize) there's no need implement throw new unsupportedoperationexception("not supported yet."); } private inputnode findvehiclesnode(inputnode rootnode) throws exception { inputnode body = rootnode.getnext("body"); inputnode buslocationresponse = body.getnext("buslocationresponse"); inputnode next; while( ( next = buslocationresponse.getnext() ) != null ) { if( next.getname().equals("vehicles") == true ) { return next; } } return null; } } }
class vehicles
@root(name = "vehicles") public class vehicles { // maps list of vehicles @elementlist(name = "vehicles", inline = true) private list<vehicle> vehicles; }
class vehicle
@root(name = "vehicle") public class vehicle { // values of type string - please replace proper types @element(name = "route") private string route; @element(name = "direction") private string direction; @element(name = "updatetime") private string updatetime; @element(name = "vehicleid") private string vehicleid; @element(name = "block") private string block; @element(name = "adherance") private string adherance; @element(name = "adhchange") private string adhchange; @element(name = "reliable") private string reliable; @element(name = "offroute") private string offroute; @element(name = "stopped") private string stopped; @element(name = "inservice") private string inservice; @element(name = "speed") private string speed; @element(name = "heading") private string heading; @element(name = "routeid") private string routeid; @elementlist(name = "positions") private list<position> postions; // class map position elements @root(name = "position") public static class position { @text() private string position; } }
how use
final string xml = ... serializer ser = new persister(new annotationstrategy()); // annotation strategy set here! soapenvelope soapenvelope = ser.read(soapenvelope.class, new stringreader(xml));
nothing special here - annotationstrategy
required! source (2nd parameter of ser.read()
set input comes. in example, soap xml comes string.
Comments
Post a Comment