WSDL.EXE problem with BEA WSDL

As it turns out, using the 1.x builds of the .NET Framework, wsdl.exe (and
VS.NET) are sometimes unable to process perfectly good WSDL documents generated
from the latest versions of BEA WebLogic Workshop. If the WSDL contains
multiple schemas, and any have the same targetNamespace as another,
you'll get something like, "a schema with the namespace 'urn:foo-bar" has
already been added."

There are not currently plans to fix this behavior in the 1.x versions
of the framework. The product group is, however, planning to fix
it in 2.0 (although it's not yet in beta 1 yet). Since I know at least 2
large Microsoft customers have hit this problem, I thought someone else
might find this XSLT transform beneficial.

 <xsl:stylesheet version="1.0" 
  xmlns:xs="https://www.w3.org/2001/XMLSchema"
  xmlns:xsl="https://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" />
  <xsl:key name="matching-schemas" 
    match="xs:schema" use="@targetNamespace" />

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

  <xsl:template match="xs:schema">
    <xsl:variable name="matches" 
      select="key('matching-schemas', @targetNamespace)" />
    <xsl:if test="count( . | $matches[1]) = 1">
      <xsl:apply-templates select="$matches[1]" mode="consolidate">
        <xsl:with-param name="matches" select="$matches" />
      </xsl:apply-templates>
    </xsl:if>
  </xsl:template>

  <xsl:template match="xs:schema" mode="consolidate">
    <xsl:param name="matches" />
    <xs:schema>
      <xsl:apply-templates select="@*|node()" />
      <xsl:for-each select="$matches[position() != 1]">
        <xsl:apply-templates select="@*|node()" />
      </xsl:for-each>
    </xs:schema>
  </xsl:template>

</xsl:stylesheet>

I just threw it together and I've only tested it on a couple of
WSDLs ... so you might want to verify the results with yours, but I think
it's pretty solid.

At a higher level, this issue is usually a result of
developing the Web service using a code-first approach
in BEA WebLogic Workshop. As you will see is a common theme on this blog, I
recommend developing Web services using a contract-first approach whenever
possible, no matter what your platform.

I hope someone finds the transform useful. If you have any improvements or
comments about it, let's hear 'em.