Simple Framework Skip Soap Envelope And Body
Solution 1:
You can't use @Path
on @Root
-Element:
The Path annotation is used to specify an XML path where an XML element or attribute is located.
( Source )
Since you want nested data, from somewhere deep in the xml, there are two solutions:
- Map the whole XML structure
- Use a Converter that cut's mapping down to few classes and map just those
And here's what to do if you choose No. 2:
The Plan
- A
SOAPEnvelope
class builds just the root-element (<soap:Envelope>...</soap:Envelope>
) and holds the list of vehicles - A
SOAPEnvelopeConverter
implements aConverter
forSOAPEnvelope
- there the serialization is reduced to vehicles list only - A class
Vehicle
holds all the data of those elements (incl. a classPosition
for the<Position>...</Position>
elements) - A class
Vehicles
maps thevehicles
-tag only (= list of vehicle elements).
(Names have no convention)
The Implementation
I've written an implementation as a reference so you can see how my suggested solution works. Please add error checking etc. All data fields are handled as String
's here, replace their types with proper ones. Only the vehicles list is deserialized, all other values are ignored. Constructors, getter / setter etc. are only shown as they are required for this example.
The deserialized vehicles list is stored into the envelope's object. This is not the best way and used for example only. Please write a better implementation here (eg. introduce a class for the soap body where you can manage contents).
Note: Some classes are implemented as inner classes - this is optional, code as you prefer.
Class SOAPEnvelope
/ Class SOAPEnvelopeConverter
(inner)
@Root(name = "Envelope")@Namespace(prefix = "soap")// Set the converter that's used for serialization@Convert(value = SOAPEnvelope.SOAPEnvelopeConverter.class)publicclassSOAPEnvelope
{
// Keep the content of vehicles list hereprivate Vehicles vehicles;
public Vehicles getVehicles()
{
return vehicles;
}
protectedvoidsetVehicles(Vehicles vehicles)
{
this.vehicles = vehicles;
}
// The converter implementation for SOAPEnvelopepublicstaticclassSOAPEnvelopeConverterimplementsConverter<SOAPEnvelope>
{
@Overridepublic SOAPEnvelope read(InputNode node)throws Exception
{
SOAPEnvelopeenvelope=newSOAPEnvelope();
InputNodevehiclesNode= findVehiclesNode(node); // Search the Vehicles list elementif( vehiclesNode == null )
{
// This is bad - do something useful herethrownewException("No vehicles node!");
}
/*
* A default serializer is used to deserialize the full node. The
* returned object is set into the envelops's object, where you can
* get it through a get()-method.
*/Serializerser=newPersister();
envelope.setVehicles(ser.read(Vehicles.class, vehiclesNode));
return envelope;
}
@Overridepublicvoidwrite(OutputNode node, SOAPEnvelope value)throws Exception
{
// If you read (deserialize) only there's no need to implement thisthrownewUnsupportedOperationException("Not supported yet.");
}
private InputNode findVehiclesNode(InputNode rootNode)throws Exception
{
InputNodebody= rootNode.getNext("Body");
InputNodebuslocationResponse= body.getNext("BuslocationResponse");
InputNode next;
while( ( next = buslocationResponse.getNext() ) != null )
{
if( next.getName().equals("Vehicles") == true )
{
return next;
}
}
returnnull;
}
}
}
Class Vehicles
@Root(name = "Vehicles")publicclassVehicles
{
// Maps the list of vehicles@ElementList(name = "Vehicles", inline = true)private List<Vehicle> vehicles;
}
Class Vehicle
@Root(name = "Vehicle")publicclassVehicle
{
// All values are of type String - please replace with 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;
// A class to map the position elements@Root(name = "Position")public static classPosition
{
@Text()private String position;
}
}
How to use
finalStringxml= ...
Serializerser=newPersister(newAnnotationStrategy()); // Annotation strategy is set here!SOAPEnvelopesoapEnvelope= ser.read(SOAPEnvelope.class, newStringReader(xml));
Nothing special here - only AnnotationStrategy
is required! The source (2nd parameter of ser.read()
is set as your input comes. In this example, the soap xml comes from a string.
Solution 2:
the simple way is use @path , example i want get Route
from node Soap/Body/BuslocationResponse/Vehicles/Vehicle
Response.java
@Root(name = "soap:Envelope", strict = false)
public class Response {
@Element(name = "Route")
@Path("Body/BuslocationResponse/Vehicles/Vehicle")
private int route;
publicintgetRoute() {
returnroute;
}
}
Main.java
classMain {
publicstatic void main(String args[]) {
String xml ="<soap:Envelope \n"+"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"+"xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"+"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n"+"soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"+"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"+"<soap:Body>\n"+" <BuslocationResponse \n"+" xmlns=\"AT_WEB\">\n"+" <Version>1.0</Version>\n"+" <Responsecode>0</Responsecode>\n"+" <Input>\n"+" <Route>801</Route>\n"+" <Direction>N</Direction>\n"+" </Input>\n"+" <Vehicles>\n"+" <Vehicle>\n"+" <Route>801</Route>\n"+" <Direction>N</Direction>\n"+" <Updatetime>09:42 PM</Updatetime>\n"+" <Vehicleid>5007</Vehicleid>\n"+" <Block>801-06</Block>\n"+" <Adherance>-2</Adherance>\n"+" <Adhchange>S</Adhchange>\n"+" <Reliable>Y</Reliable>\n"+" <Offroute>N</Offroute>\n"+" <Stopped>N</Stopped>\n"+" <Inservice>Y</Inservice>\n"+" <Speed>20.61</Speed>\n"+" <Heading> 3</Heading>\n"+" <Routeid>44916</Routeid>\n"+" <Positions>\n"+" <Position>30.221222,-97.765007</Position>\n"+" <Position>30.218363,-97.766747</Position>\n"+" <Position>30.215282,-97.768715</Position>\n"+" <Position>30.212505,-97.770485</Position>\n"+" <Position>30.204943,-97.774765</Position>\n"+" <Position>30.204035,-97.775078</Position>\n"+" </Positions>\n"+" </Vehicle>\n"+" </Vehicles>\n"+"</BuslocationResponse>\n"+"</soap:Body>\n"+"</soap:Envelope>";
try {
Serializer serializer = new Persister();
Response r = serializer.read(Response.class, xml);
System.out.println("route: "+ r.getRoute());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Result:
/usr/lib/jvm/java-8-oracle/bin/java....
route:801
Process finished withexit code 0
Post a Comment for "Simple Framework Skip Soap Envelope And Body"