У меня наверняка есть проблема понимания конвертера Xstream.
У меня довольно сложный XML, исходящий из старого приложения back office, и просто хочу преобразовать его в более простой класс Java или карту с конвертером.
Мой XML похож на
<root>
<agent>
<id>123456789</id>
<name>GABIN</name>
<forname>Jean</forname>
<unit>
<legacyReference>AA</legacyReference>
<name>SAN ANTONIO</name>
<legacyName>SA</legacyName>
<address>
<number>1</number>
<street>Sesam street</street>
<city>NoWhere</city>
<legacyID>AAZE-56</legacyID>
</address>
<legacyStructurBlablabla>
<type>OFFICE</type>
<data>
<foo>BAR</foo>
</data>
</legacyStructurBlablabla>
<...>
</unit>
<...>
</agent>
</root>
Мой целевой класс очень прост
class Agent {
String id;
String name;
String forname;
String unitName;
String unitType;
<...>
}
Мой основной метод выглядит
xStream = new XStream(new DomDriver());
stream = this.getClass().getClassLoader().getResourceAsStream("data/agent.xml") ;
xStream.alias("root", Map.class);
xStream.alias("agent", Agent.class);
xStream.registerConverter(new ResultConverter());
xStream.registerConverter(new AgentConverter());
xStream.ignoreUnknownElements();
Object obj = xStream.fromXML(stream);
Я не понимаю, как уйти в пользу другого конвертера.
public class ResultConverter implements Converter {
...
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
Map<String, Object> agents = new HashMap<String, Object>();
while( reader.hasMoreChildren() ) {
reader.moveDown();
// HOW I DO TO STEP DOWN IN FAVOR OF Agent CONVERTER ?
reader.moveUp();
}
return agents;
}
Я не видел, чтобы Xstream прокручивал иерархию для активации моего AgentConverter.
Я, конечно, пропуская точку
РЕДАКТИРОВАТЬ
Для этого Xstream может быть не лучшим инструментом. Я бы использовал xmlbeam, согласно совету Cfx. XMLBeam проектирует XML в Java-классе в соответствии с отображением XPATH.
Кажется, вы хотите, чтобы структура xml не отражалась в вашем классе Java. Если вы придерживаетесь XStream, у меня нет решения. Но есть альтернативная схема, которая была создана для решения именно этой проблемы. Он использует аннотации, но IMHO не нарушает принцип KISS. Вот пример:
public interface Agent {
@XBRead("/root/agent/id")
String getId();
@XBRead("/root/agent/name")
String getName();
@XBRead("/root/agent/forename")
String getForname();
@XBRead("/root/agent/unit/name")
String getUnitName();
@XBRead("/root/agent/unit/legacyStructurBlablabla/type")
String getUnitType();
}
Вы определяете интерфейсы вместо классов, но экземпляры этих интерфейсов можно использовать так же, как POJO. (с toString(), equals(), hashCode,...). Создание экземпляров этих интерфейсов выглядит так:
Agent agent = new XBProjector().io().stream(stream).read(Agent.class);