[Repoze-checkins] r1384 - in repoze.lxmlgraph/trunk/docs: . step03 step03/myapp
Paul Everitt
paul at agendaless.com
Fri Jul 18 18:34:54 EDT 2008
Author: Paul Everitt <paul at agendaless.com>
Date: Fri Jul 18 18:34:54 2008
New Revision: 1384
Log:
Step 03 nearly done, bout time for dinner.
Added:
repoze.lxmlgraph/trunk/docs/step03/
repoze.lxmlgraph/trunk/docs/step03.rst
repoze.lxmlgraph/trunk/docs/step03/myapp/
repoze.lxmlgraph/trunk/docs/step03/myapp/__init__.py
repoze.lxmlgraph/trunk/docs/step03/myapp/configure.zcml
repoze.lxmlgraph/trunk/docs/step03/myapp/default.pt
repoze.lxmlgraph/trunk/docs/step03/myapp/models.py
repoze.lxmlgraph/trunk/docs/step03/myapp/samplemodel.xml
repoze.lxmlgraph/trunk/docs/step03/myapp/views.py
repoze.lxmlgraph/trunk/docs/step03/myapp/xsltview.xsl
repoze.lxmlgraph/trunk/docs/step03/run.py
repoze.lxmlgraph/trunk/docs/step04.rst
Added: repoze.lxmlgraph/trunk/docs/step03.rst
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03.rst Fri Jul 18 18:34:54 2008
@@ -0,0 +1,99 @@
+================================================
+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
+
+ <bfg:view
+ for=".models.IMyModel"
+ factory=".views.zpt_default_view"
+ />
+
+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
+ def zpt_default_view(context, request):
+ fn = "default.pt"
+ return render_template(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`` 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`` 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 ``<html>`` node with a namespace for TAL.
+
+#. Line 5 inserts the value of the ``name`` that we passed into
+ ``render_template``.
+
+#. Line 6 sure looks interesting. It uses the ``node`` that we passed
+ in via ``render_template. 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.
+
+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``
+--------------------------------
+
Added: repoze.lxmlgraph/trunk/docs/step03/myapp/__init__.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/__init__.py Fri Jul 18 18:34:54 2008
@@ -0,0 +1 @@
+#
Added: repoze.lxmlgraph/trunk/docs/step03/myapp/configure.zcml
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/configure.zcml Fri Jul 18 18:34:54 2008
@@ -0,0 +1,17 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:bfg="http://namespaces.repoze.org/bfg">
+
+ <include package="repoze.bfg" />
+
+ <bfg:view
+ for=".models.IMyModel"
+ factory=".views.zpt_default_view"
+ />
+
+ <bfg:view
+ for=".models.IMyModel"
+ factory=".views.xslt_view"
+ name="xsltview.html"
+ />
+
+</configure>
Added: repoze.lxmlgraph/trunk/docs/step03/myapp/default.pt
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/default.pt Fri Jul 18 18:34:54 2008
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
+ <head></head>
+ <body>
+ <h1>My template is viewing item: ${name}</h1>
+ <p>The node has a tag name of: ${node.tag}.</p>
+ </body>
+</html>
Added: repoze.lxmlgraph/trunk/docs/step03/myapp/models.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/models.py Fri Jul 18 18:34:54 2008
@@ -0,0 +1,41 @@
+from zope.interface import implements
+from zope.interface import Attribute
+from zope.interface import Interface
+from lxml import etree
+
+class IMyModel(Interface):
+ __name__ = Attribute('Name of the model instance')
+
+class BfgElement(etree.ElementBase):
+ """Handle access control and getitem behavior"""
+
+ implements(IMyModel)
+
+ @property
+ def __name__(self):
+ return self.xpath("@id")[0]
+
+ def __getitem__(self, item_id):
+ xp = "*[@id='%s']" % item_id
+ matches = self.xpath(xp)
+ if len(matches) == 0:
+ raise KeyError('No child found for %s' % item_id)
+ elif len(matches) > 1:
+ raise KeyError('More than one child for %s' % item_id)
+ else:
+ return matches[0]
+
+def get_root(environ):
+ # Setup the custom parser with our BfgElement behavior
+ parser_lookup = etree.ElementDefaultClassLookup(element=BfgElement)
+ parser = etree.XMLParser()
+ parser.set_element_class_lookup(parser_lookup)
+
+ # Now load the XML file
+ xmlstring = open("myapp/samplemodel.xml").read()
+ root = etree.XML(xmlstring, parser)
+
+ return root
+
+
+
Added: repoze.lxmlgraph/trunk/docs/step03/myapp/samplemodel.xml
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/samplemodel.xml Fri Jul 18 18:34:54 2008
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <document id="a"/>
+ <document id="b"/>
+</root>
Added: repoze.lxmlgraph/trunk/docs/step03/myapp/views.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/views.py Fri Jul 18 18:34:54 2008
@@ -0,0 +1,10 @@
+from repoze.bfg.template import render_template
+from repoze.bfg.template import render_transform
+
+def zpt_default_view(context, request):
+ fn = "default.pt"
+ return render_template(fn, name=context.__name__, node=context)
+
+def xslt_view(context, request):
+ print "context is", context
+ return render_transform("xsltview.xsl", context)
Added: repoze.lxmlgraph/trunk/docs/step03/myapp/xsltview.xsl
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/xsltview.xsl Fri Jul 18 18:34:54 2008
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:template match="/">
+ <html>
+ <head/>
+ <body>
+ <h1>My template is viewing item: <xsl:value-of select="@id"/></h1>
+ <p>The node has a name of: <xsl:value-of select="name(../*)"/>.x</p>
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
Added: repoze.lxmlgraph/trunk/docs/step03/run.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step03/run.py Fri Jul 18 18:34:54 2008
@@ -0,0 +1,8 @@
+from paste import httpserver
+
+from repoze.bfg import make_app
+from myapp.models import get_root
+import myapp
+
+app = make_app(get_root, myapp)
+httpserver.serve(app, host='0.0.0.0', port='5432')
Added: repoze.lxmlgraph/trunk/docs/step04.rst
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04.rst Fri Jul 18 18:34:54 2008
@@ -0,0 +1,10 @@
+================================================
+Step 04: Hierarchical Rendering With XSLT
+================================================
+
+
+- hierarchical XML
+
+- xml:id and friends
+
+- multiple "views" wired to the same function and template
\ No newline at end of file
More information about the Repoze-checkins
mailing list