【问题标题】:How can I get Axis 1.4 to not generate several prefixes for the same XML namespace?如何让 Axis 1.4 不为同一个 XML 命名空间生成多个前缀?
【发布时间】:2008-09-15 12:48:18
【问题描述】:

我正在接收来自使用 Axis 1.4 库的客户端的 SOAP 请求。请求具有以下形式:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <PlaceOrderRequest xmlns="http://example.com/schema/order/request">
      <order>
        <ns1:requestParameter xmlns:ns1="http://example.com/schema/common/request">
          <ns1:orderingSystemWithDomain>
            <ns1:orderingSystem>Internet</ns1:orderingSystem>
            <ns1:domainSign>2</ns1:domainSign>
          </ns1:orderingSystemWithDomain>
        </ns1:requestParameter>
        <ns2:directDeliveryAddress ns2:addressType="0" ns2:index="1" 
                                   xmlns:ns2="http://example.com/schema/order/request">
          <ns3:address xmlns:ns3="http://example.com/schema/common/request">
            <ns4:zipcode xmlns:ns4="http://example.com/schema/common">12345</ns4:zipcode>
            <ns5:city xmlns:ns5="http://example.com/schema/common">City</ns5:city>
            <ns6:street xmlns:ns6="http://example.com/schema/common">Street</ns6:street>
            <ns7:houseNum xmlns:ns7="http://example.com/schema/common">1</ns7:houseNum>
            <ns8:country xmlns:ns8="http://example.com/schema/common">XX</ns8:country>
          </ns3:address>
[...]

如您所见,为同一个命名空间定义了多个前缀,例如命名空间 http://example.com/schema/common 具有前缀 ns4、ns5、ns6、ns7 和 ns8。一些长请求为同一个命名空间定义了数百个前缀。

这导致Saxon XSLT 处理器出现问题,我用它来转换请求。 Saxon 将同一命名空间的不同前缀数量限制为 255 个,并在定义更多前缀时引发异常。

Axis 1.4 能否配置为定义更智能的前缀,以便每个命名空间只有一个前缀?

【问题讨论】:

  • 我也有同样的问题。我会密切关注这个话题。

标签: java xml soap namespaces axis


【解决方案1】:

我也有同样的问题。目前,我通过编写 BasicHandler 扩展来解决它,然后自己遍历 SOAPPart 并将名称空间引用向上移动到父节点。我不喜欢这个解决方案,但它似乎确实有效。

我真的希望有人过来告诉我们必须做什么。

编辑

这太复杂了,就像我说的,我一点也不喜欢它,但我们开始吧。我实际上将功能分解为几个类(这不是我们在那个项目中需要做的唯一操作,所以还有其他实现)我真的希望有人能尽快解决这个问题。这使用 dom4j 来处理通过 SOAP 进程的 XML,因此您需要 dom4j 才能使其工作。

public class XMLManipulationHandler extends BasicHandler {
    private static Log log = LogFactory.getLog(XMLManipulationHandler.class);
    private static List processingHandlers;

    public static void setProcessingHandlers(List handlers) {
        processingHandlers = handlers;
    }

    protected Document process(Document doc) {
        if (processingHandlers == null) {
            processingHandlers = new ArrayList();
            processingHandlers.add(new EmptyProcessingHandler());
        }
        log.trace(processingHandlers);
        treeWalk(doc.getRootElement());
        return doc;
    }

    protected void treeWalk(Element element) {
        for (int i = 0, size = element.nodeCount(); i < size; i++) {
            Node node = element.node(i);
            for (int handlerIndex = 0; handlerIndex < processingHandlers.size(); handlerIndex++) {
                ProcessingHandler handler = (ProcessingHandler) processingHandlers.get(handlerIndex);
                handler.process(node);
            }
            if (node instanceof Element) {
                treeWalk((Element) node);
            }
        }
    }

    public void invoke(MessageContext context) throws AxisFault {
        if (!context.getPastPivot()) {
            SOAPMessage message = context.getMessage();
            SOAPPart soapPart = message.getSOAPPart();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            try {
                message.writeTo(baos);
                baos.flush();
                baos.close();

                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                SAXReader saxReader = new SAXReader();
                Document doc = saxReader.read(bais);
                doc = process(doc);
                DocumentSource ds = new DocumentSource(doc);
                soapPart.setContent(ds);
                message.saveChanges();
            } catch (Exception e) {
                throw new AxisFault("Error Caught processing document in XMLManipulationHandler", e);
            }
        }
    }
}
public interface ProcessingHandler {
    public Node process(Node node);
}
public class NamespaceRemovalHandler implements ProcessingHandler {
    private static Log log = LogFactory.getLog(NamespaceRemovalHandler.class);
    private Namespace namespace;
    private String targetElement;
    private Set ignoreElements;

    public NamespaceRemovalHandler() {
        ignoreElements = new HashSet();
    }

    public Node process(Node node) {
        if (node instanceof Element) {
            Element element = (Element) node;
            if (element.isRootElement()) {
                // Evidently, we never actually see the root node when we're called from
                // SOAP...
            } else {
                if (element.getName().equals(targetElement)) {
                    log.trace("Found the target Element.  Adding requested namespace");
                    Namespace already = element.getNamespaceForURI(namespace.getURI());
                    if (already == null) {
                        element.add(namespace);
                    }
                } else if (!ignoreElements.contains(element.getName())) {
                    Namespace target = element.getNamespaceForURI(namespace.getURI());
                    if (target != null) {
                        element.remove(target);
                        element.setQName(new QName(element.getName(), namespace));
                    }
                }

                Attribute type = element.attribute("type");
                if (type != null) {
                    log.trace("Replacing type information: " + type.getText());
                    String typeText = type.getText();
                    typeText = typeText.replaceAll("ns[0-9]+", namespace.getPrefix());
                    type.setText(typeText);
                }
            }
        }

        return node;
    }

    public Namespace getNamespace() {
        return namespace;
    }

    public void setNamespace(Namespace namespace) {
        this.namespace = namespace;
    }

    /**
     * @return the targetElement
     */
    public String getTargetElement() {
        return targetElement;
    }

    /**
     * @param targetElement the targetElement to set
     */
    public void setTargetElement(String targetElement) {
        this.targetElement = targetElement;
    }

    /**
     * @return the ignoreElements
     */
    public Set getIgnoreElements() {
        return ignoreElements;
    }

    /**
     * @param ignoreElements the ignoreElements to set
     */
    public void setIgnoreElements(Set ignoreElements) {
        this.ignoreElements = ignoreElements;
    }

    public void addIgnoreElement(String element) {
        this.ignoreElements.add(element);
    }
}

无保修等。

【讨论】:

    【解决方案2】:

    对于请求,我使用它来删除命名空间类型:

    String endpoint = "http://localhost:5555/yourService";
    
    // Parameter to be send
    Integer secuencial = new Integer(11);  // 0011
    
    // Make the call
    Service  service = new Service();
    
    Call call = (Call) service.createCall();
    
    // Disable sending Multirefs
    call.setOption( org.apache.axis.AxisEngine.PROP_DOMULTIREFS, new java.lang.Boolean( false) ); 
    
    // Disable sending xsi:type
    call.setOption(org.apache.axis.AxisEngine.PROP_SEND_XSI, new java.lang.Boolean( false));  
    
    // XML with new line
    call.setOption(org.apache.axis.AxisEngine.PROP_DISABLE_PRETTY_XML, new java.lang.Boolean( false)); 
    
    // Other Options. You will not need them
    call.setOption(org.apache.axis.AxisEngine.PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION, new java.lang.Boolean( true)); 
    call.setOption(org.apache.axis.AxisEngine.PROP_DOTNET_SOAPENC_FIX, new java.lang.Boolean( true));
    
    call.setTargetEndpointAddress(new java.net.URL(endpoint));
    call.setSOAPActionURI("http://YourActionUrl");//Optional
    
    // Opertion Name
    //call.setOperationName( "YourMethod" );
    call.setOperationName(new javax.xml.namespace.QName("http://yourUrl", "YourMethod"));      
    
    // Do not send encoding style
    call.setEncodingStyle(null);
    
    // Do not send xmlns in the xml nodes
    call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
    
    /////// Configuration of namespaces
    org.apache.axis.description.OperationDesc oper;
    org.apache.axis.description.ParameterDesc param;
    oper = new org.apache.axis.description.OperationDesc();
    oper.setName("InsertaTran");
    param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://yourUrl", "secuencial"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"), int.class, false, false);
    oper.addParameter(param);
    
    oper.setReturnType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"));
    oper.setReturnClass(int.class);
    oper.setReturnQName(new javax.xml.namespace.QName("http://yourUrl", "yourReturnMethod"));
    oper.setStyle(org.apache.axis.constants.Style.WRAPPED);
    oper.setUse(org.apache.axis.constants.Use.LITERAL);
    
    call.setOperation(oper);
    
    Integer ret = (Integer) call.invoke( new java.lang.Object [] 
                { secuencial });
    

    【讨论】:

      【解决方案3】:

      更改客户的 wsdd 以将 enableNamespacePrefixOptimization 设置为 true

      <globalConfiguration >
        <parameter name="enableNamespacePrefixOptimization" value="true"/>
      

      【讨论】:

      • 这是否记录在任何地方?我想要一个很好的列表,列出我可以做些什么来配置客户端,最好不要阅读实际的源代码。
      • 我通过查看一个旧项目找到了该参数。有用吗?
      猜你喜欢
      • 2012-08-13
      • 2012-04-10
      • 2011-08-16
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多