WSDL and XSL

If this solution is familiar to experienced XSL users, forgive me.  I'm a casual XSL user, so the problem was difficult to identify and I didn't find much in the way of Google entries covering the answer.  So that (in my small, secluded little world) makes it blog-worthy.

The situation I found myself in was needing to convert the WSDL output from an ASP.NET page to a specific XML format.  The reason for the format is irrelevant.  Suffice it to say, that I needed to create a list of the valid SOAP operations for a particular web service.  I tool the WSDL that was generated by ASP.NET and started the trial and error process of identifying the correct XSL stylesheet to use.  This is where I ran into problems.

I do understand the basics of XPath enough to try simple queries.  My starting point was to list out the portTypes for the WSDL.  To do this, my initial XPath query was //definitions/portType.  This didn't actually return any nodes.  I thought this strange, so I dropped down to the more straightforward //definitions.  This too returned nothing.  Running out of drop-back room, I went with the wildcard //*.  Fortunately for what remains of my hair, this worked. So the question of why the other queries didn't work remained.

After more painful attempts (and a weekend to allow my brain some reset), I finally came across the solution.  XPath queries don't work with the empty namespace.  They require that the namespace be explicit within the query.  But the WSDL generated by ASP.NET does not assign a namespace to the WSDL elements, choosing to use the empty namespace.  So the XSL file needed to be modified to define a namespace for the URI associated with the WSDL elements.  When done, the xsl:stylesheet element looked like the following:

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" >
 

The key here is the xmlns:wsdl attribute.  This defines a namespace called wsdl and associates it with the listed URI.  This URI needs to match exactly the URI associated with the empty namespace in the WSDL file.  And I do mean exactly.  Character for character.  Byte for byte. 

Once this has been added to the stylesheet tag, the XPath queries can be modified to be //wsdl:definitions/wsdl:portType and the results will be as expected.