3

XML ファイルを受信し、アンマーシャリングを行って XML ファイルをオブジェクトに変換する Web サービスがあります。問題は、Web サービスがさまざまな XML 構造を受け取る可能性があり、正しいアンマーシャリングを行う必要があることです。

だから私はこの種のXMLファイルを受け取ります:

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

XMLelementsこれはタグ名の例であることに注意してください。すべての XML ファイルには異なる名前を付けることができます。

したがって、私の Web サービス ワークフローは次のようになるはずです。

  1. XMLファイルを受け取ります。
  2. ユーザーIDをチェックします。
    • ユーザー ID == 1234 の場合
      • UserA userA = アンマーシャリング(XMLFile)
    • ユーザー ID == 5678 の場合
      • UserB userB = アンマーシャリング(XMLFile)
    • そうしないと
      • UserC userC = アンマーシャリング(XMLFile)

そのため、さまざまな XML 構造を受け取り、それぞれに対して異なるアンマーシャリングを実行して、異なるクラスのオブジェクトを取得する必要があります。

このアプローチを実行するにはどうすればよいですか? マーシャリングにSpringを使用しています(Metro)。

編集:この質問には回答がありませんでした。おそらく私は明確ではありません。私はそれをよりよく説明しようとします:

XML ファイルを受信する URL をリッスンする Web サービスがあります。実際、同じ URL パスで、私の Web サービスは 2 つの異なる XML スキーマを受け取ります。アンマーシャリングを正しく行う方法を知るにはどうすればよいですか? つまり、異なる XML スキーマが渡された場合、アンマーシャリングは正しいオブジェクトを返す必要があります。

4

1 に答える 1

3

このユース ケースをサポートするには、いくつかの方法があります。


オプション #1 - DOM アプローチ

常にDOMパーサーを使用してXMLを変換し、Documentそれに対してXPathを実行してid要素の値を取得し、結果に基づいてドキュメントを非整列化できます


オプション #2 - SAX アプローチ

LookAheadUnmarshallerHandler

SAX パーサーと JAXB のUnmarshallerHandlerメカニズムを利用して、次のことを行うことができます。

  • ContentHandler必要な情報が検出されるまで SAX イベントをキューに入れる を作成します。
  • JAXBContext要素の値に基づいて を作成/取得しますid
  • UnmarshallerHandlerから を作成しますJAXBContext
  • でキューに入れられたイベントを呼び出しますUnmarshallerHandler
  • を として設定しUnmarshallerHandlerます。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);
        }

    }

}

ジャバモデル

次のオブジェクト モデルは、質問で言及したクラスに基づいています。

ユーザー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
于 2012-11-21T11:46:34.830 に答える