簡體   English   中英

如何根據收到的 XML 解組到不同的對象?

[英]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 文件都可以有不同的名稱。

所以,我認為,我的網絡服務工作流程應該是這樣的:

  1. 它接收 XML 文件。
  2. 它檢查用戶ID。
    • 如果用戶 ID == 1234
      • UserA userA = 解組(XMLFile)
    • 否則如果用戶 ID == 5678
      • UserB userB = 解組(XMLFile)
    • 別的
      • UserC userC = 解組(XMLFile)

所以我收到不同的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM