[英]How do unmarshalling to different objects depending on the XML received?
I have a web service which receives XML files and does unmarshalling to convert the XML file to an object.我有一个 Web 服务,它接收 XML 文件并进行解组以将 XML 文件转换为对象。 The problem is that my web service can receive different XML structures and has to do the correct unmarshalling.
问题是我的 Web 服务可以接收不同的 XML 结构并且必须进行正确的解组。
So I receibe this kind of XML files:所以我收到这种 XML 文件:
<root>
<user>
<id>1234</id>
</user>
<XMLelements>
...
</XMLelements>
</root>
Notice that XMLelements
is an example tag name, every XML file could have differents names.请注意,
XMLelements
是一个示例标签名称,每个 XML 文件都可以有不同的名称。
So, I think, my web service workflow should be something like:所以,我认为,我的网络服务工作流程应该是这样的:
So I receive different XML structures and for each one I have to do a different unmarshalling to get objects of different classes.所以我收到不同的 XML 结构,对于每个结构,我必须进行不同的解组以获取不同类的对象。
How can I perform this approach?我该如何执行这种方法? I'm using Spring for marshalling (Metro).
我正在使用 Spring 进行编组(Metro)。
Edit: This question didn't receive any answer, maybe I'm not clear.编辑:这个问题没有得到任何答案,也许我不清楚。 I'll try to explain it better:
我会试着更好地解释它:
I have a web service which is listening a url where receives XML files.我有一个 Web 服务,它正在侦听接收 XML 文件的 url。 Actually, in the same url path my web service receives two different XML schemas.
实际上,在同一个 url 路径中,我的 Web 服务收到两个不同的 XML 模式。 How can I know how to do unmarshalling correctly?
我怎么知道如何正确解组? I mean, unmarshalling should return correct object when different XML schemas are passed.
我的意思是,当传递不同的 XML 模式时,解组应该返回正确的对象。
There are a couple of different ways to support this use case.有几种不同的方法来支持这个用例。
OPTION #1 - DOM Approach选项 #1 - DOM 方法
You could always use a DOM parser to convert the XML to a Document
perform an XPath against it to get the value of the id
element and then unmarshal the document based on the result您始终可以使用 DOM 解析器将 XML 转换为
Document
对其执行 XPath 以获取id
元素的值,然后根据结果解组文档
OPTION #2 - SAX Approach选项 #2 - SAX 方法
LookAheadUnmarshallerHandler LookAheadUnmarshallerHandler
You could leverage a SAX parser and JAXB's UnmarshallerHandler
mechanism and do the following:您可以利用 SAX 解析器和 JAXB 的
UnmarshallerHandler
机制并执行以下操作:
ContentHandler
that queues up SAX events until the necessary information is discovered.ContentHandler
来对 SAX 事件进行排队,直到发现必要的信息。JAXBContext
based on the value of the id
element.id
元素的值创建/检索JAXBContext
。UnmarshallerHandler
from the JAXBContext
.JAXBContext
创建一个UnmarshallerHandler
。UnmarshallerHandler
.UnmarshallerHandler
上调用排队的事件。UnmarshallerHandler
on the XMLReader
as the ContentHandler
.XMLReader
上的UnmarshallerHandler
设置为ContentHandler
。UnmarshallerHandler
.UnmarshallerHandler
检索解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 MODEL爪哇模型
The following object model is based on the classes you mention in your question.以下对象模型基于您在问题中提到的类。
UserA用户A
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserA {
}
UserB用户B
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserB {
}
UserC用户C
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserC {
}
INPUT (input.xml)输入 (input.xml)
We will use the XML document from your question as the input for this example.我们将使用您问题中的 XML 文档作为此示例的输入。
<root>
<user>
<id>1234</id>
</user>
<XMLelements>
...
</XMLelements>
</root>
DEMO CODE演示代码
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());
}
}
Output输出
class forum13397834.UserA
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.