简单的框架跳过肥皂信封和身体

时间:2014-06-08 03:30:14

标签: java android simple-framework retrofit

我在Android中使用RetroFit和简单XML框架来模拟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并跳过肥皂信封和身体

爪哇:

@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' 

我在这里误解了什么?

2 个答案:

答案 0 :(得分:5)

您无法在@Path上使用@Root - 元素:

  

Path annotation用于指定XML元素或属性所在的XML路径。

Source

由于您希望嵌套数据来自xml深处,因此有两种解决方案:

  1. 映射整个XML结构
  2. 使用Converter剪切到几个类的映射并仅映射那些
  3. 如果您选择第2号,该怎么办:

    计划

    • SOAPEnvelope 类只构建 root -element(<soap:Envelope>...</soap:Envelope>)并保存车辆列表
    • SOAPEnvelopeConverter Converter实施SOAPEnvelope - 序列化仅限于车辆列表
    • 一个 Vehicle 类包含这些元素的所有数据(包括Position 的{strong> <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来自一个字符串。

答案 1 :(得分:2)

简单的方法是使用@path,例如我想从节点($a) ? $b : $c;获取Route

Response.java

Soap/Body/BuslocationResponse/Vehicles/Vehicle

Main.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;
   }
}

结果:

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();
    }
}
}