在XML(WSDL)文件中交换元素属性值?

时间:2012-07-17 15:55:29

标签: java xml xslt xpath xquery

考虑我有任何标准的WSDL文件(用XML表示):

<wsdl:definitions>

      <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 name="countrySoap”>

  ....
</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:definitionswsdl:portTypewsdl:operation - 而其他人可能只是definitionsportTypeoperation

2 个答案:

答案 0 :(得分: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"))

HTH!

答案 1 :(得分: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>