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

Arc*_*rci 19 java xml soap jaxb unmarshalling

如果已删除soap信封,则JAXB只能解组XML.但是,我试图解组的SOAP响应在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>
Run Code Online (Sandbox Code Playgroud)

如果我移除肥皂信封会发生这种情况:

<ns:getNumberResponse>
    <number>123456789</number>
</ns:getNumberResponse>
Run Code Online (Sandbox Code Playgroud)

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

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

bdo*_*han 37

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

响应

package forum11465653;

public class Response {

    private long number;

    public long getNumber() {
        return number;
    }

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

}
Run Code Online (Sandbox Code Playgroud)

演示

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

}
Run Code Online (Sandbox Code Playgroud)

产量

http://example.com/
{http://example.com/}getNumberResponse
forum11465653.Response@781f6226
Run Code Online (Sandbox Code Playgroud)


Ian*_*rts 16

您可以使用DOM解析器解析整个SOAP消息,该解析器能够在解析时解析所有命名空间.然后从生成的DOM树中提取所需的元素,并将其传递给unmarshaller.

DomDemo

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

}
Run Code Online (Sandbox Code Playgroud)

产量

{http://example.com/}getNumberResponse
forum11465653.Response@19632847
Run Code Online (Sandbox Code Playgroud)

  • XML中的命名空间前缀是将正确的名称空间URI与正确的元素相关联的语法技巧.对JAXB unmarshaller这样的下游组件唯一重要的是命名空间URI和本地名称(冒号后面的位) - 一旦你有了一个DOM树,每个级别的所有元素都完全解析了它们的命名空间,并且前缀映射是不再相关. (2认同)