[Repoze-checkins] r1400 - in repoze.lxmlgraph/trunk/docs: . step00 step01/myapp step02/myapp step03/myapp step04 step04/myapp

Paul Everitt paul at agendaless.com
Sat Jul 19 13:48:48 EDT 2008


Author: Paul Everitt <paul at agendaless.com>
Date: Sat Jul 19 13:48:48 2008
New Revision: 1400

Log:
Get a working implementation of step04 in place.

Added:
   repoze.lxmlgraph/trunk/docs/step04/
   repoze.lxmlgraph/trunk/docs/step04/myapp/
   repoze.lxmlgraph/trunk/docs/step04/myapp/__init__.py
   repoze.lxmlgraph/trunk/docs/step04/myapp/configure.zcml
   repoze.lxmlgraph/trunk/docs/step04/myapp/models.py
   repoze.lxmlgraph/trunk/docs/step04/myapp/samplemodel.xml
   repoze.lxmlgraph/trunk/docs/step04/myapp/views.py
   repoze.lxmlgraph/trunk/docs/step04/myapp/xsltview.xsl
   repoze.lxmlgraph/trunk/docs/step04/run.py
Modified:
   repoze.lxmlgraph/trunk/docs/background.rst
   repoze.lxmlgraph/trunk/docs/index.rst
   repoze.lxmlgraph/trunk/docs/installation.rst
   repoze.lxmlgraph/trunk/docs/step00/simplemodel.xml
   repoze.lxmlgraph/trunk/docs/step01.rst
   repoze.lxmlgraph/trunk/docs/step01/myapp/models.py
   repoze.lxmlgraph/trunk/docs/step02.rst
   repoze.lxmlgraph/trunk/docs/step02/myapp/samplemodel.xml
   repoze.lxmlgraph/trunk/docs/step03/myapp/samplemodel.xml
   repoze.lxmlgraph/trunk/docs/step04.rst

Modified: repoze.lxmlgraph/trunk/docs/background.rst
==============================================================================
--- repoze.lxmlgraph/trunk/docs/background.rst	(original)
+++ repoze.lxmlgraph/trunk/docs/background.rst	Sat Jul 19 13:48:48 2008
@@ -93,9 +93,10 @@
 
 #. **Authorization**.  By hooking up support for an ``__acl__``
    property, I can store ACL information on a single node, on an
-   ancestor, on the root, on the Python class, or any combination
-   thereof.  Additionally, I can wire up the ``__parent__`` attribute
-   as a property that makes an lxml ``node.getparent()`` call.
+   ancestor, on the ``<site>`` root, on the Python class, or any
+   combination thereof.  Additionally, I can wire up the
+   ``__parent__`` attribute as a property that makes an lxml
+   ``node.getparent()`` call.
 
 #. **Multiple views**.  Instead of just having a single default view
    on a node, I can allow other view names, all pointing at the same

Modified: repoze.lxmlgraph/trunk/docs/index.rst
==============================================================================
--- repoze.lxmlgraph/trunk/docs/index.rst	(original)
+++ repoze.lxmlgraph/trunk/docs/index.rst	Sat Jul 19 13:48:48 2008
@@ -18,5 +18,4 @@
    step01
    step02
    step03
-
-
+   step04

Modified: repoze.lxmlgraph/trunk/docs/installation.rst
==============================================================================
--- repoze.lxmlgraph/trunk/docs/installation.rst	(original)
+++ repoze.lxmlgraph/trunk/docs/installation.rst	Sat Jul 19 13:48:48 2008
@@ -5,11 +5,11 @@
 steps along the way, via the miracles of virtualenv, easy_install and Paster
 templates::
 
-  virtualenv --no-site-packages myapp
-  cd myapp
-  source bin/activate
-  easy_install repoze.lxmlgraph
-  paster create -t lxmlgraph_project
+  $ virtualenv --no-site-packages myapp
+  $ cd myapp
+  $ source bin/activate
+  $ easy_install repoze.lxmlgraph
+  $ paster create -t lxmlgraph_project
 
 Answer the questions, then run the demo:
 

Modified: repoze.lxmlgraph/trunk/docs/step00/simplemodel.xml
==============================================================================
--- repoze.lxmlgraph/trunk/docs/step00/simplemodel.xml	(original)
+++ repoze.lxmlgraph/trunk/docs/step00/simplemodel.xml	Sat Jul 19 13:48:48 2008
@@ -1,28 +1,26 @@
 <?xml version="1.0"?>
-<root>
-    <site>
-        <title>My XMLGRAPH Website</title>
-    </site>
-    <folder xml:id="n1" name="folder1">
-        <document xml:id="n11" name="doc1">
-            <title>doc1 in folder1</title>
-            <body>
-                <div xmlns="http://www.w3.org/1999/xhtml">
-                    <p>Welcome to the site.  We have lots to say.</p>
-                    <p>Or, <em>maybe</em> not.</p>
-                </div>
-            </body>
-        </document>
-        <document xml:id="n12" name="doc2">
-            <title>doc2 in folder1</title>
-        </document>
-    </folder>
-    <folder xml:id="n2" name="folder2">
-        <document xml:id="n21" name="doc1">
-            <title>doc1 in folder2</title>
-        </document>
-        <document xml:id="n22" name="doc2">
-            <title>doc2 in folder2</title>
-        </document>
-    </folder>
+<site>
+  <title>My XMLGRAPH Website</title>
+  <folder xml:id="n1" name="folder1">
+    <document xml:id="n11" name="doc1">
+      <title>doc1 in folder1</title>
+      <body>
+        <div xmlns="http://www.w3.org/1999/xhtml">
+          <p>Welcome to the site.  We have lots to say.</p>
+          <p>Or, <em>maybe</em> not.</p>
+        </div>
+      </body>
+    </document>
+    <document xml:id="n12" name="doc2">
+      <title>doc2 in folder1</title>
+    </document>
+  </folder>
+  <folder xml:id="n2" name="folder2">
+    <document xml:id="n21" name="doc1">
+      <title>doc1 in folder2</title>
+    </document>
+    <document xml:id="n22" name="doc2">
+      <title>doc2 in folder2</title>
+    </document>
+  </folder>
 </root>

Modified: repoze.lxmlgraph/trunk/docs/step01.rst
==============================================================================
--- repoze.lxmlgraph/trunk/docs/step01.rst	(original)
+++ repoze.lxmlgraph/trunk/docs/step01.rst	Sat Jul 19 13:48:48 2008
@@ -61,7 +61,7 @@
    :linenos:
    :language: xml
 
-#. Lines 1-3 provide the root element and namespaces for the
+#. Lines 1-3 provide the root node and namespaces for the
    configuration language.  ``bfg`` is the namespace for
    ``repoze.bfg``-specific configuration directives.
 

Modified: repoze.lxmlgraph/trunk/docs/step01/myapp/models.py
==============================================================================
--- repoze.lxmlgraph/trunk/docs/step01/myapp/models.py	(original)
+++ repoze.lxmlgraph/trunk/docs/step01/myapp/models.py	Sat Jul 19 13:48:48 2008
@@ -10,7 +10,7 @@
     def __init__(self, name):
         self.__name__ = name
 
-root = MyModel('root')
+root = MyModel('site')
 root['a'] = MyModel('a')
 root['b'] = MyModel('b')
 

Modified: repoze.lxmlgraph/trunk/docs/step02.rst
==============================================================================
--- repoze.lxmlgraph/trunk/docs/step02.rst	(original)
+++ repoze.lxmlgraph/trunk/docs/step02.rst	Sat Jul 19 13:48:48 2008
@@ -32,13 +32,14 @@
    :linenos:
    :language: xml
 
-#. Line 2 provides the root of the model as an XML ``<root>`` node.
-   The element name doesn't have to be ``<root>``.
+#. Line 2 provides the root of the model as an XML ``<site>`` node.
+   The element name doesn't have to be ``<site>``.
 
-#. In lines 3-4, the root contains 2 top-level children: a and b.
-   These are provided as an element name ``<document>``.  This, also,
-   is meaningfless as far as ``repoze.bfg`` is concerned.  However,
-   this is where you compose th information model you are publishing.
+#. In lines 3-4, the ``<site>`` contains 2 top-level children: a and
+   b.  These are provided as an element name ``<document>``.  This,
+   also, is meaningfless as far as ``repoze.bfg`` is concerned.
+   However, this is where you compose th information model you are
+   publishing.
 
 The only special constraint is that a node that wants to be "found" by
 ``repoze.bfg`` in during traversal *must* have an ``name`` attribute.

Modified: repoze.lxmlgraph/trunk/docs/step02/myapp/samplemodel.xml
==============================================================================
--- repoze.lxmlgraph/trunk/docs/step02/myapp/samplemodel.xml	(original)
+++ repoze.lxmlgraph/trunk/docs/step02/myapp/samplemodel.xml	Sat Jul 19 13:48:48 2008
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<root>
+<site>
     <document name="a"/>
     <document name="b"/>
-</root>
+</site>

Modified: repoze.lxmlgraph/trunk/docs/step03/myapp/samplemodel.xml
==============================================================================
--- repoze.lxmlgraph/trunk/docs/step03/myapp/samplemodel.xml	(original)
+++ repoze.lxmlgraph/trunk/docs/step03/myapp/samplemodel.xml	Sat Jul 19 13:48:48 2008
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<root>
+<site>
     <document name="a"/>
     <document name="b"/>
-</root>
+</site>

Modified: repoze.lxmlgraph/trunk/docs/step04.rst
==============================================================================
--- repoze.lxmlgraph/trunk/docs/step04.rst	(original)
+++ repoze.lxmlgraph/trunk/docs/step04.rst	Sat Jul 19 13:48:48 2008
@@ -2,9 +2,33 @@
 Step 04: Hierarchical Rendering With XSLT
 ================================================
 
+Now that we have basic templating for our XML graph in place, let's
+start doing some fun stuff with it.  As we walk through use cases and
+build out patterns for implementing them, we'll get to leverage some
+features available in XML processors.  For better or worse. [wink]
 
-- hierarchical XML
+In this step we take a look at the following:
 
-- xml:id and friends
+- Hierarchical XML, to build a nested, folder-like site structure
 
-- multiple "views" wired to the same function and template
\ No newline at end of file
+- Improving performance in that case through the use of the ``xml:id`` standard
+
+- Different element names (``<folder>``, ``<document>``, etc.) in our
+  XML, along with "rules" in the template to handle them
+
+- A template model that performs the "theme" work common to all pages,
+  then performs the "unique to this page" work
+
+Pre-Flight Cleanup
+====================
+
+In the last example, we had a default template that used ZPT.  We're
+shifting the rest of the steps over to XSLT.  Thus, our
+``myapp/configure.zcml`` is now simpler:
+
+.. literalinclude:: step04/myapp/configure.zcml
+   :linenos:
+   :language: xml
+
+We also remove the ZPT view function from ``views.py``, as we'll see
+in a moment.
\ No newline at end of file

Added: repoze.lxmlgraph/trunk/docs/step04/myapp/__init__.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04/myapp/__init__.py	Sat Jul 19 13:48:48 2008
@@ -0,0 +1 @@
+#

Added: repoze.lxmlgraph/trunk/docs/step04/myapp/configure.zcml
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04/myapp/configure.zcml	Sat Jul 19 13:48:48 2008
@@ -0,0 +1,11 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+	   xmlns:bfg="http://namespaces.repoze.org/bfg">
+
+  <include package="repoze.bfg" />
+
+  <bfg:view
+     for=".models.IMyModel"
+     view=".views.xslt_view"
+     />
+
+</configure>

Added: repoze.lxmlgraph/trunk/docs/step04/myapp/models.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04/myapp/models.py	Sat Jul 19 13:48:48 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("@name")[0]
+
+    def __getitem__(self, child_name):
+        xp = "*[@name='%s']" % child_name
+        matches = self.xpath(xp)
+        if len(matches) == 0:
+            raise KeyError('No child found for %s' % child_name)
+        elif len(matches) > 1:
+            raise KeyError('More than one child for %s' % child_name)
+        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/step04/myapp/samplemodel.xml
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04/myapp/samplemodel.xml	Sat Jul 19 13:48:48 2008
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<site>
+    <title>My XMLGRAPH Website</title>
+    <document xml:id="index" name="index.html">
+        <title>Site Home Page</title>
+        <body>
+            <div xmlns="http://www.w3.org/1999/xhtml">
+                <p>Welcome to the site. We have lots to say.</p>
+                <p>Or, <em>maybe</em> not.</p>
+            </div>
+        </body>
+    </document>
+    <folder xml:id="n1" name="folder1">
+        <title>Folder One</title>
+        <document xml:id="n11" name="doc1">
+            <title>doc1 in folder1</title>
+            <body>
+                <div xmlns="http://www.w3.org/1999/xhtml">
+                    <p>I am in an HTML <code>div</code> so I can do <strong>LOTS</strong> of
+                        formatting.</p>
+                </div>
+            </body>
+        </document>
+        <document xml:id="n12" name="doc2">
+            <title>doc2 in folder1</title>
+            <body>
+                <div xmlns="http://www.w3.org/1999/xhtml">
+                    <p>Keep this on one line.</p>
+                </div>
+            </body>
+        </document>
+    </folder>
+    <folder xml:id="n2" name="folder2">
+        <title>The Second Folder</title>
+        <document xml:id="n21" name="doc1">
+            <title>doc1 in folder2</title>
+            <body>
+                <div xmlns="http://www.w3.org/1999/xhtml">
+                    <p>This is a special folder. It's folder 2!</p>
+                </div>
+            </body>
+        </document>
+    </folder>
+</site>

Added: repoze.lxmlgraph/trunk/docs/step04/myapp/views.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04/myapp/views.py	Sat Jul 19 13:48:48 2008
@@ -0,0 +1,13 @@
+from repoze.bfg.template import render_transform_to_response
+
+# Some constants
+XML_NAMESPACE='http://www.w3.org/XML/1998/namespace'
+XML_PREFIX= '{%s}' % XML_NAMESPACE
+
+def xslt_view(context, request):
+    # Grab the root of the tree, which should be a <site>
+    site = context.getroottree().getroot()
+    # Jot down which node we're sitting on as the <context>
+    contextid = "'%s'" % context.get(XML_PREFIX+'id')
+    return render_transform_to_response("xsltview.xsl", site, 
+                                        contextid=contextid)

Added: repoze.lxmlgraph/trunk/docs/step04/myapp/xsltview.xsl
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04/myapp/xsltview.xsl	Sat Jul 19 13:48:48 2008
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+    <xsl:param name="contextid">n1</xsl:param>
+    <xsl:variable name="contextnode" select="id($contextid)"/>
+    <xsl:template match="/">
+        <html>
+            <head>
+                <title>
+                    <xsl:value-of select="$contextnode/title"/>
+                </title>
+            </head>
+            <body>
+                <h2>
+                    <xsl:value-of select="$contextnode/title"/>
+                </h2>
+                <xsl:apply-templates select="$contextnode"/>
+                <table border="1" cellpadding="6" cellspacing="0">
+                    <tr>
+                        <th>Type</th>
+                        <th>@xml:id</th>
+                        <th>@name</th>
+                        <th>Parent Type</th>
+                        <th>Parent @name</th>
+                    </tr>
+                    <tr>
+                        <td>
+                            <xsl:value-of select="name($contextnode)"/>
+                        </td>
+                        <td>
+                            <xsl:value-of select="$contextnode/@xml:id"/>
+                        </td>
+                        <td>
+                            <xsl:value-of select="$contextnode/@name"/>
+                        </td>
+                        <td>
+                            <xsl:value-of select="name($contextnode/..)"/>
+                        </td>
+                        <td>
+                            <xsl:value-of select="$contextnode/../@name"/>
+                        </td>
+                    </tr>
+                </table>
+            </body>
+        </html>
+    </xsl:template>
+    <xsl:template match="folder">
+        <p>
+            <em>Folders are special, they contain things.</em>
+        </p>
+        <xsl:if test="*[@xml:id]">
+            <h2>Folder Contents</h2>
+            <ul>
+                <xsl:for-each select="*[@xml:id]">
+                    <li>
+                        <a href="{../@name}/{@name}">
+                            <xsl:value-of select="title"/>
+                        </a>
+                    </li>
+                </xsl:for-each>
+            </ul>
+        </xsl:if>
+    </xsl:template>
+    <xsl:template match="document">
+        <p>
+            <em>Documents contain text.</em>
+        </p>
+        <xsl:copy-of select="body/*"/>
+    </xsl:template>
+</xsl:stylesheet>

Added: repoze.lxmlgraph/trunk/docs/step04/run.py
==============================================================================
--- (empty file)
+++ repoze.lxmlgraph/trunk/docs/step04/run.py	Sat Jul 19 13:48:48 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')


More information about the Repoze-checkins mailing list