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="http://www.w3.org/2001/XMLSchema"
  xmlns:xsl="http://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.