如果已删除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>
如果我移除肥皂信封会发生这种情况:
<ns:getNumberResponse>
<number>123456789</number>
</ns:getNumberResponse>
如果删除了soap信封,名称空间声明也将消失。 JAXB将无法解组上述xml,因为缺少前缀“ns”的命名空间定义。因此,它将返回"The prefix "ns" for element "ns:getNumberResponse" is not bound."
错误消息。我该如何解决?
请注意我使用的是JDK 1.5。我不确定在JDK 1.6中是否有办法解决这个问题。我能够使用JAXB,因为我下载了使用JAXB所需的jar。
答案 0 :(得分:36)
您可以使用StAX解析器来解析SOAP消息,然后将XMLStreamReader
推进到getNumberResponse
元素,并使用带有类参数的unmarshal方法。 Java SE 6中包含StAX解析器,但您需要为Java SE 5下载一个。Woodstox是一种流行的StAX解析器。
<强>响应强>
package forum11465653;
public class Response {
private long number;
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
}
<强>演示强>
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
答案 1 :(得分:17)
您可以使用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());
}
}
<强>输出强>
{http://example.com/}getNumberResponse
forum11465653.Response@19632847