我有一个Web服务,它接收XML文件并进行解组以将XML文件转换为对象。问题是我的Web服务可以接收不同的XML结构,并且必须进行正确的解组。
所以我收到了这种XML文件:
<root>
<user>
<id>1234</id>
</user>
<XMLelements>
...
</XMLelements>
</root>
请注意,XMLelements
是一个示例标记名称,每个XML文件都可以包含不同的名称。
所以,我认为,我的网络服务工作流程应该是这样的:
所以我收到了不同的XML结构,每个我必须做一个不同的解组来获取不同类的对象。
我该如何执行此方法?我正在使用Spring进行编组(Metro)。
编辑:这个问题没有得到任何答案,也许我不清楚。我会试着更好地解释一下:
我有一个正在侦听接收XML文件的URL的Web服务。实际上,在同一个url路径中,我的Web服务接收两个不同的XML模式。我怎么知道如何正确解组?我的意思是,当传递不同的XML模式时,解组应该返回正确的对象。
答案 0 :(得分:3)
有几种不同的方法可以支持这种用例。
选项#1 - DOM方法
您总是可以使用DOM解析器将XML转换为Document
对其执行XPath以获取id
元素的值,然后根据结果解组文档
选项#2 - SAX方法
的 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模型
以下对象模型基于您在问题中提到的类。
的用户A 强> 的
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserA {
}
的用户B 强> 的
package forum13397834;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="root")
public class UserB {
}
的用户C 强> 的
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>
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());
}
}
<强>输出强>
class forum13397834.UserA