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

时间:2017-07-28 05:59:09

标签: 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>

如您所见,我可以将命名空间前缀添加到<getMachine>标记,但随后会自动将xmlns属性添加到子元素<machineId>。我该如何避免或解决这个问题?

1 个答案:

答案 0 :(得分:0)

在使用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) {
        }
    }

}