Home
 

User login

 
 

Navigation

 
 

Events

« July 2008
SunMonTueWedThuFriSat
12345
6789101112
13141516171819
20212223242526
2728293031
 

Simplified WSDL, Part 2

By James Pasley - 10 June 2003

In the first part of this article, I explained how to apply a stylesheet to a WSDL document. In this article I'll take a closer look at the simplifyWSDL stylesheet itself.

The Start of the Stylesheet

For those of you familiar with XSLT, it starts simply enough by declaring a few XML namespaces and stating that the output will be HTML:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" >
<-- Copyright (C) 2002 Cape Clear Software. All rights reserved. -->
<xsl:output method="html" indent="yes"/>

Following that is the template that matches on the root node of the WSDL document. This is used to output the basic HTML tags including the link to the cascading style sheet defining the fonts and colors. Then the XSLT processor is instructed to process the rest of the document using the apply-templates instruction.

<xsl:template match="/">
<html>
<link rel="stylesheet" href="simplifiedxml.css"/>
<head>
<xsl:comment>Simplified WSDL: Generated by the CapeStudio Simplied WSDL Stylesheet. http://www.capeclear.com/capestudio
</xsl:comment>
</head>
<body class="text">
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

It is tempting the use the instruction <xsl:apply-templates select="*" /> to process all the child nodes. However, while the asterix is the wild card, it only matches elements, so comments and text nodes in the source doc will be ignored. In this case we do want to process such nodes, as everything in the source will be displayed. This is achieved by leaving out the select statement.

The Formatting Rules for WSDL

Following this initial template is a set of templates, one for each of the WSDL constructs: definitions, import, types, message, and so on. Each of these templates follows roughly the same structure:

  1. Output the documentation
  2. Start a new line and indent
  3. Output the element name as a keyword
  4. Output any attributes associated with the definition in an appropriate format
  5. Where appropriate, process the child nodes (using apply-templates) enclosed within some curly braces.

For example, the template for the definitions construct is shown below:

<xsl:template match="wsdl:definitions">
<xsl:call-template name="documentation"/>
<xsl:call-template name="newline"/>
<xsl:call-template name="keyword"/>
<xsl:value-of select="@name"/>
<xsl:if test="@targetNamespace">
<xsl:call-template name="keyword">
<xsl:with-param name="word" select="'@targetNamespace'"/>
</xsl:call-template>
<xsl:value-of select="@targetNamespace">
</xsl:value-of>
</xsl:if>
<xsl:call-template name="openbrace"/>
<xsl:apply-templates/>
<xsl:call-template name="closebrace"/>
</xsl:template>

 

Utility Templates

After the WSDL construct templates is a set of utility templates.

Documentation

The template that outputs the documentation is a named template as opposed to a matching one. In fact, there is a matching one just below it which ensures that wsdl:documentation nodes that are found are not processed. The reason for this is that documentation associated with a WSDL definition is placed within the element that it documents, where as it is more typical (in languages such as Java) to place the documentation just before the definition. Calling the documentation template explicitly from within the templates for all the other WSDL constructs allows us to output the text in a different order to the way it is arranged in the source document.

<xsl:template name="documentation">
<xsl:param name="doc" select="wsdl:documentation"/>
<xsl:if test="$doc">
<xsl:for-each select="$doc/parent::node()">
<xsl:call-template name="newline"/>
</xsl:for-each>
<a class="comment">/** <xsl:value-of select="$doc"/> */ </a>
</xsl:if>
</xsl:template>

<xsl:template match="wsdl:documentation"/>

Where the data in the output is to be arranged in the same order as the input, matching templates are most appropriate. Where the order of the data is to be changed, named templates are usually used. These two approaches are commonly referred to as 'push' and 'pull' respectively. In a lot of real world examples, you will see the two approaches used together as in this example.

The Default Matching Rule

The template <xsl:template match="*"> is used to match any elements found in the file which are not defined in the WSDL specification. This will typically be embedded XML Schemas as these are not yet supported by the simplifyWSDL stylesheet. This template just outputs elements and attributes so that a browser may display them. In the interests of simplification, all of the namespace information is dropped.

Keywords

The keyword template is a small template that outputs the HTML necessary to highlight a piece of text as a keyword of the language (i.e. in blue). The word to be highlighted is passed in using the parameter called word.

<xsl:template name="keyword">
<xsl:param name="word" select="local-name(.)"/>
<a class="keyword">
<xsl:value-of select="concat($word,' ')"/>
</a>
</xsl:template>

Of interest in this template is the use of a default value for the parameter. Specifying default values for parameters wherever possible can significantly reduce the amount of code necessary to call a template. In this case, the default value is the local name of the current node. A node from the source becomes the current node when it is processed using either apply-template or for-each. In this scenario, it typically refers to the node that was matched when a template was invoked. Additionally, using a parameter and not just relying on the use of the current node allows the default value to be easily overridden where necessary. As a result of defining the template in this way most calls to it are simply: <xsl:call-template name="keyword"/>.

Starting a New Line

The newline template outputs a <br/> to start a new line followed by an appropriate number of &nbsp characters to provide the indentation. &nbsp can not be used within the stylesheet as the XSLT processor will attempt to interpret it. Hence the character code &#160 is used instead.

<xsl:template name="newline">
<br/>
<xsl:for-each select="ancestor::*">
<xsl:text>&#160;&#160;&#160;&#160;</xsl:text>
</xsl:for-each>
</xsl:template>

This template provides a good example of how the programmer must adapt to writing XSLT. If you were writting a text-formatting program in Java or C, your first approach would probably be to declare a variable to store the number of spaces by which each line is to be indented. When a new scope level is entered, the variable would be incremented and when it is exited, the variable is decremented. However, the values of variables cannot be modified in XSLT--this is the source of much frustration to the beginner (not as much as tree fragments, but that�s another story). In many cases, as it is here, the answer is to look for ways of calculating the value as you need it based on the information available in the source document. So the simple rule of thumb: �indent by the number of parent nodes in the source document� comes to our rescue.

Finally...

The set of templates described above may be used to simplify any declarative language that uses the XML syntax. To create a new stylesheet, keep the template that matches on the root node and the utility templates and replace all the templates that match on the WSDL element with templates specific to the new language. In fact, I have done just that for XSLT itself, so if you still don't like to look of all those XML tags, you can view the stylesheet as simplified XSLT http://developer.capeclear.com/files/simplifiedwsdl.xslt. Finally, if it doesn't make your brain hurt, you can even see what the simplifiedxslt stylesheet looks like when you process it using itself: simplifiedxslt.xslt.

However, if you would rather not write XSLT by hand and are converting between XML formats described by schema, check out the CapeStudio XSLT Mapper at http://www.capeclear.com/products/capestudio/index.shtml.


Categories: