In Chapter 3, we created an XML document that represents the Python classes in the PyXML package (index.py). The pyxml.xml file from Chapter 3 is a lengthy XML document, and makes a good test subject.
In this section, we convert the pyxml.xml file back to HTML, but this time
using XSLT instead of a SAX driver. After using XSLT to perform this,
the SAX and string approach from Chapter
2 will not seem nearly as powerful. However, this type of
conversion work is exactly what XSLT is designed to accomplish. The
basic structure of the pyxml.xml
document consists of a file
element,
followed by one or more class
elements, followed by one or more method definition elements:
<file name="../xml/dom/ext/reader/HtmlLib.py"> <class name="class HtmlToDomParser(SGMLParser):"> <method name="def __init__(self):"/> <method name="def unknown_starttag(self,tag,attrs):"/> <method name="def unknown_endtag(self, tag):"/> <method name="def handle_data(self, data):"/> <method name="def handle_comment(self, comment):"/> <method name="def handle_generic_node(self, node):"/> <method name="def report_unbalanced(self, tag):"/> <method name="def toDom(self, st, ownerDoc=None):"/> </class> </file>
The above XML represents only a few lines of the 2600 line file.
The stylesheet used to convert this XML to HTML uses a combination of
apply-templates
and value-of
elements to traverse the structure
and generate appropriate output.
The stylesheet starts by creating the HTML opening and closing
elements, and calling apply-templates
to fill in the content:
<xsl:template match="pyxml"> <html> <body bgcolor="#FFFFFF" text="#3333FF"> <xsl:apply-templates/> </body> </html> </xsl:template>
Three separate templates, one for each of the element types generated by index.py, are defined in the next section and catch the content and generate the appropriate HTML output.
To catch file
elements in pyxml.xml, create a
template that uses the element’s name as a match. Once found, HTML is
formatted to produce the name of the file in red text in a new table
row:
<xsl:template match="file"> <p> <table cellpadding="0" cellspacing="0" border="1" bordercolor="#000000" width="540"> <tr> <td align="center">Source File: <b class="filename"><xsl:value-of select="./@name"/></b> </td> </tr> <xsl:apply-templates/> </table></p> </xsl:template>
Inside the template, a value-of
element is used with a path
expression that targets the name
attribute. After the table row is complete, apply-templates
is used to fill in the
content beneath this element, which may consist of multiple class
and method
elements.
The class
template
creates a new table row with the classname, then simply prints out the
classname:
<xsl:template match="class"> <tr> <td>Class: <b class="classname"><xsl:value-of select="./@name"/></b> </td> </tr> <xsl:apply-templates/> </xsl:template>
As shown earlier, the apply-templates
instruction is used to
further fill in the content beneath this element.
The method
template
follows suit and creates its own unique HTML to display method names,
this time in black text:
<xsl:template match="method"> <tr> <td align="left"> <span class="methodname" ><xsl:value-of select="./@name"/></span> </td> </tr> </xsl:template>
Here apply-templates
is not
used because there are no child elements of a method
element in the pyxml.xml document.
Example 6-5 shows the complete listing of pyxml.xsl.
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/> <xsl:template match="pyxml"> <html> <body bgcolor="#FFFFFF" text="#3333FF"> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="file"> <p><table cellpadding="0" cellspacing="0" border="1" bordercolor="#000000" width="540"> <tr> <td align="center">Source File: <b><font color="#FF0000"> <xsl:value-of select="./@name"/> </font></b> </td> </tr> <xsl:apply-templates/> </table></p> </xsl:template> <xsl:template match="class"> <tr> <td>Class: <b><xsl:value-of select="./@name"/></b> </td> </tr> <xsl:apply-templates/> </xsl:template> <xsl:template match="method"> <tr> <td align="left"> <font color="#000000"> <xsl:value-of select="./@name"/> </font> </td> </tr> </xsl:template> </xsl:stylesheet>
When you run the transformation in Example 6-5, you produce a pyxml.html document that shows all of the classes in the PyXML package.
C:my-dir> 4xslt pyxml.xml pyxml.xsl > pyxml.html
3.21.246.223