Демаршалинг xml, где атрибуты определяют тип
Мне дают документы XML (которые я не могу контролировать его формат). Я хотел бы знать, возможно ли демаршалировать этот xml на основе идентификатора атрибута элемента. Таким образом, разные типы объектов будут иметь одинаковое имя элемента.
Кроме того, я планирую использовать Simpile XML, потому что я на Android, а JAXB не любит Android.
Поэтому я хотел бы что-то вроде:
class Root {
Person p;
Car c;
ArrayList<Person> plist;
}
class Person{
String name;
}
class Car {
String type;
}
от
<root>
<object id="person">
<name> bob </name>
</object>
<object id="car">
<model> ford </ford>
</object>
<sequence id="personSequence">
<object id="person">
<name> bob </name>
</object>
<object id="person">
<name> bob </name>
</object>
</sequence>
</root>
Однако я точно знаю, что документ, который я получаю, всегда будет в одном и том же порядке с одинаковым количеством элементов верхнего уровня. Например,
У Rool всегда будет: 1 человек, 1 машина, 1 человек, 2 машины и последовательность автомобилей неизвестного размера.
<root>
<person />
<car />
<person />
<car />
<car />
<sequence >
I don't know how many objects will be in here
<sequence >
<root>
Спасибо.
1 ответ
Вы можете использовать Converter
Выполнение этого. Это позволяет вам реализовать процесс (де) сериализации самостоятельно.
Вот предложение, как это сделать:
- Абстрактный класс как база для всех объектов (людей, автомобилей и т. Д.)
- Реализации для тех
- Корневой объект, содержащий все остальные элементы
-
Converter
который создает конкретный корень-объект из узлов
Btw. вам не нужно добавлять эти простые аннотации, если вы используете конвертеры - однако, это всегда хорошая идея, на тот случай, если они вам нужны.
(Аннотация) Базовый класс для всех объектов:
@Root()
public abstract class ObjectElement
{
@Attribute(name = "id")
private String id;
public ObjectElement(String id)
{
this.id = id;
}
// ...
}
Персональный класс:
@Root(name = "object")
public class PersonObject extends ObjectElement
{
@Element(name = "name")
private String name;
public PersonObject(String name)
{
super("person");
this.name = name;
}
// ...
}
Класс автомобиля:
@Root(name = "object")
public class CarObject extends ObjectElement
{
@Element(name = "model")
private String model;
public CarObject( String model)
{
super("car");
this.model = model;
}
// ...
}
Класс последовательности:
@Root(name = "sequence")
public class SequenceObject extends ObjectElement
{
@ElementList(inline = true)
private final List<ObjectElement> elements;
public SequenceObject()
{
super("personSequence");
this.elements = new ArrayList<>();
}
// ...
}
root
-элемент; у него есть экземпляры его детей (автомобили и т. д.) и карты <root> ... </root>
элемент.
@Root(name = "root")
@Convert(RootElementConverter.class) // Set Converter here!
public class RootElement
{
private final List<ObjectElement> elememts;
public RootElement()
{
this.elememts = new ArrayList<>();
}
public void add(ObjectElement element)
{
this.elememts.add(element);
}
// ...
}
Converter
:
public class RootElementConverter implements Converter<RootElement>
{
@Override
public RootElement read(InputNode node) throws Exception
{
RootElement root = new RootElement();
/*
* Iterate over all nodes and add them to root. You can use
* "node.getName()" and "node.getAttribute(...)" to test what
* instance you have to add.
*
* Use "root.add(...)" to add nodes.
*/
return root;
}
@Override
public void write(OutputNode node, RootElement value) throws Exception
{
/*
* Implement this if you also serialize to xml.
*/
throw new UnsupportedOperationException("Not supported yet.");
}
}
И напоследок как позвонить:
final String xml = ...
// Important: Don't forget the AnnotationStrategy!
Serializer ser = new Persister(new AnnotationStrategy());
// Read root-object from xml-string or whatever
RootElement root = ser.read(RootElement.class, xml);