简体   繁体   English

如何根据收到的 XML 解组到不同的对象?

[英]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:所以,我认为,我的网络服务工作流程应该是这样的:

  1. It receives XML file.它接收 XML 文件。
  2. It checks user id.它检查用户ID。
    • If user id == 1234如果用户 ID == 1234
      • UserA userA = unmarshalling(XMLFile) UserA userA = 解组(XMLFile)
    • Else if user id == 5678否则如果用户 ID == 5678
      • UserB userB = unmarshalling(XMLFile) UserB userB = 解组(XMLFile)
    • Else别的
      • UserC userC = unmarshalling(XMLFile) UserC userC = 解组(XMLFile)

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机制并执行以下操作:

  • Create a ContentHandler that queues up SAX events until the necessary information is discovered.创建一个ContentHandler来对 SAX 事件进行排队,直到发现必要的信息。
  • Create/retrieve a JAXBContext based on the value of the id element.根据id元素的值创建/检索JAXBContext
  • Create an UnmarshallerHandler from the JAXBContext .JAXBContext创建一个UnmarshallerHandler
  • Call the queued events on the UnmarshallerHandler .UnmarshallerHandler上调用排队的事件。
  • Set the UnmarshallerHandler on the XMLReader as the ContentHandler .XMLReader上的UnmarshallerHandler设置为ContentHandler
  • Retrieve the unmarshalled object from the 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM