在Soap响应中读取XML时名称空间错误(不为空)

时间:2019-02-04 12:08:41

标签: java xml soap jaxb xml-namespaces

我对SOAP服务有问题,该服务返回直接嵌入SOAP XML中的XML文档。 SOAP响应如下所示:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header />
    <soap:Body xmlns="WebserviceNamespace">
        <Result xmlns="WebserviceNamespace">
            <ActualXmlDocument DtdRelease="0" DtdVersion="4" xmlns="">
                ...
            </ActualXmlDocument>
        </Result>
    </soap:Body>
</soap:Envelope>

根据WSDL,<Result>的内容类型为

<s:element minOccurs="0" maxOccurs="1" name="Result">
    <s:complexType mixed="true">
        <s:sequence>
            <s:any />
        </s:sequence>
    </s:complexType>
</s:element>

对于<ActualXmlDocument>,我从提供的XSD文件中使用xjc生成了Java类。对于Web服务实现,我正在使用javax.jws/javax.jws-api/1.1javax.xml.ws/jaxws-api/2.3.1com.sun.xml.ws/rt/2.3.1。代表我从WS实现中检索到的<ActualXmlDocument>的对象类型是com.sun.org.apache.xerces.internal.dom.ElementNSImpl,它实现了org.w3c.dom.Node。尝试与JAXB解组

JAXBContext context = JAXBContext.newInstance(ActualXmlDocument.class);
context.createUnmarshaller().unmarshal((Node)result);

我收到以下异常

UnmarshalException:
    unexpected element (URI:"WebserviceNamespace", local:"ActualXmlDocument").
    Expected elements are <{}ActualXmlDocument>

因此由于某些原因,在读取XML文档时,空命名空间不会被当作新的默认命名空间,而是会被WebseriveNamespace覆盖,而该WebseriveNamespace会被错误地放置在那里。

那么我该如何解决此问题?我不想触摸XSD生成的文件只是为了适应这种明显错误的行为。另外,我无法控制Web服务的服务器端,因此无法更改其行为。我现在看到的唯一可能性是JAXB: How to ignore namespace during unmarshalling XML document?

还有其他方法来获取具有正确命名空间的节点吗?

1 个答案:

答案 0 :(得分:1)

JAXB: How to ignore namespace during unmarshalling XML document?的启发,我实现了一个解决方案,这不是最佳方法,因为它需要将DOM序列化为XML文档:

JAXBContext context = JAXBContext.newInstance(ActualXmlDocument.class);
Unmarshaller unmarshaller = context.createUnmarshaller();

SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(false);
XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader();

Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
OutputStreamout = new ByteArrayOutputStream();
StreamResult streamResult = new StreamResult(out);
transformer.transform(new DOMSource(result), streamResult);

InputStream in = new ByteArrayInputStream(out.toByteArray())
SAXSource source = new SAXSource(xmlReader, new InputSource(in));

unmarshaller.unmarshal(source);