21

SOAP エンベロープがすでに削除されている場合にのみ、JAXB は XML を非整列化できます。ただし、アンマーシャリングしようとしている SOAP 応答には、soap エンベロープに名前空間宣言があります。soap エンベロープを削除すると、名前空間宣言も削除されます。そのため、タグのプレフィックスは none を参照します。これにより、JAXB はエラーをスローします。名前空間が SOAP エンベロープで宣言されている場合、JAXB を使用して SOAP 応答を非整列化するにはどうすればよいですか?

非整列化する必要がある XML の同様のサンプルを以下に示します。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com/">
    <soapenv:Body>
        <ns:getNumberResponse>
            <number>123456789</number>
        </ns:getNumberResponse>
    </soapenv:Body>
</soapenv:Envelope>

石鹸の封筒を外すとこうなります。

<ns:getNumberResponse>
    <number>123456789</number>
</ns:getNumberResponse>

soap エンベロープを削除すると、名前空間宣言も削除されます。プレフィックス「ns」の名前空間定義が欠落しているため、JAXB は上記の xml を非整列化できません。そのため、"The prefix "ns" for element "ns:getNumberResponse" is not bound."エラー メッセージが返されます。どうすれば修正できますか?

JDK 1.5 を使用していることに注意してください。JDK 1.6 でこれを解決する方法があるかどうかはわかりません。JAXB を使用するために必要な jar をダウンロードしたので、JAXB を使用することができました。

4

2 に答える 2

42

You can use a StAX parser to parse the SOAP message and then advance the XMLStreamReader to the getNumberResponse element and use the unmarshal method that takes a class parameter. A StAX parser is included in Java SE 6, but you will need to download one for Java SE 5. Woodstox is a popular StAX parser.

Response

package forum11465653;

public class Response {

    private long number;

    public long getNumber() {
        return number;
    }

    public void setNumber(long number) {
        this.number = number;
    }

}

Demo

An XMLStreamReader has a NamespaceContext. The NamespaceContext knows all the active namespace declarations for the current level. Your JAXB (JSR-222) implementation will be able to leverage this to get the necessary information.

package forum11465653;

import java.io.FileReader;
import javax.xml.bind.*;
import javax.xml.stream.*;

public class Demo {

    public static void main(String[] args) throws Exception{
        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("src/forum11465653/input.xml"));
        xsr.nextTag(); // Advance to Envelope tag
        xsr.nextTag(); // Advance to Body tag
        xsr.nextTag(); // Advance to getNumberResponse tag
        System.out.println(xsr.getNamespaceContext().getNamespaceURI("ns"));

        JAXBContext jc = JAXBContext.newInstance(Response.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        JAXBElement<Response> je = unmarshaller.unmarshal(xsr, Response.class);
        System.out.println(je.getName());
        System.out.println(je.getValue());
    }

}

Output

http://example.com/
{http://example.com/}getNumberResponse
forum11465653.Response@781f6226
于 2012-07-13T09:11:06.320 に答える
16

解析時にすべての名前空間を解決できる DOM パーサーを使用して、SOAP メッセージ全体を解析できます。次に、結果の DOM ツリーから必要な要素を抽出し、それをアンマーシャラーに渡します。

ドムデモ

package forum11465653;

import java.io.File;
import javax.xml.bind.*;
import javax.xml.parsers.*;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.*;

public class DomDemo {

    public static void main(String[] args) throws Exception{
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document d = db.parse(new File("src/forum11465653/input.xml"));
        Node getNumberResponseElt = d.getElementsByTagNameNS("http://example.com/", "getNumberResponse").item(0);

        JAXBContext jc = JAXBContext.newInstance(Response.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        JAXBElement<Response> je = unmarshaller.unmarshal(new DOMSource(getNumberResponseElt), Response.class);
        System.out.println(je.getName());
        System.out.println(je.getValue());
    }

}

出力

{http://example.com/}getNumberResponse
forum11465653.Response@19632847
于 2012-07-13T08:43:43.017 に答える