3

我有一个 Web 服务,它接收 XML 文件并进行解组以将 XML 文件转换为对象。问题是我的 Web 服务可以接收不同的 XML 结构并且必须进行正确的解组。

所以我收到了这种 XML 文件:

<root>
    <user>
        <id>1234</id>
    </user>
    <XMLelements>
        ...
    </XMLelements>
</root>

请注意,这XMLelements是一个示例标签名称,每个 XML 文件都可以有不同的名称。

所以,我认为,我的网络服务工作流程应该是这样的:

  1. 它接收 XML 文件。
  2. 它检查用户 ID。
    • 如果用户 ID == 1234
      • 用户 A 用户 A = 解组(XMLFile)
    • 否则,如果用户 ID == 5678
      • 用户 B 用户 B = 解组(XMLFile)
    • 别的
      • UserC userC = unmarshalling(XMLFile)

因此,我收到不同的 XML 结构,并且对于每个结构,我必须进行不同的解组以获取不同类的对象。

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

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

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

4

1 回答 1

3

有几种不同的方式来支持这个用例。


选项 #1 - DOM 方法

您始终可以使用 DOM 解析器将 XML 转换为Document对它执行 XPath 以获取id元素的值,然后根据结果解组文档


选项 #2 - SAX 方法

LookAheadUnmarshallerHandler

您可以利用 SAX 解析器和 JAXB 的UnmarshallerHandler机制并执行以下操作:

  • 创建一个ContentHandler将 SAX 事件排队,直到发现必要的信息。
  • JAXBContext根据id元素的值创建/检索 a 。
  • 从. UnmarshallerHandler_JAXBContext
  • 调用 上的排队事件UnmarshallerHandler
  • UnmarshallerHandleron设置XMLReaderContentHandler
  • 从 中检索未编组的对象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 {

}

输入(输入.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
于 2012-11-21T11:46:34.830 回答