[英]How do unmarshalling to different objects depending on the XML received?
我有一個 Web 服務,它接收 XML 文件並進行解組以將 XML 文件轉換為對象。 問題是我的 Web 服務可以接收不同的 XML 結構並且必須進行正確的解組。
所以我收到這種 XML 文件:
<root>
<user>
<id>1234</id>
</user>
<XMLelements>
...
</XMLelements>
</root>
請注意, XMLelements
是一個示例標簽名稱,每個 XML 文件都可以有不同的名稱。
所以,我認為,我的網絡服務工作流程應該是這樣的:
所以我收到不同的 XML 結構,對於每個結構,我必須進行不同的解組以獲取不同類的對象。
我該如何執行這種方法? 我正在使用 Spring 進行編組(Metro)。
編輯:這個問題沒有得到任何答案,也許我不清楚。 我會試着更好地解釋它:
我有一個 Web 服務,它正在偵聽接收 XML 文件的 url。 實際上,在同一個 url 路徑中,我的 Web 服務收到兩個不同的 XML 模式。 我怎么知道如何正確解組? 我的意思是,當傳遞不同的 XML 模式時,解組應該返回正確的對象。
有幾種不同的方法來支持這個用例。
選項 #1 - DOM 方法
您始終可以使用 DOM 解析器將 XML 轉換為Document
對其執行 XPath 以獲取id
元素的值,然后根據結果解組文檔
選項 #2 - SAX 方法
LookAheadUnmarshallerHandler
您可以利用 SAX 解析器和 JAXB 的UnmarshallerHandler
機制並執行以下操作:
ContentHandler
來對 SAX 事件進行排隊,直到發現必要的信息。id
元素的值創建/檢索JAXBContext
。JAXBContext
創建一個UnmarshallerHandler
。UnmarshallerHandler
上調用排隊的事件。XMLReader
上的UnmarshallerHandler
設置為ContentHandler
。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);
}
}
}
爪哇模型
以下對象模型基於您在問題中提到的類。
用戶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.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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.