3

考虑一下我有任何标准 WSDL 文件(以 XML 表示):

<wsdl:definitions>

      <wsdl:types>
        ...
      </wsdl:types>

      <wsdl:message>
        ...
      </wsdl:message>

      <wsdl:portType name="countrySoap”&gt;
         <wsdl:operation name="GetCountryByCountryCode">
             <wsdl:documentation>Get country name by country code</wsdl:documentation>
             <wsdl:input message="tns:GetCountryByCountryCodeSoapIn" />
             <wsdl:output message="tns:GetCountryByCountryCodeSoapOut" />
         </wsdl:operation>
        <wsdl:operation name="GetISD">
            <wsdl:documentation>Get International Dialing Code </wsdl:documentation>
            <wsdl:input message="tns:GetISDSoapIn" />
            <wsdl:output message="tns:GetISDSoapOut" />
        </wsdl:operation>
        ...
      <wsdl:portType name="countrySoap”&gt;

  ....
</wsdl:definitions>

我想做的是有一种简单/有效的方法来交换每条消息的输入和输出消息。

例如,我想要:

         <wsdl:operation name="GetCountryByCountryCode">
             <wsdl:documentation>Get country name by country code</wsdl:documentation>
             <wsdl:input message="tns:GetCountryByCountryCodeSoapOut" />
             <wsdl:output message="tns:GetCountryByCountryCodeSoapIn" />
         </wsdl:operation>

我一直在使用的示例 wsdl 文件可以在这里找到: http ://www.webservicex.net/country.asmx?WSDL

进一步说明:

  • 我可能正在寻找基于 XSLT 的解决方案,因为在我看来这似乎更有效。例如,我当前的解决方案是基于 Java 的,但它似乎没有我想要的那么高效。
  • 如果解决方案能够忽略任何命名空间,那就太好了,例如:一些 wsdl 文件显示为:wsdl:definitions, wsdl:portType, wsdl:operation- 而其他可能只是definitions, portType,operation等。
4

2 回答 2

1

您无需担心命名空间前缀,只要命名空间 uri 匹配,这并不重要。

XSLT 和 XQuery 都可以为您提供紧凑的解决方案。不过,在 XSLT 中调整输出缩进可能更容易一些。

这里有一个 XSLT 2.0 解决方案:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wsdl:input">
        <xsl:copy>
            <xsl:apply-templates select="../wsdl:output/(@*|node())"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wsdl:output">
        <xsl:copy>
            <xsl:apply-templates select="../wsdl:input/(@*|node())"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet> 

这里有一个 XQuery 1.0 解决方案:

xquery version "1.0";

declare namespace wsdl = "http://schemas.xmlsoap.org/wsdl/";

declare function local:recurse-nodes($nodes) {
    for $node in $nodes
    return typeswitch ($node)
        case $node as element (wsdl:input) return
            element { node-name($node) } { $node/../wsdl:output/local:recurse-nodes(@*|node()) }
        case $node as element (wsdl:output) return
            element { node-name($node) } { $node/../wsdl:input/local:recurse-nodes(@*|node()) }
        case $node as element () return
            element { node-name($node) } { $node/local:recurse-nodes(@*|node()) }
        case $node as document-node () return
            document { local:recurse-nodes($node/node()) }
        default return $node
};

local:recurse-nodes(doc("country.xml"))

于 2012-07-17T16:44:36.120 回答
1

此 XSLT(1.0 和 2.0)转换

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:x="some:wsdl">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="x:input/@message">
  <xsl:attribute name="message">
    <xsl:value-of select="../../x:output/@message"/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="x:output/@message">
  <xsl:attribute name="message">
    <xsl:value-of select="../../x:input/@message"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

当应用于以下 XML 文档时(从提供的、严重格式错误的文档中获得):

<wsdl:definitions xmlns:wsdl="some:wsdl">

          <wsdl:types>
            ...
          </wsdl:types>

          <wsdl:message>
            ...
          </wsdl:message>

          <wsdl:portType name="countrySoap">
             <wsdl:operation name="GetCountryByCountryCode">
                 <wsdl:documentation>Get country name by country code</wsdl:documentation>
                 <wsdl:input message="tns:GetCountryByCountryCodeSoapIn" />
                 <wsdl:output message="tns:GetCountryByCountryCodeSoapOut" />
             </wsdl:operation>
            <wsdl:operation name="GetISD">
                <wsdl:documentation>Get International Dialing Code </wsdl:documentation>
                <wsdl:input message="tns:GetISDSoapIn" />
                <wsdl:output message="tns:GetISDSoapOut" />
            </wsdl:operation>
            ...
          </wsdl:portType>

      ....
</wsdl:definitions>

产生想要的正确结果

<wsdl:definitions xmlns:wsdl="some:wsdl">
   <wsdl:types>
            ...
          </wsdl:types>
   <wsdl:message>
            ...
          </wsdl:message>
   <wsdl:portType name="countrySoap">
      <wsdl:operation name="GetCountryByCountryCode">
         <wsdl:documentation>Get country name by country code</wsdl:documentation>
         <wsdl:input message="tns:GetCountryByCountryCodeSoapOut"/>
         <wsdl:output message="tns:GetCountryByCountryCodeSoapIn"/>
      </wsdl:operation>
      <wsdl:operation name="GetISD">
         <wsdl:documentation>Get International Dialing Code </wsdl:documentation>
         <wsdl:input message="tns:GetISDSoapOut"/>
         <wsdl:output message="tns:GetISDSoapIn"/>
      </wsdl:operation>
            ...
          </wsdl:portType>

      ....
</wsdl:definitions>
于 2012-07-18T02:36:39.177 回答