home .. products ..
restxsl

restxsl transforms reStructuredText files into XML files using XSL templates. Most users will output XHTML files, but any form of XML file can be created.

Every aspect of the generated content and layout can be controlled. A sample XSL template is provided to get you going, but you can easily create templates to match any type of site design. The strangeGizmo.com web site is 100% reStructuredText, generated entirely with restxsl.

As an added bonus, restxsl can apply SmartyPants-style processing to your reStructuredText files. Quotes, dashes, and ellipses are all educated automatically as part of the restxsl processing pipeline. This behavior is controlled by a parameter to restxsl and can be enabled and disabled as desired.

Rationale

Semantically correct XHTML and CSS let you separate content from presentation. But how do you separate content from layout? CSS absolute positioning might work, although it brings its own set of baggage to the table. Besides, who wants to write XHTML all day?

restxsl uses existing technologies to separate content, layout, and presentation. The result is an easy-to-use, well-balanced approach to web site design:

Maintaining a reST+XSL+CSS site is much easier than maintaining an XHTML-based site. No complex tags or layout decisions enter into the content equation. Just fire up a text editor and start typing.

restxsl also makes it easy to change the look and layout of your site. Want to make a style change? Use CSS, just like in the XHTML+CSS world. Need to move content blocks around? Just change the appropriate XSL template; the content files stay the same.

How it works

reStructuredText files are converted (in-memory) into an XML representation of the Docutils Document Tree. This in-memory XML document is then transformed using an XSL template.

Special reStructuredText Extensions in the form of restxsl-specific directives and roles may modify the XML representation of the reStructuredText document before the XSL transformation is applied. These extensions allow you to, among other things, include dynamic content in your statically-generated pages.

System Requirements

restxsl makes use of libxml2 to build its internal XML documents and libxslt to perform XSL transformations. Both packages must be installed in order for restxsl to do its job. docutils is, of course, required as well.

 
Command-Line API

The restxsl command-line tool makes it easy to access restxsl’s functionality from shell scripts, Makefiles, etc. restxsl accepts a list of reStructuredText files to process and produces a series of output files.

Specifying the XSL template

There are two ways to specify the XSL template that should be used to transform the reST files:

  1. Provide the path to an XSL template on the command line using the -s or --stylesheet option. All of the listed reStructuredText files will be processed with the same XSL template.
  2. Specify the path (relative or absolute) to the XSL template by including an :xsl-template: field definition in each of the reStructuredText files. Here is a sample file:===========
    My Document
    ===========

    :xsl-template: mydoc.xsl

    This is only paragraph in my document.  It will be styled using
    the ``mydoc.xsl`` template in the same directory as this reST
    file.

Path names

Paths to XSL templates may appear in one of three locations: on the command line, in a reStructuredText file (via the :xsl-template: field), or in an XSL template (via the xsl:include or xsl:import tags).

If a path is specified on the command line, then that path should refer to the XSL template itself. This can be a relative or absolute path, as long as it points to a real file on disk.

Any relative path that is found inside of a file (reST or XSL) is assumed to be relative to the document that included the file. This is true regardless of the file type (reST, XSL, even something in a code-block directive).

Absolute XSL paths, on the other hand, need special handling. These path names are usually rooted to the base directory of your web site. That works fine for serving up XSL files over HTTP, but does not work very well when you are processing the content locally.

To resolve this issue, restxsl provides a command line option (-b or --base-path) that lets you set the base path for absolute stylesheet references. Any absolute XSL path will first be rooted at this base path before being resolved.

Here is a sample reStructuredText document that makes use of this functionality:

===========
My Document
===========

:xsl-template: /xsl/site_layout.xsl

This is only paragraph in my document.  It will be styled using
the ``site_layout.xsl`` template in the web server's ``/xsl``
directory.

Assuming that your web server’s root directory is /var/www, you would execute restxsl with the following command-line arguments in order to properly resolve absolute path names:

restxsl --base-path /var/www mydoc.txt

The reference to /xsl/site_layout.xsl in the reStructuredText file would first be changed to /var/www/xsl/site_layout.xsl before the XSL template was processed. Relative XSL paths will remain unchanged.

 
reStructuredText Extensions

In addition to the base functionality offered by restxsl, a number of additional reStructuredText directives and roles are also provided by restxsl. Among other things, these extra features make it much easier to build sites with statically-generated dynamic content.

Directives

pyxslt

The pyxslt directive lets you execute pre-defined Python functions during the restxsl processing phase. The value(s) returned from the called function will be serialized using the pyxslt package and embedded in the intermediate XML document. You can then transform the pyxslt XML fragment using your XSL template.

pyxslt accepts a function name and a list of keyword arguments. Only functions that are defined in the module specified by the extModule argument to the restxsl.transform.restxsl function (--module argument to the restxsl command-line tool) can be called. There is no provision for executing Python source embedded in reStructuredText documents.

Sample usage:

This is a line of text in a reStructuredText file.

.. pyxslt:: sampleFunction
    :sampleArg: One
    :anotherArg: 27

More generic text.

The above sample would call the function sampleFunction in the specified extension module. The function will be called with two arguments: sampleArg (given a string value of 'One') and anotherArg (string value of '27'). Note that all arguments are passed as strings.

The return value from the sampleFunction will be passed to the pyxslt serializer. The resulting XML fragment will be embedded in the intermediate reStructuredText XML tree under a node with the tag pyxslt.

multidoc

The multidoc feature of the pyxslt directive lets you create multiple XML target documents from a single reStructuredText source file. You might use this feature to generate one page for each entry in a database, for example.

To generate multiple documents from a pyxslt result, pass an XPATH expression to the multidoc argument of the pyxslt directive. This XPATH expression will be used to generate the name of each file that is created by the multidoc feature of pyxslt. The file extension will be the same as the base extension given to the restxsl command-line tool.

The following sample assumes that a function named listFriends exists in the extension module. This function returns a list of Person objects. Our theoretical XSL template (not included here), elides the pyxslt tag, ensuring that the serialized Python objects are not present in the document.

================================================
My Friend: :xpath:`list/item/first-name`
================================================

.. pyxslt:: listFriends
    :multidoc: list/item/first-name
    :randomArg: Just here for sample purposes.

I have a friend named :xpath:`list/item/first-name`.  Where does
:xpath:`list/item/pronoun` live?  :xpath:`list/item/city`, of
course.

Assuming that I have two friends in the database, and assuming that I am using a very simple XSL template, the following two XHTML files might be output:

File #1 (will be called Bob.html):

<?xml version="1.0" encoding="ASCII"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  
<head>
    
<title>My Friend: Bob</title>
  
</head>
  
<body>
    
<p>I have a friend named Bob.  Where does he live?
    Bobville, of course.
</p>
  
</body>
</html>

File #2 (will be called Jim.html):

<?xml version="1.0" encoding="ASCII"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  
<head>
    
<title>My Friend: Jim</title>
  
</head>
  
<body>
    
<p>I have a friend named Jim.  Where does he live?
    Jimville, of course.
</p>
  
</body>
</html>

This example makes use of the xpath role that is provided by restxsl. You could also use multidoc without the xpath role: just transform the resulting pyxslt objects in your XSL template. In the above example, I could have provided all of the text (“I have a friend…”) in the XSL template and inserted the pyxslt values using <xsl:value-of .. /> tags. I prefer to use the xpath role, because it provides a cleaner separation between content and layout.

code-block

code-block is based on a Python Cookbook recipe by Kevin Schluff. This directive lets you include arbitrary blocks of source code which will then be colorized and inserted into your XHTML target document.

SilverCity must be installed to use this directive. Note that version 0.9.6 of SilverCity has a bug in it (description and workaround available on SourceForge); 0.9.5 works fine.

Roles

xpath

The xpath role lets you insert text into your reStructuredText document based on an XPATH query into the contents of a pyxslt section. This is especially useful when combined with the multidoc feature of the pyxslt directive. See the code example in the multidoc section for a sample of the xpath role.

XPATH expressions are usually absolute, but the xpath role also supports relative XPATH expressions. Relative expressions will be prepended with //pyxslt/.