summaryrefslogtreecommitdiff
path: root/docs/tutorials
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-05-01 10:26:57 +0000
committerChris McDonough <chrism@agendaless.com>2009-05-01 10:26:57 +0000
commitba9b0e647bff1bf0c437ab204ddf11783ed698f8 (patch)
tree1952ebfdc40ae71a3bc54eb10a92a0fe1e8273ec /docs/tutorials
parentbc0698e1ac67106346d8c006bddcb38370f7c16b (diff)
downloadpyramid-ba9b0e647bff1bf0c437ab204ddf11783ed698f8.tar.gz
pyramid-ba9b0e647bff1bf0c437ab204ddf11783ed698f8.tar.bz2
pyramid-ba9b0e647bff1bf0c437ab204ddf11783ed698f8.zip
Merge "c-free" branch to trunk.
Diffstat (limited to 'docs/tutorials')
-rw-r--r--docs/tutorials/lxmlgraph/NOTES.txt6
-rw-r--r--docs/tutorials/lxmlgraph/background.rst83
-rw-r--r--docs/tutorials/lxmlgraph/index.rst17
-rw-r--r--docs/tutorials/lxmlgraph/step00/simplemodel.xml26
-rw-r--r--docs/tutorials/lxmlgraph/step01.rst24
-rw-r--r--docs/tutorials/lxmlgraph/step01/myapp/__init__.py1
-rw-r--r--docs/tutorials/lxmlgraph/step01/myapp/configure.zcml12
-rw-r--r--docs/tutorials/lxmlgraph/step01/myapp/models.py18
-rw-r--r--docs/tutorials/lxmlgraph/step01/myapp/views.py7
-rw-r--r--docs/tutorials/lxmlgraph/step01/run.py8
-rw-r--r--docs/tutorials/lxmlgraph/step02.rst132
-rw-r--r--docs/tutorials/lxmlgraph/step02/myapp/__init__.py1
-rw-r--r--docs/tutorials/lxmlgraph/step02/myapp/configure.zcml10
-rw-r--r--docs/tutorials/lxmlgraph/step02/myapp/models.py42
-rw-r--r--docs/tutorials/lxmlgraph/step02/myapp/samplemodel.xml5
-rw-r--r--docs/tutorials/lxmlgraph/step02/myapp/views.py8
-rw-r--r--docs/tutorials/lxmlgraph/step02/run.py8
-rw-r--r--docs/tutorials/lxmlgraph/step03.rst209
-rw-r--r--docs/tutorials/lxmlgraph/step03/myapp/__init__.py1
-rw-r--r--docs/tutorials/lxmlgraph/step03/myapp/configure.zcml16
-rw-r--r--docs/tutorials/lxmlgraph/step03/myapp/models.py42
-rw-r--r--docs/tutorials/lxmlgraph/step03/myapp/samplemodel.xml5
-rw-r--r--docs/tutorials/lxmlgraph/step03/myapp/templates/default.pt8
-rw-r--r--docs/tutorials/lxmlgraph/step03/myapp/templates/xsltview.xsl12
-rw-r--r--docs/tutorials/lxmlgraph/step03/myapp/views.py10
-rw-r--r--docs/tutorials/lxmlgraph/step04.rst250
-rw-r--r--docs/tutorials/lxmlgraph/step04/myapp/__init__.py1
-rw-r--r--docs/tutorials/lxmlgraph/step04/myapp/configure.zcml10
-rw-r--r--docs/tutorials/lxmlgraph/step04/myapp/models.py45
-rw-r--r--docs/tutorials/lxmlgraph/step04/myapp/samplemodel.xml44
-rw-r--r--docs/tutorials/lxmlgraph/step04/myapp/views.py13
-rw-r--r--docs/tutorials/lxmlgraph/step04/myapp/xsltview.xsl69
-rw-r--r--docs/tutorials/lxmlgraph/step04/run.py8
-rw-r--r--docs/tutorials/lxmlgraph/step05.rst11
34 files changed, 0 insertions, 1162 deletions
diff --git a/docs/tutorials/lxmlgraph/NOTES.txt b/docs/tutorials/lxmlgraph/NOTES.txt
deleted file mode 100644
index 60b4b9f55..000000000
--- a/docs/tutorials/lxmlgraph/NOTES.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-
-To Do
-------------
-
-- Dream up a ZPT/XSLT theme engine
-
diff --git a/docs/tutorials/lxmlgraph/background.rst b/docs/tutorials/lxmlgraph/background.rst
deleted file mode 100644
index aec4cda26..000000000
--- a/docs/tutorials/lxmlgraph/background.rst
+++ /dev/null
@@ -1,83 +0,0 @@
-Background
-====================
-
-In this demo application, we build up, bit-by-bit, the functionality
-for a website based on a single XML document. You don't have to know
-much about XML to follow along. In fact, the real purpose of this
-demo app is to teach its author how to use the stack
-(:mod:`repoze.bfg`, ``paster``, eggs, etc.)
-
-.. warning::
-
- If you dislike XML and related technologies such as XPath and XSLT,
- you'll thoroughly detest this sample application. Just to be
- stupendously clear, :mod:`repoze.bfg` is in no way dependent on XML.
- On the other hand, :mod:`repoze.bfg` happens to make XML publishing
- kinda fun.
-
-In summary:
-
- - Represent a hierarchical website as an XML document
-
- - Inject :mod:`repoze.bfg` semantics into elements using
- :term:`lxml`
-
- - Support rendering with :term:`XSLT`
-
-What It Does
--------------------
-
-Imagine you have a website that looks like this::
-
- /
- folder1/
- doc1
- doc2
- image1
- folder2/
- doc2
-
-Meaning, a heterogenous, nested folder structure, just like your hard
-drive. (Unless you're one of those folks that uses your Windows
-Desktop as a flat filing system.) How might I get that information
-into a website?
-
-Using :mod:`repoze.bfg`, of course. More specifically, with an XML file
-that models that hierarchy:
-
-.. literalinclude:: step00/simplemodel.xml
- :language: xml
-
-How It Works
--------------------
-
-To coerce :mod:`repoze.bfg` into publishing this model, I just need to
-sprinkle in some Python behavior. For example, :mod:`repoze.bfg` uses
-``__getitem__`` to traverse the model. I need my XML data to support
-this method. Moreover, I want some specific behavior: run an XPath
-express on the node to get the child with the ``@name`` attribute
-matching the URL hop.
-
-Fortunately :term:`lxml` makes this easy. I can inject my nodes with a
-class that I write, thus providing my own ``__getitem__`` behavior.
-
-That class can also assert that my XML nodes provide an interface.
-The interface then lets me glue back into the standard :mod:`repoze.bfg`
-machinery, such as associating views and permissions into the model.
-
-Next up, I need to provide views for the elements in the model. I
-could, for example, use ZPT and manipulate the XML data using Python
-expressions against the :term:`lxml` API. Or, I could use XSLT.
-
-For the latter, I could register a different XSLT for every "view" on
-every interface. Or, I could write one big XSLT, and let its template
-matching machinery decide who to render in a certain context.
-
-And finally, I could pass in just a single node and render it, or pass
-in the entire tree with a parameter identifying the context node.
-
-In the course of this writeup, we'll build ``repoze.lxmlgraph``
-step-by-step, starting with no XML. Each of those decisions will be
-analyzed an implemented. At the end, you'll see both the resulting
-demo application, plus the thought process that went along with it.
-
diff --git a/docs/tutorials/lxmlgraph/index.rst b/docs/tutorials/lxmlgraph/index.rst
deleted file mode 100644
index cc79f7e73..000000000
--- a/docs/tutorials/lxmlgraph/index.rst
+++ /dev/null
@@ -1,17 +0,0 @@
-``lxmlgraph``: Publishing An XML Tree with :mod:`repoze.bfg`
-============================================================
-
-Hierarchical websites are easy to develop with :mod:`repoze.bfg`.
-That hierarchy doesn't need to be defined by any particular sort of
-graph or databsase system. To demonstrate this, we present
-``repoze.lxmlgraph``, a demo application for :mod:`repoze.bfg` that
-describes publishing an XML document as a hierarchical website.
-
-.. toctree::
- :maxdepth: 2
-
- background
- step01
- step02
- step03
- step04
diff --git a/docs/tutorials/lxmlgraph/step00/simplemodel.xml b/docs/tutorials/lxmlgraph/step00/simplemodel.xml
deleted file mode 100644
index 7dbc53951..000000000
--- a/docs/tutorials/lxmlgraph/step00/simplemodel.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0"?>
-<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>
diff --git a/docs/tutorials/lxmlgraph/step01.rst b/docs/tutorials/lxmlgraph/step01.rst
deleted file mode 100644
index 578f13608..000000000
--- a/docs/tutorials/lxmlgraph/step01.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-=======================
-Step 1: Getting Started
-=======================
-
-To get started, using the ``paster`` command from a :term:`virtualenv`
-you've created that has :mod:`repoze.bfg` installed, run ``paster
-create -t bfg`` as described in :ref:`project_narr` to create your
-``lxmlgraph`` project::
-
- $ paster create -t bfg Selected and implied templates: repoze.bfg#bfg
- repoze.bfg starter project
-
- Enter project name: lxmlgraph
- ...
- $
-
-You now have a project named ``lxmlgraph`` in your current directory.
-We'll add to this project in subsequent steps.
-
-To get your project ready for development and execution, use the
-``setup.py develop`` command within the same virtualenv as bfg is
-installed as documented in :ref:`project_narr` . You'll need to do
-this in order to run the ``lxmlgraph`` application in subsequent
-steps.
diff --git a/docs/tutorials/lxmlgraph/step01/myapp/__init__.py b/docs/tutorials/lxmlgraph/step01/myapp/__init__.py
deleted file mode 100644
index 792d60054..000000000
--- a/docs/tutorials/lxmlgraph/step01/myapp/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/docs/tutorials/lxmlgraph/step01/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step01/myapp/configure.zcml
deleted file mode 100644
index e06023c24..000000000
--- a/docs/tutorials/lxmlgraph/step01/myapp/configure.zcml
+++ /dev/null
@@ -1,12 +0,0 @@
-<configure xmlns="http://namespaces.repoze.org/bfg">
-
- <!-- this must be included for the view declarations to work -->
- <include package="repoze.bfg.includes" />
-
- <!-- the default view for a MyModel -->
- <view
- for=".models.IMyModel"
- view=".views.my_hello_view"
- />
-
-</configure>
diff --git a/docs/tutorials/lxmlgraph/step01/myapp/models.py b/docs/tutorials/lxmlgraph/step01/myapp/models.py
deleted file mode 100644
index 85d603d80..000000000
--- a/docs/tutorials/lxmlgraph/step01/myapp/models.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from zope.interface import implements
-from zope.interface import Attribute
-from zope.interface import Interface
-
-class IMyModel(Interface):
- __name__ = Attribute('Name of the model instance')
-
-class MyModel(dict):
- implements(IMyModel)
- def __init__(self, name):
- self.__name__ = name
-
-root = MyModel('site')
-root['a'] = MyModel('a')
-root['b'] = MyModel('b')
-
-def get_root(environ):
- return root
diff --git a/docs/tutorials/lxmlgraph/step01/myapp/views.py b/docs/tutorials/lxmlgraph/step01/myapp/views.py
deleted file mode 100644
index 13de3ae31..000000000
--- a/docs/tutorials/lxmlgraph/step01/myapp/views.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from webob import Response
-
-def my_hello_view(context, request):
- response = Response('Hello from %s @ %s' % (
- context.__name__,
- request.environ['PATH_INFO']))
- return response
diff --git a/docs/tutorials/lxmlgraph/step01/run.py b/docs/tutorials/lxmlgraph/step01/run.py
deleted file mode 100644
index 1eac209dc..000000000
--- a/docs/tutorials/lxmlgraph/step01/run.py
+++ /dev/null
@@ -1,8 +0,0 @@
-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')
diff --git a/docs/tutorials/lxmlgraph/step02.rst b/docs/tutorials/lxmlgraph/step02.rst
deleted file mode 100644
index 1dc1ebcd3..000000000
--- a/docs/tutorials/lxmlgraph/step02.rst
+++ /dev/null
@@ -1,132 +0,0 @@
-================================================
-Step 2: Hello World as XML
-================================================
-
-We now have a project named ``lxmlgraph``. It contains a *package*
-(also) named ``lxmlgraph``.
-
-In this step we will add an XML document to the *package* as our model
-data. We will leverage the following :mod:`repoze.bfg` machinery:
-
- - Model data with interfaces that define "types"
-
- - ZCML configuration to provide type-specific views
-
-Our application will need to do these things:
-
- - Use :term:`lxml` Element classes to inject :mod:`repoze.bfg`
- behavior into ``lxml`` nodes
-
- - That model class needs to implement the :mod:`repoze.bfg`
- publishing contract
-
-All of the below filenames are relative to the ``lxmlgraph`` *package*
-rather than the *project*.
-
-``samplemodel.xml``
------------------------------------
-
-We're going to add an XML document that will serve as a source for
-model data named ``samplemodel.xml``. Put the content of this file in
-your package:
-
-.. literalinclude:: step02/myapp/samplemodel.xml
- :linenos:
- :language: xml
-
-#. Line 2 provides the root of the model as an XML ``<site>`` node.
- The element name doesn't have to be ``<site>``. It has a name of
- ``site``.
-
-#. 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 meaningless as far as :mod:`repoze.bfg` is concerned.
- However, this is where you compose the information model you are
- publishing.
-
-The only special constraint is that an XML node that wants to be
-"found" by :mod:`repoze.bfg` in during traversal *must* have a
-``name`` attribute. (The use of ``@name`` corresponds to ``__name__``
-in the :mod:`repoze.bfg` sense of :term:`location` ). Each hop in the
-URL tries to grab a child with an attribute matching the next hop.
-Also, the value of the ``@name`` should be unique in its containing
-node.
-
-Module ``models.py``
-------------------------------
-
-At a high level, we make write a class that "extends" ``lxml``
-``Element`` nodes, create an ``lxml`` parser, and register the custom
-class with the parser. Replace the contents of the autogenerated
-``models.py`` with the content we show below.
-
-.. literalinclude:: step02/myapp/models.py
- :linenos:
-
-#. Line 4 imports :term:`lxml`.
-
-#. Line 9 creates the custom class we are going to use to extend
- etree.ElementBase. The `<lxml website
- <http://codespeak.net/lxml/>`_ has great documentation on the
- various ways to inject custom Python behavior into XML.
-
-#. Just as before, line 12 says that instances of this class support a
- certain content type (interface.) In our case, instances will be
- XML nodes.
-
-#. :mod:`repoze.bfg` has a protocol where model data should have an
- ``__name__`` attribute. Lines 14-16 implement this by grabbing the
- ``@name`` attribute of the current node.
-
-#. URL traversal in :mod:`repoze.bfg` works via the ``__getitem__``
- protocol. Thus, we need a method that implements this. Lines
- 18-26 use XPath to look for a direct child that has an ``@name``
- matching the item name that's being traversed to. If it finds it,
- return it. If not, or if more than one is found, raise an error.
-
-#. As before, ``get_root`` is the function that is expected to return
- the top of the model. In lines 30+ we do the :term:`lxml` magic to
- get the custom Python class registered. We then load some XML and
- return the top of the tree.
-
-Module ``views.py``
------------------------------
-
-Replace the autogenerated ``views.py`` code in the ``lxmlgraph``
-package with the following:
-
-.. literalinclude:: step02/myapp/views.py
- :linenos:
-
-Here's what that file does:
-
-#. Line 5 grabs the element name (tag name) of the ``context``, which
- is the current XML node that we're traversing through.
-
-#. Line 6 uses the special property we defined in our custom Python
- class to get the ``__name__`` of the context.
-
-We don't need to change the ``configure.zcml`` because the
-autogenerated one is still correct for this configuration. It
-includes:
-
-.. literalinclude:: step02/myapp/configure.zcml
- :linenos:
- :language: xml
-
-Browsing the Model
-------------------------
-
-We're done changing code. Start the application by executing ``paster
-serve lxmlgraph.ini`` (the ``.ini`` file is in the project directory).
-It will listen on port 5432. We can use these URLs to browse the
-model graph and see results::
-
- http://localhost:5432/a (Hello to document from a @ /a)
-
- http://localhost:5432/b (Hello to document from b @ /b)
-
- http://localhost:5432/c (Not Found)
-
-In this case, each request grabs a node in the XML and uses it as the
-data for the view.
diff --git a/docs/tutorials/lxmlgraph/step02/myapp/__init__.py b/docs/tutorials/lxmlgraph/step02/myapp/__init__.py
deleted file mode 100644
index 792d60054..000000000
--- a/docs/tutorials/lxmlgraph/step02/myapp/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/docs/tutorials/lxmlgraph/step02/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step02/myapp/configure.zcml
deleted file mode 100644
index 2414ae6b2..000000000
--- a/docs/tutorials/lxmlgraph/step02/myapp/configure.zcml
+++ /dev/null
@@ -1,10 +0,0 @@
-<configure xmlns="http://namespaces.repoze.org/bfg">
-
- <include package="repoze.bfg.includes" />
-
- <view
- for=".models.IMyModel"
- view=".views.my_view"
- />
-
-</configure>
diff --git a/docs/tutorials/lxmlgraph/step02/myapp/models.py b/docs/tutorials/lxmlgraph/step02/myapp/models.py
deleted file mode 100644
index 1d93ccdd0..000000000
--- a/docs/tutorials/lxmlgraph/step02/myapp/models.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import os
-
-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
- here = os.path.join(os.path.dirname(__file__))
- samplemodel = os.path.join(here, 'samplemodel.xml')
- xmlstring = open(samplemodel).read()
- root = etree.XML(xmlstring, parser)
-
- return root
diff --git a/docs/tutorials/lxmlgraph/step02/myapp/samplemodel.xml b/docs/tutorials/lxmlgraph/step02/myapp/samplemodel.xml
deleted file mode 100644
index bbe474c63..000000000
--- a/docs/tutorials/lxmlgraph/step02/myapp/samplemodel.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<site name="site">
- <document name="a"/>
- <document name="b"/>
-</site>
diff --git a/docs/tutorials/lxmlgraph/step02/myapp/views.py b/docs/tutorials/lxmlgraph/step02/myapp/views.py
deleted file mode 100644
index 75e390efb..000000000
--- a/docs/tutorials/lxmlgraph/step02/myapp/views.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from webob import Response
-
-def my_view(context, request):
- response = Response('Hello to %s from %s @ %s' % (
- context.tag,
- context.__name__,
- request.environ['PATH_INFO']))
- return response
diff --git a/docs/tutorials/lxmlgraph/step02/run.py b/docs/tutorials/lxmlgraph/step02/run.py
deleted file mode 100644
index 1eac209dc..000000000
--- a/docs/tutorials/lxmlgraph/step02/run.py
+++ /dev/null
@@ -1,8 +0,0 @@
-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')
diff --git a/docs/tutorials/lxmlgraph/step03.rst b/docs/tutorials/lxmlgraph/step03.rst
deleted file mode 100644
index ce88b78c8..000000000
--- a/docs/tutorials/lxmlgraph/step03.rst
+++ /dev/null
@@ -1,209 +0,0 @@
-================================================
-Step 3: 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.
-Change your project's ``configure.zcml`` so that it looks like this:
-
-.. code-block:: xml
-
- <configure xmlns="http://namespaces.repoze.org/bfg">
-
- <!-- this must be included for the view declarations to work -->
- <include package="repoze.bfg.includes" />
-
- <view
- for=".models.IMyModel"
- view=".views.zpt_view"
- />
-
- </configure>
-
-In other words, replace the default view function with
-``.views.zpt_view``. This view stanza indicates that the *default
-view* for a model that implements ``lxmlgraph.models.IMyModel`` should
-be the ``lxmlgraph.views.zpt_view`` function. It is the *default*
-view because this stanza does not have a ``name`` attribute.
-
-Additonally, add a template to your project's ``templates`` directory
-named ``default.pt`` with this content:
-
-.. literalinclude:: step03/myapp/templates/default.pt
- :linenos:
- :language: xml
-
-Also add a function in ``views.py`` that looks like the following:
-
-.. code-block:: python
- :linenos:
-
- from repoze.bfg.chameleon_zpt import render_template_to_response
- def zpt_view(context, request):
- return render_template_to_response('templates/default.pt',
- name=context.__name__,
- node=context)
-
-This function is relatively simple:
-
-#. Line 1 imports a :mod:`repoze.bfg` function that renders ZPT
- templates to a response. :mod:`repoze.bfg` uses the
- :term:`chameleon.zpt` 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 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 02, we returned a :term:`WebOb` Response object that we
-created. ``render_template_to_response`` makes a Response itself.
-The response's status is always ``200 OK`` and the content-type is
-always ``text/html`` if you use this shortcut function.
-
-Here's what the ZPT looks like again:
-
-.. literalinclude:: step03/myapp/templates/default.pt
- :linenos:
- :language: xml
-
-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_to_response``.
-
-#. Line 6 looks interesting. It uses the ``node`` that we passed in
- via ``render_template_to_response``. Since :term:`chameleon.zpt`
- 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, restarting the application and visiting
-``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.
-
-If you visit ``http://localhost:5432/`` you will see::
-
- My template is viewing item: site
-
- The node has a tag name of: site.
-
-We've successfully rendered a view that uses a template against a
-model using the ZPT templating language.
-
-
-XSLT Templates
-==============
-
-So that's the ZPT way of rendering HTML for an XML document. We can
-additonally use XSLT to do templating. How might XSLT look?
-
-``configure.zcml``
-----------------------------------
-
-Make your ``configure.zcml`` look like so:
-
-.. 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 URLs invoked against our model can have ``/xsltview.html``
- appended to them, which will invoke our XSLT view.
-
-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. The view itself controls which templating
-language is in use.
-
-``views.py``
---------------------------------
-
-The ZCML says that our XSLT view (``xsltview.html`` on the URL) comes
-from the ``lxmlgraph.views.xslt_view`` function, which you should add
-to your ``views.py`` file:
-
-.. 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 :mod:`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.
-
-
-``xsltview.xsl``
---------------------------------
-
-Add a file named ``xsltview.xsl`` to your application's ``templates``
-directory and give it the following contents:
-
-.. literalinclude:: step03/myapp/templates/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 ``<document>`` 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
- ``<document>`` node (thanks to line 3). Thus, ``<xsl:value of
- select="@id"/>`` 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 those changes in place, restart the application. Visiting to the
-``http://localhost:5432/a/xsltview.html`` URL should show::
-
- My template is viewing item: a
-
- The node has a name of: document.
-
-We've successfully run an XSL template against our model object.
-
-We've now seen how to use ZPT and XSL templates against model objects
-created via an XML tree.
-
-
diff --git a/docs/tutorials/lxmlgraph/step03/myapp/__init__.py b/docs/tutorials/lxmlgraph/step03/myapp/__init__.py
deleted file mode 100644
index 792d60054..000000000
--- a/docs/tutorials/lxmlgraph/step03/myapp/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/docs/tutorials/lxmlgraph/step03/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step03/myapp/configure.zcml
deleted file mode 100644
index 43b766cfb..000000000
--- a/docs/tutorials/lxmlgraph/step03/myapp/configure.zcml
+++ /dev/null
@@ -1,16 +0,0 @@
-<configure xmlns="http://namespaces.repoze.org/bfg">
-
- <include package="repoze.bfg.includes" />
-
- <view
- for=".models.IMyModel"
- view=".views.zpt_view"
- />
-
- <view
- for=".models.IMyModel"
- view=".views.xslt_view"
- name="xsltview.html"
- />
-
-</configure>
diff --git a/docs/tutorials/lxmlgraph/step03/myapp/models.py b/docs/tutorials/lxmlgraph/step03/myapp/models.py
deleted file mode 100644
index 1d93ccdd0..000000000
--- a/docs/tutorials/lxmlgraph/step03/myapp/models.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import os
-
-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
- here = os.path.join(os.path.dirname(__file__))
- samplemodel = os.path.join(here, 'samplemodel.xml')
- xmlstring = open(samplemodel).read()
- root = etree.XML(xmlstring, parser)
-
- return root
diff --git a/docs/tutorials/lxmlgraph/step03/myapp/samplemodel.xml b/docs/tutorials/lxmlgraph/step03/myapp/samplemodel.xml
deleted file mode 100644
index bbe474c63..000000000
--- a/docs/tutorials/lxmlgraph/step03/myapp/samplemodel.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<site name="site">
- <document name="a"/>
- <document name="b"/>
-</site>
diff --git a/docs/tutorials/lxmlgraph/step03/myapp/templates/default.pt b/docs/tutorials/lxmlgraph/step03/myapp/templates/default.pt
deleted file mode 100644
index 3cc98ef92..000000000
--- a/docs/tutorials/lxmlgraph/step03/myapp/templates/default.pt
+++ /dev/null
@@ -1,8 +0,0 @@
-<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>
diff --git a/docs/tutorials/lxmlgraph/step03/myapp/templates/xsltview.xsl b/docs/tutorials/lxmlgraph/step03/myapp/templates/xsltview.xsl
deleted file mode 100644
index 4d759b15b..000000000
--- a/docs/tutorials/lxmlgraph/step03/myapp/templates/xsltview.xsl
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <xsl:template match="/document">
- <html>
- <head/>
- <body>
- <h1>My template is viewing item: <xsl:value-of select="@name"/></h1>
- <p>The node has a name of: <xsl:value-of select="name()"/>.</p>
- </body>
- </html>
- </xsl:template>
-</xsl:stylesheet>
diff --git a/docs/tutorials/lxmlgraph/step03/myapp/views.py b/docs/tutorials/lxmlgraph/step03/myapp/views.py
deleted file mode 100644
index e18c04415..000000000
--- a/docs/tutorials/lxmlgraph/step03/myapp/views.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from repoze.bfg.chameleon_zpt import render_template_to_response
-from repoze.bfg.xslt import render_transform_to_response
-
-def zpt_view(context, request):
- return render_template_to_response("templates/default.pt",
- name=context.__name__,
- node=context)
-
-def xslt_view(context, request):
- return render_transform_to_response('templates/xsltview.xsl', context)
diff --git a/docs/tutorials/lxmlgraph/step04.rst b/docs/tutorials/lxmlgraph/step04.rst
deleted file mode 100644
index f96a0712f..000000000
--- a/docs/tutorials/lxmlgraph/step04.rst
+++ /dev/null
@@ -1,250 +0,0 @@
-================================================
-Step 4: 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]
-
-In this step we take a look at the following:
-
-- Build a nested, folder-like website
-
-- Render the HTML common to all pages, then render the part specific
- to a certain page
-
-- Show contents of a folder when sitting on a folder, and content of a
- document when sitting on a document
-
-
-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
-``configure.zcml`` can now be madesimpler. Change your
-``configure.zcml`` to lok like so:
-
-.. literalinclude:: step04/myapp/configure.zcml
- :linenos:
- :language: xml
-
-We'll also remove the ``zpt_view`` function from ``views.py``, as
-we'll see in a moment.
-
-Design Change: Trees and Context IDs
-========================================
-
-In :mod:`repoze.bfg`, the ``context`` variable that is passed into our
-view function equates to the Python object that was grabbed on the
-current hop in the URL. For ``lxmlgraph``, that "context" object is a
-node in the XML document, found by traversing node children.
-
-For the XSLT in Step 3, we passed in the context node. From the
-XSLT's perpective, the universe started at the context node. It could
-only see information in that node and the children beneath it.
-
-If we could see the entire tree, however, we could put the other
-information to use: showing the name of the site in a header, listing
-the breadcrumbs to reach the document, and other portal-style boxes.
-
-To enable this, we need the following:
-
-#. A way to pass in the entire XML document tree.
-
-#. A way to uniquely point at the item in the XML that we are
- currently sitting on, with the fastest performance possible.
-
-We will thus make the following changes in our approach:
-
-#. The XML document will support an ``xml:id`` attribute on each node
- that has a ``name`` attribute. The ``xml:id`` uniquely identifies
- the resource within the document. Moreover, it leverages built-in
- support for high-speed lookups in XPath.
-
-#. We change the view function to pass in the root of the tree,
- instead of the context node.
-
-#. We also pass in, via an XSLT parameter, the ``xml:id`` of the
- context node.
-
-#. The XSLT will start at the top of the tree, generate the site-wide
- look and feel, then render the context node.
-
-That's the big picture. Each of these changes will be explained in
-detail below.
-
-``samplemodel.xml``
-=====================
-
-The XML document with the information for our website has quite a
-number of changes:
-
-.. literalinclude:: step04/myapp/samplemodel.xml
- :linenos:
- :language: xml
-
-#. Line 3 shows that our ``<site>`` now gets a ``<title>``.
-
-#. On Line 4 we make an index document at the root that contains a
- document-wide unique value for its ``@xml:id``.
-
-#. In lines 5-11, our ``<document>`` gets some extra information: a
- ``<title>``, plus some HTML-namespaced markup content inside a
- ``<body>``.
-
-#. Lines 13-32 show a nested XML hierarchy. A ``<folder>`` gets an
- ``@name``, making the folder itself published as a possible URL.
- It also gets an ``@xml:id``, allowing it to be uniquely addressed
- within the entire document. The ``<folder>`` gets a ``<title>``
- child node, but then gets two more ``__getitem__``-enabled child
- nodes of type ``<document>``. ("Enabled", as in, has a ``@name``
- attribute.)
-
-Thus the major changes:
-
-- The root contains ``<folder>`` nodes which contain ``<document>``
- nodes.
-
-- The root could contain documents too, and the folder could contain
- sub-folders. There's nothing special about the arrangement.
-
-- The only thing special is the presence of ``@name`` attributes,
- which allow ``__getitem__`` (via XPath) to traverse to that child.
-
-- As we'll see in a second, the ``@xml:id`` allows jumping through the
- hierarchy directly to a node.
-
-- Finally, for UI-framework-ish purposes, having a child ``<title>``
- allows us to show in a browser what we're looking at.
-
-The ``models.py`` hasn't changed, so let's move to the small changes
-in the ``views.py``.
-
-``views.py``
-============
-
-As noted above, we removed the ZPT views, and thus ``views.py`` is
-shorter, and focused only on a function that provides an XSLT
-template. Although there aren't many lines in that function, there
-are some concepts to explain:
-
-.. literalinclude:: step04/myapp/views.py
- :linenos:
-
-#. We are going to be using a feature from XML called ``xml:id``,
- which we explained above in the ``samplemodel.xml`` section. In
- lines 4 and 5, we make constants that point to the namespace
- needed.
-
-#. As the comment says, line 9 grabs the "root" node of the site.
- Inside this function, we are traversing, node-by-node, through a
- hierarchy. Thus our context node is an lxml Element object, which
- supports a method to grab the tree (and thus root) in which the
- context sits.
-
-#. Next, to support the XSLT approach we show next, we want to let the
- XSLT know the ``xml:id`` that we are sitting on. Since we are
- passing it in as an XSLT paramter, we need some special handling:
-
- - The *value* of the parameter is the ``@xml:id`` of the node we are
- sitting on.
-
- - Per lxml's needs, that value needs to be quoted. Thus, the value
- of ``contextid`` will be something like ``"'n1'"``
-
-#. Finally, on line 12, we call the XSLT processor, passing in keyword
- arguments that become XSLT parameters. Unlike before, the node we
- pass in is the top of the tree, rather than the current (context)
- node.
-
-In summary, we render the XSLT by handing it the root node of the
-tree, plus a flag that says which node we are currently sitting on.
-
-``xsltview.xsl``
-=================
-
-The XSLT template gets the most substantive changes, as we both have
-to support this root-and-contextid idea, as well as some features that
-put this to use:
-
-- Having a common look-and-feel across all pages, along with "rules"
- that handle each content type
-
-- Show the context's ``<title>`` in the same place
-
-- Show some general information about the node
-
-The following XSLT accomplishes these features:
-
-.. literalinclude:: step04/myapp/xsltview.xsl
- :linenos:
- :language: xml
-
-#. Line 3 accepts the ``@xml:id`` passed in as a parameter of the XSLT
- transformation. This can differ between requests, as different
- nodes are traversed.
-
-#. Line 4 jumps directly to the tree node that has that ``@xml:id`` by
- using XPath's ``id()`` function. This is a high-speed lookup,
- similar to ``document.getElementById()`` in JavaScript. We then
- assign the node to a global XSLT variable, to avoid paying that
- price again.
-
-#. Line 5 gets into XSLT's rule-oriented mumbo-jumbo. This template
- rule says: "Match on the root of the tree that was passed in, then
- do some work." Think of this as a CSS rule that matches on ``body
- {}``.
-
-#. Lines 7-11 output HTML for the document and ``<head>``.
-
-#. Line 9 (and line 14) inserts the value of the context node's
- ``<title>`` using ``<xsl:value-of>``.
-
-#. Line 16 does some XSLT mumbo jumbo. It says "Find a rule that
- handles the context node, which might be a ``<folder>`` or might be
- a ``<document>``." Control is then passed to an ``<xsl:template>``
- that meets the conditions. Once that rule is finished, control
- returns to line 17.
-
-#. Lines 17-42 then format some basic information about the context
- node. The HTML generated for this, however, appears *after* the
- type-specific handler in the resulting HTML.
-
-#. Line 46 is an ``<xsl:template>`` rule that handles ``<folder>``
- nodes. It only gets control when something else hands control to it.
-
- In this case, the rule makes a paragraph then lists the contents of
- the folder.
-
-#. Line 50 checks to see if the folder contains any "publishable"
- content. We wouldn't want a heading to appear saying "Folder
- Contents" with empty space under it.
-
-#. Line 53 then iterates over all the child nodes which have an
- ``@xml:id``.
-
-#. Lines 55-57 make an ``<li>`` with an ``<a>`` for each item in the
- folder. Inside the ``<xsl:for-each``, the "current" node is the
- current item in the iteration. The ``@href`` uses what XSLT calls
- "attribute value template" (curly braces) to let the XSLT processor
- operate inside an attribute.
-
-#. Line 63 handles ``<document>`` nodes when handed control.
-
-#. Line 67 recursively copies the nodes in the ``<document>`` content.
-
-To recap, this XSLT handles any node passed in, and generates a UI
-that can handle the global styling, the navigational elements, and the
-content for the current traversal hop.
-
-Conclusion
-=====================
-
-Though not very much code, this is the basis for a useful amount of
-features. A hierarchical website with templating that can handle
-global styling and navigation, as well as type-driven templating, all
-at reasonable (albeit in-memory) performance.
-
-
diff --git a/docs/tutorials/lxmlgraph/step04/myapp/__init__.py b/docs/tutorials/lxmlgraph/step04/myapp/__init__.py
deleted file mode 100644
index 792d60054..000000000
--- a/docs/tutorials/lxmlgraph/step04/myapp/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/docs/tutorials/lxmlgraph/step04/myapp/configure.zcml b/docs/tutorials/lxmlgraph/step04/myapp/configure.zcml
deleted file mode 100644
index c2d59effb..000000000
--- a/docs/tutorials/lxmlgraph/step04/myapp/configure.zcml
+++ /dev/null
@@ -1,10 +0,0 @@
-<configure xmlns="http://namespaces.repoze.org/bfg">
-
- <include package="repoze.bfg.includes" />
-
- <view
- for=".models.IMyModel"
- view=".views.xslt_view"
- />
-
-</configure>
diff --git a/docs/tutorials/lxmlgraph/step04/myapp/models.py b/docs/tutorials/lxmlgraph/step04/myapp/models.py
deleted file mode 100644
index a0d64ef59..000000000
--- a/docs/tutorials/lxmlgraph/step04/myapp/models.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import os
-
-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
- here = os.path.join(os.path.dirname(__file__))
- samplemodel = os.path.join(here, 'samplemodel.xml')
- xmlstring = open(samplemodel).read()
- root = etree.XML(xmlstring, parser)
-
- return root
-
-
-
diff --git a/docs/tutorials/lxmlgraph/step04/myapp/samplemodel.xml b/docs/tutorials/lxmlgraph/step04/myapp/samplemodel.xml
deleted file mode 100644
index 36ab335d2..000000000
--- a/docs/tutorials/lxmlgraph/step04/myapp/samplemodel.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?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>
diff --git a/docs/tutorials/lxmlgraph/step04/myapp/views.py b/docs/tutorials/lxmlgraph/step04/myapp/views.py
deleted file mode 100644
index f079cea8c..000000000
--- a/docs/tutorials/lxmlgraph/step04/myapp/views.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from repoze.bfg.xslt 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)
diff --git a/docs/tutorials/lxmlgraph/step04/myapp/xsltview.xsl b/docs/tutorials/lxmlgraph/step04/myapp/xsltview.xsl
deleted file mode 100644
index 2406987d0..000000000
--- a/docs/tutorials/lxmlgraph/step04/myapp/xsltview.xsl
+++ /dev/null
@@ -1,69 +0,0 @@
-<?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>
diff --git a/docs/tutorials/lxmlgraph/step04/run.py b/docs/tutorials/lxmlgraph/step04/run.py
deleted file mode 100644
index 1eac209dc..000000000
--- a/docs/tutorials/lxmlgraph/step04/run.py
+++ /dev/null
@@ -1,8 +0,0 @@
-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')
diff --git a/docs/tutorials/lxmlgraph/step05.rst b/docs/tutorials/lxmlgraph/step05.rst
deleted file mode 100644
index c3ba037d2..000000000
--- a/docs/tutorials/lxmlgraph/step05.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-================================================
-Step 5: Advanced Templating
-================================================
-
-- multiple "views" wired to the same function and template
-
-- breadcrumbs, sidebars
-
-- <query> support
-
-- type-based support for <document>, <folder>, <query>, <site>