如何让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可以配置为定义更智能的前缀,以便每个名称空间只有一个前缀?
我有同样的问题。目前,我通过编写一个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设置enableNamespacePrefixOptimization
到true
<globalConfiguration >
<parameter name="enableNamespacePrefixOptimization" value="true"/>
这是记录在任何地方吗?我想要一个我能做些什么来配置客户端的清单,最好不要阅读实际的源代码。 – 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 });
我有完全相同的问题。我会密切关注这个话题。 – 2008-10-07 17:19:14