nori 0.1.0

Nori is a webserving framework built on Python and XML. It allows a web developer to send an XML input document through any number of steps, where each step is either a stylesheet transformation or a custom process. A processor that evaluates embedded Python code is included. The output of each step is passed as the input to the next step (similar to a Unix pipe). Additionally, the output of each processor step can be cached for a user-specified time period. All configuration is done in XML files that allow you to specify rules based on matching paths against Unix-style wildcard patterns or regular expressions.

Nori is a fork of Maki, which developement has been halted.

Nori provides a simple, flexible framework that allows you to use XML, XSLT, your webserver, and Python to serve web pages. The core nori engine is webserver-neutral. "Adapters" are provided that allow nori to be used in a few different environments, such as FastCGI, Webware, and mod_python. After installing nori, you configure your webserver such that requests for XML files are handled by nori. When nori receives such a request, it determines the path to the file, then searches through its configuration to find the first rule that matches that path. Each rule specifies one or more steps that are to be sequentially applied.

Currently recognized steps are:

  • stylesheet - Apply an XSL stylesheet to the document. nori currently supports 4XSLT (the version from 4Suite), Sablotron (via Sab-pyth), libxslt (via the bundled stylesheet Python bindings or Dave Kuhlman's libxsltmod), and Xalan C++ (via Pyana). You can select which transformer you want to use globally and then override it on a stylesheet basis.
  • process - Run the document through a process (which changes the document in some way). For example, a processor named noriLogic is included which evaluates Python code embedded in the text nodes of the document and dynamically adds text, elements, and/or attributes to the document.
  • write - Write the document out to the HTTP response stream.
  • debug - Write the document out to the log. This is useful when you want to see what the document looks like between two steps.

Two other features are also available: inclusion and caching.

Inclusion

Whenever an XML or XSL file is read, nori searches the document for <nori:include>s. Each such element references an XML file that is to be inserted into the current document - replacing the <nori:include> tag. You may wonder why I opted to create my own inclusion method when others already exists (such as XInclude and xsl:include). By implementing my own inclusion method, nori can both do the inclusion and maintain a tree of file dependencies. That way nori can know when to invalidate the cache. There's nothing stopping you from using other inclusion techniques - just understand that nori's caching system will not be aware of the dependencies. For example, if a file included (via a method other than <nori:include>) by a file included by a document were to change, nori might mistakenly continue to use the cached document.

Caching

To improve speed of content delivery, nori attempts to cache as much as possible. After an XML/XSL document is parsed and inclusion is done, the resulting document is cached. The next time that file is requested, the modification time of the cached file is compared with the modification time of the source file (and the modification times of any dependent files). If the cache file modification time is greater than the modification time of the source file (and all included files), then the cached document is used. Otherwise, the file is re-parsed (along with includes) and cached.

Additionally, the output of each stylesheet step is cached. Now for the tricky part: caching of process output. By default, the output of a process is not cacheable. However, you can specify a cache time for each process step. The cache time may be forever or some number of seconds, minutes, hours, or days. By default, caching takes the query string into account, but ignores cookies and environment variables. However, you can specify at the rule level that specific cookie or environment variables are to be used as part of the cache key. Currently caching is done on the file system instead of in memory. This allows the cache to persist between server restarts and to be shared among multiple processes. It also makes it possible to manually view the cache, and clear or prune it simply by deleting files (perhaps from a cronjob).

Acknowledgements

Nori could not exist without the incredible software it either depends on or interfaces with. I give my sincerest thanks to the creators and maintainers of Python, PyXML, libxml2/libxslt, 4Suite, Sablotron, Xalan, Sab-pyth, libxsltmod, Pyana, Apache, mod_python, FastCGI, fcgi, and Webware. Hope I didn't forget anyone :-) == Why 'nori'? == Nori is based on Maki system. I wanted the name to be somehow related to the base of Nori. I was thinking about 'nigiri', other kind of sushi, but it was too long to use it as XML namespace. Finally, I've decided on 'nori' - sea weeds used to wrap sushi. Here's how Maki's author explained why he named this project 'Maki':

"The name Maki refers to maki-zushi (rolled sushi). Why? It's a cool, short name that isn't already in use by other software. It brings to mind a complex and artistic process with an end result that's beautiful and delicious. Hopefully Maki will help you roll out webpages that are beautiful and useful!"