如果名称空间声明位于SOAP信封上,如何使用JAXB解组SOAP响应?


问题内容

如果已删除肥皂信封,JAXB只能解组XML。但是,我要解组的SOAP响应在soap信封上有其名称空间声明。如果我删除肥皂信封,则名称空间声明也将被删除。因此,标签的前缀将不涉及任何前缀。这将导致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>

如果删除了肥皂信封,则名称空间声明也将消失。JAXB无法解组上述xml,因为缺少前缀“ ns”的名称空间定义。这样,它将返回"The prefix "ns" for element "ns:getNumberResponse" is not bound."错误消息。我如何解决它?

请注意,我正在使用JDK 1.5。我不确定JDK 1.6中是否有解决此问题的方法。我能够使用JAXB,因为我下载了使用JAXB所需的jar。


问题答案:

您可以使用StAX解析器来解析SOAP消息,然后将其前进XMLStreamReadergetNumberResponse元素,并使用带有类参数的unmarshal方法。Java
SE 6中包含一个StAX解析器,但是您需要为Java SE
5下载一个StAX解析器。Woodstox是流行的StAX解析器。

响应

package forum11465653;

public class Response {

    private long number;

    public long getNumber() {
        return number;
    }

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

}

演示版

An
XMLStreamReader有一个NamespaceContext。在NamespaceContext知道所有当前级别活动命名空间声明。您的JAXB(JSR-222)实现将能够利用它来获取必要的信息。

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());
    }

}

输出量

http://example.com/
{http://example.com/}getNumberResponse
forum11465653.Response@781f6226