java - SOAPHandler:如何从子元素中删除自动添加的命名空间/属性

标签 java soap namespaces soaphandler

我正在尝试设置一个 SOAPHandler在我的服务器上转换此传入请求

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <getMachine xmlns="http://machine.soap.webservices.product.company.at/">
            <machineId>92623-15853588</machineId>
        </getMachine>
    </S:Body>
</S:Envelope>

对这个要求。
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <enns1:getMachine xmlns:enns1="http://machine.soap.webservices.product.company.at/">
            <machineId>92623-15853588</machineId>
        </enns1:getMachine>
    </S:Body>
</S:Envelope>

我的 SOAPHandler 看起来像这样。
package at.company.product.webservices.soap;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPValidationHandler implements SOAPHandler<SOAPMessageContext> {

    private static final String PREFIX = "enns1";

    @Override
    public boolean handleMessage(SOAPMessageContext context) {

        System.out.println("Server : handleMessage()......");

        Boolean isRequest = (Boolean) context
                .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        // inbound
        if (!isRequest) {

            try {
                SOAPMessage soapMsg = context.getMessage();

                SOAPBody body = soapMsg.getSOAPBody();
                Iterator<SOAPElement> it = body.getChildElements();

                // Look for all body elements who have a "xmlns" attribute and
                // add a namespace prefix to it
                while (it.hasNext()) {

                    SOAPElement elem = it.next();
                    addNamespacePrefix(elem);

                    Iterator itChildren = elem.getChildElements();

                    while (itChildren.hasNext()) {
                        Object child = itChildren.next();

                        if (child instanceof SOAPElement) {
                            SOAPElement cElem = ((SOAPElement) child);

                            // TODO: Remove the namespace from the child
                            // cElem.removeNamespaceDeclaration(""); => Does not
                            // work
                        }
                    }

                }

                // tracking
                soapMsg.writeTo(System.out);

            } catch (SOAPException e) {
                System.err.println(e);
            } catch (IOException e) {
                System.err.println(e);
            }
        }

        return true;
    }

    private void addNamespacePrefix(SOAPElement elem) throws SOAPException {
        Iterator<Object> it = elem.getAllAttributes();

        QName name = new QName("xmlns");
        String value = elem.getAttributeValue(name);

        if (value != null) {
            elem.addNamespaceDeclaration(PREFIX, elem.getNamespaceURI());
            elem.removeNamespaceDeclaration("");
            elem.setPrefix(PREFIX);
        }

    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        System.out.println("Server : handleFault()......");
        return true;
    }

    @Override
    public void close(MessageContext context) {
        System.out.println("Server : close()......");
    }

    @Override
    public Set<QName> getHeaders() {
        System.out.println("Server : getHeaders()......");
        return null;
    }

}

使用 SOAPHandler 处理请求后,请求如下所示:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <enns1:getMachine xmlns:enns1="http://machine.soap.webservices.product.company.at/">
             <machineId xmlns="http://machine.soap.webservices.product.company.at/">92623-15853588</machineId>
        </enns1:getMachine>
    </S:Body>
</S:Envelope>

如您所见,我可以将 namespace 前缀添加到 <getMachine>标签,但随后它会自动添加 xmlns子元素的属性 <machineId> .我怎样才能避免或解决这个问题?

最佳答案

在玩弄 API 之后,我想出了这个解决方案。这解决了所描述的情况。

package at.company.product.webservices.soap;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;

public class SOAPValidationHandler implements SOAPHandler<SOAPMessageContext> {

    private static final String PREFIX = "enns1";

    @Override
    public boolean handleMessage(SOAPMessageContext context) {


        Boolean isRequest = (Boolean) context
                .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        // for response message only, true for outbound messages, false for
        // inbound
        if (!isRequest) {

            try {
                SOAPMessage soapMsg = context.getMessage();
                SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
                SOAPHeader soapHeader = soapEnv.getHeader();

                // if no header, add one
                if (soapHeader == null) {
                    soapHeader = soapEnv.addHeader();
                    // throw exception
                    generateSOAPErrMessage(soapMsg, "No SOAP header.");
                }

                SOAPBody body = soapMsg.getSOAPBody();
                Iterator<SOAPElement> it = body.getChildElements();

                while (it.hasNext()) {
                    SOAPElement elem = it.next();
                    addNamespacePrefix(elem);


                    Iterator itChildChildren = elem.getChildElements();
                    while (itChildChildren.hasNext()) {
                        Object obj = itChildChildren.next();
                        if ((obj instanceof SOAPElement)) {
                            SOAPElement soapElem = (SOAPElement) obj;
                            String name = soapElem.getElementName().getLocalName();

                            QName qName = new QName(name);
                            ((SOAPElement) obj).setElementQName(qName);
                        }
                    }
                }

                // tracking
                soapMsg.writeTo(System.out);

            } catch (SOAPException e) {
                System.err.println(e);
            } catch (IOException e) {
                System.err.println(e);
            }

        }

        // continue other handler chain
        return true;
    }

    private void addNamespacePrefix(SOAPElement elem) throws SOAPException {
        Iterator<Object> it = elem.getAllAttributes();

        QName name = new QName("xmlns");
        String value = elem.getAttributeValue(name);

        if (value != null) {
            elem.addNamespaceDeclaration(PREFIX, elem.getNamespaceURI());
            elem.removeNamespaceDeclaration("");
            elem.setPrefix(PREFIX);
        }

    }

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

    @Override
    public void close(MessageContext context) {
    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }

    private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
        try {
            SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
            SOAPFault soapFault = soapBody.addFault();
            soapFault.setFaultString(reason);
            throw new SOAPFaultException(soapFault);
        } catch (SOAPException e) {
        }
    }

}

关于java - SOAPHandler:如何从子元素中删除自动添加的命名空间/属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45365901/

相关文章:

java - 如何禁用 Apache CXF

sql-server - T-SQL : Adding namespaces to XML

Java ConcurrentHashMap 和同步

php - php 中的 Soap 版本不匹配

java - Amazon S3 文件上传不起作用 - 公共(public)读取权限

objective-c - 寻找有关在iOS中访问NWS严重警报的建议

php - 如何使用 SimpleXMLElement 和多个命名空间解析 XML 文件?

python - 如何在(子)模块中使用 __init__.py 来定义命名空间?

java - 如何将java中创建的href链接传递到jsp页面

java - 哪些 Java 集合(和映射)可以按上次访问排序