Вы не можете использовать @Path
на @Root
-элементе:
Аннотация Path используется для указания пути XML, в котором находится XML-элемент или атрибут.
( Источник )
Поскольку вам нужны вложенные данные откуда-то глубоко в xml, есть два решения:
- Сопоставьте всю структуру XML
- Используйте преобразователь это сопоставление сокращений до нескольких классов и сопоставление только тех
И вот что делать, если вы выберете № 2:
План
- Класс
SOAPEnvelope
создает только корневой-элемент (<soap:Envelope>...</soap:Envelope>
) и содержит список транспортных средств.
SOAPEnvelopeConverter
реализует Converter
для SOAPEnvelope
- там сериализация сводится только к списку транспортных средств
- Класс
Vehicle
содержит все данные этих элементов (включая класс Position
для <Position>...</Position>
элементов).
- Класс
Vehicles
сопоставляет только тег vehicles
(= список элементов транспортного средства).
(Имена не имеют соглашения)
Реализация
Я написал реализацию в качестве эталона, чтобы вы могли увидеть, как работает предложенное мной решение. Пожалуйста, добавьте проверку ошибок и т. д. Все поля данных здесь обрабатываются как String
, замените их типы на правильные. Только десериализуется список транспортных средств, все остальные значения игнорируются. Конструкторы, геттеры/сеттеры и т. д. показаны только в том случае, если они необходимы для этого примера.
Список десериализованных транспортных средств хранится в объекте конверта. Это не лучший способ и используется только для примера. Пожалуйста, напишите здесь лучшую реализацию (например, введите класс для тела мыла, где вы можете управлять содержимым).
Примечание. Некоторые классы реализованы как внутренние классы — это необязательно, используйте код по своему усмотрению.
Класс 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
! Источник (2-й параметр ser.read()
устанавливается по мере поступления вашего ввода. В этом примере мыло xml происходит из строки.
person
ollo
schedule
14.06.2014