如何从SOAP请求中的body标签中删除xmlns:ns2?

时间:2017-10-02 11:57:26

标签: java xml namespaces jax-ws soap-client

我的SOAP请求生成为以下

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body xmlns:ns2="http://www.myserviceABC.com/application/ws/service">
      <ns2:getStatus>
         <pRef>123</pRef>
      </ns2:getStatus>
   </S:Body>
</S:Envelope>

我想从正文标记中删除 xmlns:ns2 =&#34; http://www.myserviceABC.com/application/ws/service" 并将其添加到 getStatus 标记中,如下所示

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns2:getStatus xmlns:ns2="http://www.myserviceABC.com/application/ws/service">
         <pRef>123</pRef>
      </ns2:getStatus>
   </S:Body>
</S:Envelope>

有人可以告诉我这样做吗?

如果我可以使用SOAPHandler

,那就更好了

1 个答案:

答案 0 :(得分:0)

您从WSDL生成的类应包含Service的子类。

使用自定义HandlerResolver调用Service.setHandlerResolver,该HandlerResolver返回一个改变消息正文的Handler:

    HandlerResolver originalResolver = myService.getHandlerResolver();

    myService.setHandlerResolver(new HandlerResolver() {
        @Override
        @SuppressWarnings({"rawtypes", "unchecked"})
        public List<Handler> getHandlerChain(PortInfo info) {
            Handler handler = new SOAPHandler<SOAPMessageContext>() {
                @Override
                public Set<QName> getHeaders() {
                    return Collections.emptySet();
                }

                @Override
                public boolean handleMessage(SOAPMessageContext context) {
                    SOAPMessage message = context.getMessage();

                    try {
                        if (moveNamespaceToDocument(message,
                            "http://www.myserviceABC.com/application/ws/service")) {

                            context.setMessage(message);
                        }
                    } catch (SOAPException e) {
                        throw new RuntimeException(e);
                    }

                    return true;
                }

                @Override
                public boolean handleFault(SOAPMessageContext context) {
                    return true;
                }

                @Override
                public void close(MessageContext context) {
                    // Deliberately empty
                }
            };

            List<Handler> handlers = new ArrayList<>(
                originalResolver.getHandlerChain(info));
            handlers.add(handler);
            return handlers;
        }
    });

// ...

private static boolean moveNamespaceToDocument(SOAPMessage message,
                                               String namespaceURI)
throws SOAPException {
    SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
    SOAPBody body = envelope.getBody();
    if (body.hasFault()) {
        return false;
    }

    Attr namespaceAttr = null;

    NamedNodeMap attributes = body.getAttributes();
    int count = attributes.getLength();
    for (int i = 0; i < count; i++) {
        Attr attr = (Attr) attributes.item(i);
        String name = attr.getName();
        if (name.startsWith("xmlns:") &&
            namespaceURI.equals(attr.getValue())) {

            namespaceAttr = attr;
            break;
        }
    }

    if (namespaceAttr == null) {
        return false;
    }

    NodeList children = body.getElementsByTagName("*");
    if (children.getLength() < 1) {
        return false;
    }
    Element root = (Element) children.item(0);

    body.removeAttributeNode(namespaceAttr);
    root.setAttributeNode(namespaceAttr);

    return true;
}

我可以验证moveNamespaceToDocument方法是否有效,但我没有一种简单的方法可以使用实际的服务来测试它,所以我不确定HandlerResolver。