• Aucun résultat trouvé

A More Complex Example

Chapter 5. Querying XML with XPath

6.6 A More Complex Example

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.

6.6.1 File Template

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.

6.6.2 Class Template

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.

6.6.3 Method Template

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.

Example 6-5. 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