2008-09-15 11 views
6

Je reçois des demandes SOAP d'un client qui utilise les bibliothèques Axis 1.4. Les demandes ont la forme suivante:Comment puis-je obtenir que Axis 1.4 ne génère pas plusieurs préfixes pour le même espace de noms 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> 
[...] 

Comme vous pouvez le voir, plusieurs préfixes sont définis pour le même espace de noms, par exemple l'espace de noms http://example.com/schema/common a les préfixes ns4, ns5, ns6, ns7 et ns8. Certaines requêtes longues définissent plusieurs centaines de préfixes pour le même espace de noms.

Cela provoque un problème avec le processeur XSLT Saxon, que j'utilise pour transformer les demandes. Saxon limite le nombre de préfixes différents pour le même espace de noms à 255 et déclenche une exception lorsque vous définissez plusieurs préfixes.

L'Axe 1.4 peut-il être configuré pour définir des préfixes plus intelligents, de sorte qu'il n'y a qu'un seul préfixe pour chaque espace de noms?

+1

J'ai exactement le même problème. Je vais regarder ce fil de près. –

Répondre

3

J'ai le même problème. Pour le moment, j'ai travaillé autour d'elle en écrivant une extension BasicHandler, puis en parcourant moi-même SOAPPart et en déplaçant la référence d'espace de noms jusqu'à un nœud parent. Je ne ai pas comme cette solution, mais cela semble fonctionner. J'espère vraiment que quelqu'un viendra et nous dira ce que nous devons faire.

EDIT

C'est trop compliqué, et comme je l'ai dit, je ne l'aime pas du tout, mais ici nous allons. En fait, j'ai cassé la fonctionnalité dans quelques classes (ce n'était pas la seule manipulation que nous avions besoin de faire dans ce projet, donc il y avait d'autres implémentations) J'espère vraiment que quelqu'un pourra le réparer bientôt. Cela utilise dom4j pour traiter le XML passant par le processus SOAP, vous aurez donc besoin de dom4j pour le faire fonctionner.

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

Aucune garantie, etc, etc.

1

Alter WSDD de votre client pour définir enableNamespacePrefixOptimization à true

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

Est-ce documenté quelque part? Je voudrais une bonne liste de ce que je peux faire pour configurer le client, de préférence sans lire le code source réel. –

+0

J'ai trouvé ce paramètre en regardant un ancien projet. Est-ce que ça marche? –

2

Pour la demande, je l'utiliser pour supprimer des types d'espaces de noms:

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