如何让Axis 1.4不为相同的XML名称空间生成多个前缀?

问题描述:

我正在接收来自使用Axis 1.4库的客户端的SOAP请求。这些请求具有以下形式:如何让Axis 1.4不为相同的XML名称空间生成多个前缀?

<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。一些长请求为相同的名称空间定义了几百个前缀。

这导致了我用来转换请求的XSLT处理器的Saxon问题。撒克逊将相同名称空间的不同前缀数量限制为255,并在定义更多前缀时引发异常。

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

+1

我有完全相同的问题。我会密切关注这个话题。 – 2008-10-07 17:19:14

我有同样的问题。目前,我通过编写一个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); 
} 
} 

没有担保,等等,等等

改变客户的WSDD设置enableNamespacePrefixOptimizationtrue

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

这是记录在任何地方吗?我想要一个我能做些什么来配置客户端的清单,最好不要阅读实际的源代码。 – 2008-10-09 20:53:06

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

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 });