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

Set*_*eth 5 java android simple-framework retrofit

我正在使用Android中的RetroFitSimple XMLFramework来模拟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>
Run Code Online (Sandbox Code Playgroud)

真的,我关心的只是车辆的集合.似乎我只能模拟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;

}
Run Code Online (Sandbox Code Playgroud)

这只会产生错误:

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

我在这里误解了什么?

oll*_*llo 5

你不能@Path在@Root-Element上使用:

Path注释用于指定XML元素或属性所在的XML路径.

(来源)

由于您需要嵌套数据,从xml深处的某个位置,有两种解决方案:

  1. 映射整个XML结构
  2. 使用转换器将映射缩减到几个类并仅映射那些

如果你选择2号,这是怎么做的:

计划

  • 一个SOAPEnvelope类只构建root -element(<soap:Envelope>...</soap:Envelope>)并保存车辆列表
  • 一个SOAPEnvelopeConverter实现了Converter的SOAPEnvelope-有序列化是减少到只有车辆列表
  • 一类Vehicle保持这些元件的所有数据(包括一个类Position的<Position>...</Position>元素)
  • 类仅Vehicles映射vehicles-tag(=车辆元素列表).

(名称没有约定)

实施

我已经编写了一个实现作为参考,因此您可以看到我的建议解决方案是如何工作的.请添加错误检查等.所有数据字段都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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

类 Vehicles

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

类 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如何使用

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

SOAPEnvelope soapEnvelope = ser.read(SOAPEnvelope.class, new StringReader(xml));
Run Code Online (Sandbox Code Playgroud)

这里没有什么特别-仅AnnotationStrategy被要求!源(第二个参数ser.read()设置为您的输入.在此示例中,soap xml来自一个字符串.