[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