如何使Axis 1.4不能为同一XML名称空间生成多个前缀? [英] How can I get Axis 1.4 to not generate several prefixes for the same XML namespace?

查看:70
本文介绍了如何使Axis 1.4不能为同一XML名称空间生成多个前缀?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am receiving SOAP requests from a client that uses the Axis 1.4 libraries. The requests have the following form:

<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.一些长请求为同一个命名空间定义了数百个前缀.

As you can see, several prefixes are defined for the same namespace, e.g. the namespace http://example.com/schema/common has the prefixes ns4, ns5, ns6, ns7 and ns8. Some long requests define several hundred prefixes for the same namespace.

这会导致 Saxon XSLT处理器出现问题,该问题用于转换请求. Saxon将同一名称空间的不同前缀数限制为255,并且在定义更多前缀时引发异常.

This causes a problem with the Saxon XSLT processor, that I use to transform the requests. Saxon limits the the number of different prefixes for the same namespace to 255 and throws an exception when you define more prefixes.

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

Can Axis 1.4 be configured to define smarter prefixes, so that there is only one prefix for each namespace?

推荐答案

我遇到了同样的问题.目前,我通过编写BasicHandler扩展解决了这个问题,然后亲自遍历SOAPPart并将名称空间引用移至父节点.我不喜欢这种解决方案,但它确实有效.

I have the same issue. For the moment, I've worked around it by writing a BasicHandler extension, and then walking the SOAPPart myself and moving the namespace reference up to a parent node. I don't like this solution, but it does seem to work.

我真的希望有人能告诉我们我们该怎么做.

I really hope somebody comes along and tells us what we have to do.

EDIT

EDIT

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

This is way too complicated, and like I said, I don't like it at all, but here we go. I actually broke the functionality into a few classes (This wasn't the only manipulation that we needed to do in that project, so there were other implementations) I really hope that somebody can fix this soon. This uses dom4j to process the XML passing through the SOAP process, so you'll need dom4j to make it work.

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

无保修等.

这篇关于如何使Axis 1.4不能为同一XML名称空间生成多个前缀?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆