如何获得Axis 1.4而不为同一XML名称空间生成多个前缀?
时间:2020-03-05 18:53:21 来源:igfitidea点击:
我正在从使用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配置为定义更智能的前缀,以便每个命名空间只有一个前缀吗?
解决方案
回答
我有同样的问题。目前,我通过编写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"/>