Как сделать демонтаж различных объектов в зависимости от полученного XML?
У меня есть веб-сервис, который получает файлы XML и выполняет демаршаллинг для преобразования файла XML в объект. Проблема заключается в том, что мой веб-сервис может получать различные XML-структуры и должен выполнять правильный демаршаллинг.
Итак, я получаю такие XML-файлы:
<root>
<user>
<id>1234</id>
</user>
<XMLelements>
...
</XMLelements>
</root>
Заметить, что XMLelements
является примером имени тега, каждый файл XML может иметь разные имена.
Так что, я думаю, мой рабочий процесс веб-службы должен выглядеть примерно так:
- Он получает файл XML.
- Проверяет идентификатор пользователя.
- Если идентификатор пользователя == 1234
- UserA userA = unmarshalling (XMLFile)
- Иначе, если идентификатор пользователя == 5678
- UserB userB = unmarshalling (XMLFile)
- еще
- UserC userC = unmarshalling(XMLFile)
- Если идентификатор пользователя == 1234
Поэтому я получаю разные XML-структуры, и для каждой из них мне приходится делать разные демаршаллинги для получения объектов разных классов.
Как я могу выполнить этот подход? Я использую Spring для сортировки (Metro).
Изменить: Этот вопрос не получил никакого ответа, может быть, я не ясно. Я постараюсь объяснить это лучше:
У меня есть веб-сервис, который прослушивает URL-адрес, где получает файлы XML. Фактически, по одному и тому же пути URL мой веб-сервис получает две разные XML-схемы. Как я могу узнать, как правильно выполнять демаршаллинг? Я имею в виду, unmarshalling должен возвращать правильный объект, когда передаются разные XML-схемы.
1 ответ
Есть несколько разных способов поддержки этого варианта использования.
ВАРИАНТ № 1 - DOM-подход
Вы всегда можете использовать DOM-парсер для преобразования XML в Document
выполнить XPath против него, чтобы получить значение id
элемент, а затем распаковать документ на основе результата
ВАРИАНТ № 2 - САКС Подход
LookAheadUnmarshallerHandler
Вы могли бы использовать парсер SAX и JAXB UnmarshallerHandler
механизм и сделать следующее:
- Создать
ContentHandler
это ставит в очередь события SAX, пока не будет обнаружена необходимая информация. - Создать / получить
JAXBContext
основанный на значенииid
элемент. - Создать
UnmarshallerHandler
отJAXBContext
, - Вызов событий в очереди на
UnmarshallerHandler
, - Установить
UnmarshallerHandler
наXMLReader
какContentHandler
, - Получите неупорядоченный объект из
UnmarshallerHandler
,
package forum13397834;
import java.util.*;
import javax.xml.bind.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
public class LookAheadUnmarshallerHandler extends DefaultHandler {
private XMLReader xmlReader;
private List<Event> events = new ArrayList<Event>();
private UnmarshallerHandler unmarshallerHandler;
public LookAheadUnmarshallerHandler(XMLReader xmlReader) {
this.xmlReader = xmlReader;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
events.add(new StartElement(uri, localName, qName, attributes));
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("id".equals(localName) || "id".equals(qName)) {
Characters characters = (Characters) events.get(events.size() - 1);
String value = characters.getString();
JAXBContext jc;
try {
if("1234".equals(value)) {
jc = JAXBContext.newInstance(Root1.class);
} else if("5678".equals(value)) {
jc = JAXBContext.newInstance(Root2.class);
} else {
jc = JAXBContext.newInstance(Root3.class);
}
unmarshallerHandler = jc.createUnmarshaller().getUnmarshallerHandler();
} catch(JAXBException e) {
throw new RuntimeException(e);
}
unmarshallerHandler.startDocument();
for(Event event : events) {
event.event(unmarshallerHandler);
}
unmarshallerHandler.endElement(uri, localName, qName);
xmlReader.setContentHandler(unmarshallerHandler);
} else {
events.add(new EndElement(uri, localName, qName));
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
events.add(new Characters(ch, start, length));
}
public Object getResult() throws JAXBException {
return unmarshallerHandler.getResult();
}
private static abstract class Event {
public abstract void event(ContentHandler contentHandler) throws SAXException;
}
private static class StartElement extends Event {
private String uri;
private String localName;
private String qName;
private Attributes attributes;
public StartElement(String uri, String localName, String qName, Attributes attributes) {
this.uri = uri;
this.localName = localName;
this.qName = qName;
this.attributes = attributes;
}
@Override
public void event(ContentHandler contentHandler) throws SAXException {
contentHandler.startElement(uri, localName, qName, attributes);
}
}
private static class Characters extends Event {
private char[] ch;
private int start;
private int length;
public Characters(char[] ch, int start, int length) {
this.ch = ch;
this.start = start;
this.length = length;
}
@Override
public void event(ContentHandler contentHandler) throws SAXException {
contentHandler.characters(ch, start, length);
}
public String getString() {
return new String(ch, start, length);
}
}
private static class EndElement extends Event {
private String uri;
private String localName;
private String qName;
public EndElement(String uri, String localName, String qName) {
this.uri = uri;
this.localName = localName;
this.qName = qName;
}
@Override
public void event(ContentHandler contentHandler) throws SAXException {
contentHandler.endElement(uri, localName, qName);
}
}
}
JAVA МОДЕЛЬ
Следующая объектная модель основана на классах, которые вы упоминаете в своем вопросе.
UserA
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserA {
}
UserB
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserB {
}
UserC
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserC {
}
INPUT (input.xml)
Мы будем использовать документ XML из вашего вопроса в качестве входных данных для этого примера.
<root>
<user>
<id>1234</id>
</user>
<XMLelements>
...
</XMLelements>
</root>
ДЕМО КОД
package forum13397834;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.*;
public class Demo {
public static void main(String[] args) throws Exception {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
XMLReader xmlReader = spf.newSAXParser().getXMLReader();
LookAheadUnmarshallerHandler handler = new LookAheadUnmarshallerHandler(xmlReader);
xmlReader.setContentHandler(handler);
xmlReader.parse(new InputSource("src/forum13397834/input.xml"));
Object object = handler.getResult();
System.out.println(object.getClass());
}
}
Выход
class forum13397834.UserA