[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