簡體   English   中英

簡單的框架跳過肥皂信封和身體

[英]Simple framework skip soap envelope and body

我在Android中使用RetroFit和Simple XML Framework來模擬如下所示的SOAP響應:

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>

真的,我關心的只是車輛的集合。 似乎我只能模擬BusLocationResponse並通過聲明來跳過肥皂信封和身體

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;

}

這只會產生錯誤:

org.simpleframework.xml.core.ValueRequiredException: Unable to satisfy
@org.simpleframework.xml.Element(data=false, name=Responsecode, required=true,
type=void) on field 'responseCode' 

我在這里誤解了什么?

你不能在@Root上使用@Path

Path注釋用於指定XML元素或屬性所在的XML路徑。

來源

由於您需要嵌套數據,從xml深處的某個位置,有兩種解決方案:

  1. 映射整個XML結構
  2. 使用轉換器將映射縮減到幾個類並僅映射那些

如果你選擇2號,這是怎么做的:

計划

  • SOAPEnvelope類只構建元素( <soap:Envelope>...</soap:Envelope> )並保存車輛列表
  • SOAPEnvelopeConverter實現了一個用於SOAPEnvelopeConverter - 序列化僅限於車輛列表
  • Vehicle包含這些元素的所有數據(包括<Position>...</Position>元素的類Position
  • 一類Vehicles僅映射vehicles標簽(=車輛元素列表)。

(名稱沒有約定)

實施

我已經編寫了一個實現作為參考,因此您可以看到我的建議解決方案是如何工作的。 請添加錯誤檢查等。所有數據字段在此處作為String處理,用正確的類型替換它們的類型。 僅對車輛列表進行反序列化,忽略所有其他值。 構造函數,getter / setter等僅顯示為此示例所需的構造函數。

反序列化的車輛列表存儲在信封的對象中。 這不是最好的方法,僅用於舉例。 請在這里寫一個更好的實現(例如,為肥皂體引入一個類,您可以在其中管理內容)。

注意:有些類是作為內部類實現的 - 這是可選的代碼,如您所願。

SOAPEnvelope /類SOAPEnvelopeConverter (內部)

@Root(name = "Envelope")
@Namespace(prefix = "soap")
// Set the converter that's used for serialization
@Convert(value = SOAPEnvelope.SOAPEnvelopeConverter.class)
public class SOAPEnvelope
{
    // Keep the content of vehicles list here
    private Vehicles vehicles;


    public Vehicles getVehicles()
    {
        return vehicles;
    }

    protected void setVehicles(Vehicles vehicles)
    {
        this.vehicles = vehicles;
    }



    // The converter implementation for 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 the Vehicles list element

            if( vehiclesNode == null )
            {
                // This is bad - do something useful here
                throw new Exception("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.
             */
            Serializer ser = new Persister();
            envelope.setVehicles(ser.read(Vehicles.class, vehiclesNode));

            return envelope;
        }


        @Override
        public void write(OutputNode node, SOAPEnvelope value) throws Exception
        {
            // If you read (deserialize) only there's no need to implement this
            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;
        }
    }
}

Vehicles

@Root(name = "Vehicles")
public class Vehicles
{
    // Maps the list of vehicles
    @ElementList(name = "Vehicles", inline = true)
    private List<Vehicle> vehicles;
}

Vehicle

@Root(name = "Vehicle")
public class Vehicle
{
    // 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 class Position
    {
        @Text()
        private String position;
    }
}

如何使用

final String xml = ...
Serializer ser = new Persister(new AnnotationStrategy()); // Annotation strategy is set here!

SOAPEnvelope soapEnvelope = ser.read(SOAPEnvelope.class, new StringReader(xml));

這里沒什么特別的 - 只需要 AnnotationStrategy 源( ser.read()第二個參數設置為您的輸入。在此示例中,soap xml來自字符串。

簡單的方法是使用@path,例子我想從節點Soap/Body/BuslocationResponse/Vehicles/Vehicle獲取Route

Response.java

@Root(name = "soap:Envelope", strict = false)
public class Response {
   @Element(name = "Route")
   @Path("Body/BuslocationResponse/Vehicles/Vehicle")
   private int route;

   public int getRoute() {
    return route;
   }
}

Main.java

class Main {
public static 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();
    }
}
} 

結果:

/usr/lib/jvm/java-8-oracle/bin/java....
route: 801
Process finished with exit code 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM