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

时间:2012-11-15 12:48:20

标签: java xml web-services jaxb

我有一个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 = unmarshalling(XMLFile)
    • 否则,如果用户ID == 5678
      • UserB userB = unmarshalling(XMLFile)
    • 否则
      • UserC userC = unmarshalling(XMLFile)
  3. 所以我收到了不同的XML结构,每个我必须做一个不同的解组来获取不同类的对象。

    我该如何执行此方法?我正在使用Spring进行编组(Metro)。

    编辑:这个问题没有得到任何答案,也许我不清楚。我会试着更好地解释一下:

    我有一个正在侦听接收XML文件的URL的Web服务。实际上,在同一个url路径中,我的Web服务接收两个不同的XML模式。我怎么知道如何正确解组?我的意思是,当传递不同的XML模式时,解组应该返回正确的对象。

1 个答案:

答案 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