From 1a7b14de4bc89ef0fd162ef8e62d01926e42b54e Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Thu, 24 Jul 2008 17:14:16 +0000 Subject: Add tutorial sections --- docs/tutorials/lxmlgraph/step03.rst | 175 ++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 docs/tutorials/lxmlgraph/step03.rst (limited to 'docs/tutorials/lxmlgraph/step03.rst') diff --git a/docs/tutorials/lxmlgraph/step03.rst b/docs/tutorials/lxmlgraph/step03.rst new file mode 100644 index 000000000..c7298e41d --- /dev/null +++ b/docs/tutorials/lxmlgraph/step03.rst @@ -0,0 +1,175 @@ +================================================ +Step 03: Basic Rendering With ZPT and XSLT +================================================ + +Our XML-based model is now usable. However, we're using Python to +generate the HTML, instead of a template. In this step, we'll look at +wiring up some templates, using both ZPT and XSLT. + +In a nutshell, this means: + + - Slight changes to the ZCML + + - View functions that assemble information and call the template + +ZPT Templates +======================== + +Let's start with a ZPT-based default view for the nodes in the XML. +The ZCML for this would look like this: + +.. code-block:: xml + + + +Here we point to a function in ``myapp/views.py`` that looks like the +following: + +.. code-block:: python + :linenos: + + from repoze.bfg.template import render_template_to_response + def zpt_default_view(context, request): + fn = "default.pt" + return render_template_to_response(fn, name=context.__name__, node=context) + +This function is relatively simple: + +#. Line 1 imports a ``repoze.bfg`` function that renders ZPT + templates. ``repoze.bfg`` uses the ``z3c.pt`` ZPT engine. + +#. Line 2, like our other view functions, gets passed a ``context`` + (the current hop in the URL) and WebOb ``request`` object. + +#. Line 3 points at the filename of the ZPT. + +#. Line 4 calls the ``render_template_to_response`` function, passing in the + filename for the ZPT and two top-level variables that can be used + in the ZPT. The first is the name of the current URL hop + (context). The second is the XML node object for that hop + (context). + +In Step 01 and 02, we returned a WebOb Response object that we +created. ``render_template_to_response`` makes a Response itself. + +Here's what the ZPT looks like: + +.. literalinclude:: step03/myapp/default.pt + :linenos: + :language: xml + +Look, a template! Life is better with templating: + +#. Lines 1-2 make an ```` node with a namespace for TAL. + +#. Line 5 inserts the value of the ``name`` that we passed into + ``render_template_to_response``. + +#. Line 6 sure looks interesting. It uses the ``node`` that we passed + in via ``render_template_to_response``. Since ``z3c.pt`` uses + Python as its expession language, we can put anything Python-legal + between the braces. And since ``node`` is an lxml Element object, + we just ask for its ``.tag``, like regular Python lxml code. + +Viewing the ZPT +------------------ + +With all of that in place, going to ``http://localhost:5432/a`` now +generates, via the ZPT, the following:: + + My template is viewing item: a + + The node has a tag name of: document. + + +XSLT Templates +==================== + +So that's the ZPT way of rendering HTML for an XML document. How +might XSLT look? + +.. note:: + + For the following, we'll switch back to showing the complete module + code, rather than snippets. You can then follow along by looking at + the files in ``docs/step03/myapp``. + +File ``myapp/configure.zcml`` +-------------------------------- + +The ZCML statement for the XSLT template looks almost exactly the same +as the ZPT template: + +.. literalinclude:: step03/myapp/configure.zcml + :linenos: + :language: xml + +#. Lines 10-14 wire up a new view, in addition to the default view. + +#. Line 13 provides the difference: ``name="xsltview.html"`` means + that all our URLs now can have ``/xsltview.xml`` appended to them. + +In the ZCML, there is no distinction between a ZPT view and an XSLT +view. The difference is only in the function that is pointed to by +the ``view=`` attribute. + + +Module ``myapp/views.py`` +-------------------------------- + +The ZCML says that our XSLT view (``xsltview.html`` on the URL) comes +from the ``myapp.views.xslt_view`` function: + +.. literalinclude:: step03/myapp/views.py + :linenos: + +#. Line 9 starts the Python function which serves as the view for this + template. The function has the same signature as the + ``zpt_default_view`` function we defined for the ZPT template's + view. + +#. Line 10 implements the difference. We call + ``render_transform_to_response`` instead of + ``render_template_to_response``. This tells ``repoze.bfg`` to make + an XSLT processor for this template, instead of a ZPT. The second + argument passes in ``context`` to the XSLT transform. ``context``` + is an instance of an Element node. Namely, a node from the XML + document that corresponds to the current hop in the URL. + + +File ``myapp/xsltview.xsl`` +-------------------------------- + +How different does the XSLT itself look? At this stage, not too different: + +.. literalinclude:: step03/myapp/xsltview.xsl + :linenos: + :language: xml + +#. Lines 1 and 2 are typical XSLT setup. + +#. Line 3 defines a rule to match on the node that is passed in. In + our case, a ```` node. + +#. Line 7 inserts the value of the ``@id`` attribute from the + "current" node at that point in the rule. We're sitting on the + ```` node (thanks to line 3). Thus, ```` inserts ``a`` or ``b``, depending on which + document we are sitting on. + +#. Line 8 shows the element name of the current node. + + +Viewing the XSLT +-------------------- + +With this in place, runnning the application provides a URL such as +``http://localhost:5432/a/xsltview.html``. Going to that URL should +show:: + + My template is viewing item: a + + The node has a name of: document. -- cgit v1.2.3