[Checkins] SVN: zope2book/trunk/ Lot's of updates over the weekend!

Hanno Schlichting plone at hannosch.info
Sun Feb 15 08:08:16 EST 2009


Log message for revision 96569:
  Lot's of updates over the weekend!
  

Changed:
  A   zope2book/trunk/TODO.txt
  A   zope2book/trunk/old/
  A   zope2book/trunk/old/AdvDTML.rst
  A   zope2book/trunk/old/DTML.rst
  U   zope2book/trunk/source/Acquisition.rst
  D   zope2book/trunk/source/AdvDTML.rst
  U   zope2book/trunk/source/AdvZPT.rst
  U   zope2book/trunk/source/AppendixA.rst
  U   zope2book/trunk/source/BasicObject.rst
  D   zope2book/trunk/source/DTML.rst
  U   zope2book/trunk/source/InstallingZope.rst
  U   zope2book/trunk/source/IntroducingZope.rst
  U   zope2book/trunk/source/ObjectOrientation.rst
  U   zope2book/trunk/source/Preface.rst
  U   zope2book/trunk/source/RelationalDatabases.rst
  U   zope2book/trunk/source/ScriptingZope.rst
  U   zope2book/trunk/source/SearchingZCatalog.rst
  U   zope2book/trunk/source/Security.rst
  U   zope2book/trunk/source/SimpleExamples.rst
  U   zope2book/trunk/source/UsingZope.rst
  U   zope2book/trunk/source/ZPT.rst
  U   zope2book/trunk/source/ZopeArchitecture.rst
  U   zope2book/trunk/source/ZopeServices.rst
  U   zope2book/trunk/source/index.rst

-=-
Added: zope2book/trunk/TODO.txt
===================================================================
--- zope2book/trunk/TODO.txt	                        (rev 0)
+++ zope2book/trunk/TODO.txt	2009-02-15 13:08:15 UTC (rev 96569)
@@ -0,0 +1,33 @@
+####
+TODO
+####
+
+General
+=======
+
+- The various webserver related chapters should mention repoze/WSGI instead
+  of the FastCGI/PCGI stuff.
+
+- Some more clarification of Zope3 - Zope Components is required.
+
+- External links needs to be checked and updated (Sphinx: make linkcheck).
+
+InstallingZope
+==============
+
+- Rewrite the installation chapter to cover buildout, eggs, virtualenv and
+  the modern world (Since this is 2.12, we don't need to document the old
+  full tarball release anymore).
+
+  Tres has written something in the install.txt inside the Zope2/trunk
+
+- Refer to the plone.org/how-to/buildout-on-windows stuff for compiling from
+  source on Windows. Make sure we get binary eggs of all dependencies and
+  ourselves for normal installations.
+
+ZopeArchitecture.rst
+====================
+
+- This uses ../Figures/zopearchitecture.gif which still includes ZClasses and
+  should replace the `Products` naming with a more general packages.
+


Property changes on: zope2book/trunk/TODO.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Copied: zope2book/trunk/old/AdvDTML.rst (from rev 96449, zope2book/trunk/source/AdvDTML.rst)
===================================================================
--- zope2book/trunk/old/AdvDTML.rst	                        (rev 0)
+++ zope2book/trunk/old/AdvDTML.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -0,0 +1,1664 @@
+Advanced DTML
+=============
+
+DTML is the kind of language that appears to "do what you mean."
+That is good when it does what you actually want it to do, but when
+it does something you don't want to do, well, it's no fun at all.
+This chapter tells you how to make DTML do what you *really* mean.
+When you're done reading this chapter you will be able to write DTML
+that will accomplish a number of complex tasks including:
+
+- Inspect and Modify the REQUEST object
+
+- Modify the current namespace
+
+- Call other scripts from within DTML
+
+- Send email with or without MIME attachments
+
+- Handle exceptions within DTML    
+
+A few of caveats before getting started:
+
+- It's a good idea to know something about Python before diving into
+  advanced DTML or any other advanced area of Zope.
+
+- Understand the Zope acquisition model and how it works.
+
+- If you are writing very complex functionality in DTML, consider
+  using a Python Script.  This will ease maintenance, not to mention
+  readability.
+
+- Understand the difference between a DTML Document and a DTML
+  Method before embarking on building a huge site. See the explanation
+  included in this chapter.
+
+It's no lie that DTML has a reputation for complexity.  While it is true
+that DTML is really simple if all you want to do is simple layout,
+using DTML for more advanced tasks requires an understanding of where 
+DTML variables come from.
+
+Here's a very tricky error that almost all newbies encounter.
+Imagine you have a DTML Document called *zooName*.  This
+document contains an HTML form like the following::
+
+  <dtml-var standard_html_header>
+
+    <dtml-if zooName>
+
+      <p><dtml-var zooName></p>
+
+    <dtml-else>
+
+      <form action="<dtml-var URL>" method="GET">
+        <input name="zooName">
+        <input type="submit" value="What is zooName?">
+      </form>
+
+    </dtml-if>  
+
+  <dtml-var standard_html_footer>
+
+This looks simple enough, the idea is, this is an HTML page that calls
+itself.  This is because the HTML action is the *URL* variable, which
+will become the URL of the DTML Document.  
+
+If there is a 'zooName' variable, then the page will print it, if there
+isn't, it shows a form that asks for it.  When you click submit, the data
+you enter will make the "if" evaluate to true, and this code should print
+what was entered in the form.
+
+But unfortunately, this is one of those instances where DTML will not do
+what you mean, because the name of the DTML Document that contains this
+DTML is also named *zooName*, and it doesn't use the variable out of the
+request, it uses itself, which causes it to call itself and call itself, ad
+infinitum, until you get an "excessive recursion" error.  So instead of
+doing what you really meant, you got an error. This is what confuses
+beginners.  In the next couple of sections, we'll show you how to fix this
+example to do what you mean.
+
+How Variables are Looked up
+---------------------------
+
+There are actually two ways to fix the DTML error in the
+*zooName* document.  The first is that you can rename the document
+to something like *zopeNameFormOrReply* and always remember this
+special exception and never do it; never knowing why it happens.
+The second is to understand how names are looked up, and to be
+explicit about where you want the name to come from in the
+*namespace*.
+
+The DTML namespace is a collection of objects arranged in a *stack*.  A
+stack is a list of objects that can be manipulated by *pushing* and
+*popping* objects on to and off of the stack. 
+
+When a DTML Document or DTML Method is executed, Zope creates a
+DTML namespace to resolve DTML variable names. It's important to
+understand the workings of the DTML namespace so that you can
+accurately predict how Zope will locate variables. Some of the
+trickiest problems you will run into with DTML can be resolved by
+understanding the DTML namespace.
+
+When Zope looks for names in the DTML namespace stack it first looks at
+the topmost object in the stack.  If the name can't be found
+there, then the next item down is introspected.  Zope will work its way
+down the stack, checking each object in turn until it finds the name
+that it is looking for.
+
+If Zope gets all the way down to the bottom of the stack and
+can't find what it is looking for, then an error is generated.  For
+example, try looking for the non-existent name, *unicorn*::
+
+  <dtml-var unicorn>
+
+As long as there is no variable named *unicorn* viewing this
+DTML will return an error, as shown in the figure below.
+
+.. figure:: ../Figures/7-1.png
+
+   DTML error message indicating that it cannot find a variable
+
+But the DTML stack is not all there is to names because DTML
+doesn't start with an empty stack, before you even begin executing
+DTML in Zope there are already a number of objects pushed on the
+namespace stack.
+
+DTML Namespaces
+---------------
+
+DTML namespaces are built dynamically for every request in Zope. When
+you call a DTML Method or DTML Document through the web, the DTML
+namespace starts with the same first two stack elements; the client
+object and the request, as shown in the figure below.
+
+.. figure:: ../Figures/7-2.png
+
+   Initial DTML namespace stack
+
+The client object is the first object on the top of the DTML namespace
+stack when entering a transaction (note:  commands exist to push 
+additional parameters onto the namespace stack during a thread of 
+execution).  What the client object is depends on whether you are
+executing a DTML Method or a DTML Document.  In our example above, this
+means that the client object is named *zooName*.  Which is why it
+breaks.  The form input that we really wanted comes from the web
+request, but the client is looked at first.
+
+The request namespace is always on the bottom of the DTML namespace
+stack, and is therefore the last namespace to be looked in for names.
+This means that we must be explicit in our example about which
+namespace we want.  We can do this with the DTML 'with' tag::
+
+  <dtml-var standard_html_header>
+
+    <dtml-with REQUEST only>
+      <dtml-if zooName>
+        <p><dtml-var zooName></p>
+      <dtml-else>
+        <form action="<dtml-var URL>" method="GET">
+          <input name="zooName">
+          <input type="submit" value="What is zooName?">
+        </form>
+      </dtml-if>
+    </dtml-with>
+
+  <dtml-var standard_html_footer>
+
+Here, the with tag says to look in the 'REQUEST' namespace, and *only*
+the 'REQUEST' namespace, for the name "zooName".
+
+DTML Client Object  
+~~~~~~~~~~~~~~~~~~
+
+The client object in DTML depends on whether or not you are executing a
+DTML Method or a DTML Document.  In the case of a Document, the client
+object is always the document itself, or in other words, a DTML
+Document is its own client object.
+
+A DTML Method however can have different kinds of client objects
+depending on how it is called.  For example, if you had a DTML Method
+that displayed all of the contents of a folder then the client object
+would be the folder that is being displayed.  This client object can
+change depending on which folder the method in question is
+displaying.  For example, consider the following DTML Method named
+*list* in the root folder::
+
+  <dtml-var standard_html_header>
+
+  <ul>
+  <dtml-in objectValues>
+    <li><dtml-var title_or_id></li>
+  </dtml-in>
+  </ul>
+
+  <dtml-var standard_html_footer>
+
+Now, what this method displays depends upon how it is used.  If
+you apply this method to the *Reptiles* folder with the URL
+'http://localhost:8080/Reptiles/list', then you will get
+something that looks like the figure below.
+
+.. figure:: ../Figures/7-3.png
+
+   Applying the *list* method to the *Reptiles* folder
+
+But if you were to apply the method to the *Birds* folder with
+the URL *http://localhost:8080/Birds/list* then you would get
+something different, only two items in the list, *Parrot* and
+*Raptors*.
+
+Same DTML Method, different results. In the first example, the client
+object of the *list* method was the *Reptiles* folder.  In the second
+example, the client object was the *Birds* folder. When Zope looked
+up the *objectValues* variable, in the first case it called the
+*objectValues* method of the *Reptiles* folder, in the second case it
+called the *objectValues* method of the *Birds* folder.
+
+In other words, the client object is where variables such as
+methods, and properties are looked up first.
+
+As you saw in "Dynamic Content with DTML", if Zope
+cannot find a variable in the client object, it searches through
+the object's containers.  Zope uses acquisition to automatically
+inherit variables from the client object's containers.  So when
+Zope walks up the object hierarchy looking for variables it
+always starts at the client object, and works its way up from
+there.
+
+DTML Method vs. DTML Document
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One of the most potentially confusing choices to make for Zope
+newbies is the choice between a DTML Method and a DTML Document.
+Unfortunately, many Zope newbies develop entire sites using one 
+type of object only to discover that they should have used the 
+other type. In general, keep the following items in mind when 
+deciding upon which type to use:
+
+- **Does the object require properties of its own?** If so,
+    use a DTML Document since DTML Methods have no inherent
+    properties.
+
+- **Does the object need to be called as a "page"?** If so,
+    consider using a DTML Document since it will be easier
+    to control such items as page title by using properties.
+
+- **Does the object need transparency to its context?** If so, 
+    you should probably use a DTML Method since these objects
+    act as though they are directly attached to their calling, 
+    or containing object.
+
+DTML Request Object
+~~~~~~~~~~~~~~~~~~~
+
+The request object is the bottom object on the DTML
+namespace stack.  The request contains all of the information
+specific to the current web request.
+
+Just as the client object uses acquisition to look in a number
+of places for variables, so too the request looks up variables
+in a number of places. When the request looks for a variable it
+consults these sources in order:
+
+1. The CGI environment. The `Common Gateway Interface
+   <http://www.w3.org/CGI/>`_, or CGI interface defines
+   a standard set of environment variables to be used by
+   dynamic web scripts.  These variables are provided by Zope
+   in the REQUEST namespace.
+
+2. Form data. If the current request is a form action, then
+   any form input data that was submitted with the request can
+   be found in the REQUEST object.
+
+3. Cookies. If the client of the current request has any cookies
+   these can be found in the current REQUEST object.
+
+4. Additional variables. The REQUEST namespace provides you
+   with lots of other useful information, such as the URL of
+   the current object and all of its parents.
+
+The request namespace is very useful in Zope since it is the
+primary way that clients (in this case, web browsers)
+communicate with Zope by providing form data, cookies and other
+information about themselves. For more information about the
+request object, see Appendix B.
+
+A very simple and enlightening example is to simply render the REQUEST
+object in a DTML Document or Method::
+
+  <dtml-var standard_html_header>
+
+  <dtml-var REQUEST>
+
+  <dtml-var standard_html_footer>
+
+Try this yourself, you should get something that looks like
+the figure below.
+
+.. figure:: ../Figures/7-4.png
+
+   Displaying the request
+
+Since the request comes after the client object, if there are names
+that exist in both the request and the client object, DTML will
+always find them first in the client object. This can be a
+problem. Next, let's look at some ways to get around this problem by
+controlling more directly how DTML looks up variables.
+
+Rendering Variables
+-------------------
+
+When you insert a variable using the *var* tag, Zope first looks
+up the variable using the DTML namespace, it then *renders* it
+and inserts the results. Rendering means turning an object or
+value into a string suitable for inserting into the output. Zope
+renders simple variables by using Python's standard method for
+coercing objects to strings. For complex objects such as DTML
+Methods and SQL Methods, Zope will call the object instead of
+just trying to turn it into a string. This allows you to insert
+DTML Methods into other DTML Methods.
+
+In general Zope renders variables in the way you would
+expect. It's only when you start doing more advanced tricks that
+you become aware of the rendering process. Later in this chapter
+we'll look at some examples of how to control rendering using
+the 'getitem' DTML utility function.
+
+Modifying the DTML Namespace
+----------------------------
+
+Now that you know the DTML namespace is a stack, you may
+be wondering how, or even why, new objects get pushed onto it.
+
+Some DTML tags modify the DTML namespace while they are executing.
+A tag may push some object onto the namespace stack during the
+course of execution.  These tags include the *in* tag, the *with*
+tag, and the *let* tag.
+
+*In* Tag Namespace Modifications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When the *in* tag iterates over a sequence it pushes the current
+item in the sequence onto the top of the namespace stack::
+
+  <dtml-var getId> <!-- This is the id of the client object -->
+
+  <dtml-in objectValues>
+
+    <dtml-var getId> <!-- this is the id of the current item in the 
+                       objectValues sequence -->
+  </dtml-in>
+
+You've seen this many times throughout the examples in this
+book.  While the *in* tag is iterating over a sequence, each item
+is pushed onto the namespace stack for the duration of the
+contents of the in tag block.  When the block is finished
+executing, the current item in the sequence is popped off the
+DTML namespace stack and the next item in the sequence is pushed
+on.
+
+Additional Notes
+%%%%%%%%%%%%%%%%
+
+To be more accurate, the *in* tag pushes a number of items
+onto the namespace stack.  These include sequence variables,
+grouping variables, and batch variables in addition to the
+object itself.  Some of those variables are:
+
+- sequence-item: The current item within the iteration.
+
+- sequence-start: True if the current item is the first item
+  in the sequence.
+
+- sequence-end: True if the current item is the last item in
+   the sequence.
+
+- sequence-length: The length of the sequence. 
+
+- previous-sequence: True on the first iteration if the
+  current batch is not the first one. Batch size is set with the
+  size attribute.
+
+- next-sequence: True on the last iteration if the current
+  batch is not the last batch.
+
+There are many more variables available when using the *in*
+tag.  See `Appendix A <AppendixA.html>`_ for more detail.
+
+The *With* Tag
+~~~~~~~~~~~~~~
+
+The *with* tag pushes an object that you specify onto 
+the namespace stack for the duration of the with block. This
+allows you to specify where variables should be looked up first.
+When the with block closes, the object is popped off the
+namespace stack.
+
+Consider a folder that contains a bunch of methods and
+properties that you are interested in.  You could access those
+names with Python expressions like this::
+
+  <dtml-var standard_html_header>
+
+  <dtml-var expr="Reptiles.getReptileInfo()">
+  <dtml-var expr="Reptiles.reptileHouseMaintainer">
+
+  <dtml-in expr="Reptiles.getReptiles()">
+    <dtml-var species>
+  </dtml-in>
+
+  <dtml-var standard_html_footer>
+
+Notice that a lot of complexity is added to the code just to get
+things out of the *Reptiles* folder. Using the *with* tag you can
+make this example much easier to read::
+
+  <dtml-var standard_html_header>
+
+  <dtml-with Reptiles>
+
+    <dtml-var getReptileInfo>
+    <dtml-var reptileHouseMaintainer>
+
+    <dtml-in getReptiles>
+      <dtml-var species>
+    </dtml-in>
+
+  </dtml-with>
+
+  <dtml-var standard_html_footer>
+
+Another reason you might want to use the *with* tag is to put the
+request, or some part of the request on top of the namespace
+stack. For example suppose you have a form that includes an input
+named *id*. If you try to process this form by looking up the
+*id* variable like so::
+
+  <dtml-var id>
+
+You will not get your form's id variable, but the client
+object's id. One solution is to push the web request's form on
+to the top of the DTML namespace stack using the *with* tag::
+
+  <dtml-with expr="REQUEST.form">
+    <dtml-var id>
+  </dtml-with>
+
+This will ensure that you get the form's id first. See Appendix
+B for complete API documentation of the request object.
+
+If you submit your form without supplying a value for the *id* input,
+the form on top of the namespace stack will do you no good, since the
+form doesn't contain an *id* variable. You'll still get the client
+object's id since DTML will search the client object after failing to
+find the *id* variable in the form. The *with* tag has an attribute
+that lets you trim the DTML namespace to only include the object you
+pushed onto the namespace stack::
+
+  <dtml-with expr="REQUEST.form" only>
+    <dtml-if id>
+      <dtml-var id>
+    <dtml-else>
+      <p>The form didn't contain an "id" variable.</p>
+    </dtml-if>
+  </dtml-with>
+
+Using the *only* attribute allows you to be sure about where
+your variables are being looked up.
+
+The *Let* Tag
+~~~~~~~~~~~~~
+
+The *let* tag lets you push a new namespace onto the namespace stack.
+This namespace is defined by the tag attributes to the *let* tag::
+
+  <dtml-let person="'Bob'" relation="'uncle'">
+    <p><dtml-var person>'s your <dtml-var relation>.</p>
+  </dtml-let>
+
+This would display::
+
+  <p>Bob's your uncle.</p>
+
+The *let* tag accomplishes much of the same goals as the *with*
+tag. The main advantage of the let tag is that you can use it to
+define multiple variables to be used in a block. The *let* tag
+creates one or more new name-value pairs and pushes a
+namespace object containing those variables and their values on
+to the top of the DTML namespace stack. In general the *with*
+tag is more useful to push existing objects onto the namespace
+stack, while the *let* tag is better suited for defining new
+variables for a block.
+
+When you find yourself writing complex DTML that requires things
+like new variables, there's a good chance that you could do the
+same thing better with Python or Perl. Advanced scripting is
+covered in the chapter entitled `Advanced Zope Scripting
+<ScriptingZope.html>`_ .
+
+The DTML namespace is a complex place, and this complexity evolved
+over a lot of time.  Although it helps to understand where names come
+from, it is much more helpful to always be specific about where you
+are looking for a name.  The 'with' and 'let' tags let you alter
+the namespace in order to obtain references to the objects you
+need.
+
+DTML Namespace Utility Functions 
+--------------------------------
+
+Like all things in Zope, the DTML namespace is an object, and it can
+be accessed directly in DTML with the *_* (underscore) object.  The
+*_* namespace is often referred to as "the under namespace".
+
+The under namespace provides you with many useful methods for certain
+programming tasks.  Let's look at a few of them.
+
+Say you wanted to print your name three times.  This can be done
+with the *in* tag, but how do you explicitly tell the *in* tag to
+loop three times?  Just pass it a sequence with three items::
+
+  <dtml-var standard_html_header>
+
+  <ul>
+  <dtml-in expr="_.range(3)">
+    <li><dtml-var sequence-item>: My name is Bob.</li>
+  </dtml-in>
+  </ul>
+
+  <dtml-var standard_html_footer>
+
+The '_.range(3)' Python expression will return a sequence of the
+first three integers, 0, 1, and 2.  The *range* function is a
+*standard Python built-in* and many of Python's built-in functions
+can be accessed through the *_* namespace, including:
+
+'range([start,], stop, [step])'
+  Returns a list of integers
+  from 'start' to 'stop' counting 'step' integers at a
+  time. 'start' defaults to 0 and 'step' defaults to 1.  For example:
+
+'_.range(3,10,2)'
+    gives '[3,5,7,9]'.
+
+'_.len(sequence)'
+  'len' returns the size of *sequence* as an integer.
+
+Many of these names come from the Python language, which contains
+a set of special functions called 'built-ins'.  The Python
+philosophy is to have a small number of built-in names.  The Zope
+philosophy can be thought of as having a large, complex array of
+built-in names.
+
+The under namespace can also be used to explicitly control variable
+look up.  There is a very common usage of this syntax.  As mentioned 
+above the in tag defines a number of special variables, like
+*sequence-item* and *sequence-key* that you can use inside a loop to
+help you display and control it.  What if you wanted to use one of
+these variables inside a Python expression?::
+
+  <dtml-var standard_html_header>
+
+  <h1>The squares of the first three integers:</h1>
+  <ul>
+  <dtml-in expr="_.range(3)">
+    <li>The square of <dtml-var sequence-item> is: 
+      <dtml-var expr="sequence-item * sequence-item">
+    </li>
+  </dtml-in>  
+  </ul>  
+
+  <dtml-var standard_html_footer>
+
+Try this, does it work?  No!  Why not?  The problem lies in this
+var tag::
+
+  <dtml-var expr="sequence-item * sequence-item">
+
+Remember, everything inside a Python expression attribute must be
+a *valid Python expression*.  In DTML, *sequence-item* is the name
+of a variable, but in Python this means "The object *sequence*
+minus the object *item*".  This is not what you want.
+
+What you really want is to look up the variable *sequence-item*.
+One way to solve this problem is to use the *in* tag *prefix*
+attribute. For example::
+
+  <dtml-var standard_html_header>
+
+  <h1>The squares of the first three integers:</h1>
+  <ul>
+  <dtml-in prefix="loop" expr="_.range(3)">
+    <li>The square of <dtml-var loop_item> is: 
+      <dtml-var expr="loop_item * loop_item">
+    </li>
+  </dtml-in>  
+  </ul>  
+
+  <dtml-var standard_html_footer>   
+
+The *prefix* attribute causes *in* tag variables to be renamed
+using the specified prefix and underscores, rather than using
+"sequence" and dashes. So in this example, "sequence-item" becomes
+"loop_item". See Appendix A for more information on the *prefix*
+attribute.
+
+Another way to look up the variable *sequence-item* in a DTML
+expression is to use the *getitem* utility function to explicitly
+look up a variable::
+
+  The square of <dtml-var sequence-item> is:
+  <dtml-var expr="_.getitem('sequence-item') * 
+                  _.getitem('sequence-item')">
+
+The *getitem* function takes the name to look up as its first
+argument. Now, the DTML Method will correctly display the square of the
+first three integers.  The *getitem* method takes an optional second
+argument which specifies whether or not to render the variable. Recall
+that rendering a DTML variable means turning it into a string. By
+default the *getitem* function does not render a variable.
+
+Here's how to insert a rendered variable named *myDoc*::
+
+  <dtml-var expr="_.getitem('myDoc', 1)">
+
+This example is in some ways rather pointless, since it's the
+functional equivalent to::
+
+  <dtml-var myDoc>
+
+However, suppose you had a form in which a user got to select
+which document they wanted to see from a list of choices. Suppose
+the form had an input named *selectedDoc* which contained the name
+of the document. You could then display the rendered document like
+so::
+
+  <dtml-var expr="_.getitem(selectedDoc, 1)">
+
+Notice in the above example that *selectedDoc* is not in
+quotes. We don't want to insert the text *selectedDoc*
+we want to insert the value of the variable named *selectedDoc*. For
+example, the value of *selectedDoc* might be 'chapterOne'. Using this
+method, you can look up an item using a dynamic value instead of 
+static text.
+
+If you are a python programmer and you begin using the more
+complex aspects of DTML, consider doing a lot of your work in
+Python scripts that you call *from* DTML.  This is explained more
+in the chapter entitled `Advanced Zope Scripting`_.
+Using Python sidesteps many of the issues in DTML.
+
+DTML Security
+-------------
+
+Zope can be used by many different kinds of users.  For example, the
+Zope site, `Zope.org <http://www.zope.org/>`_, has over 11,000 community
+members at the time of this writing.  Each member can log into Zope,
+add objects and news items, and manage their own personal area.
+
+Because DTML is a scripting language, it is very flexible about
+working with objects and their properties.  If there were no security
+system that constrained DTML then a user could potentially create
+malicious or privacy-invading DTML code.
+
+DTML is restricted by standard Zope security settings. So if you
+don't have permission to access an object by going to its URL you
+also don't have permission to access it via DTML. You can't use
+DTML to trick the Zope security system.
+
+For example, suppose you have a DTML Document named *Diary* which
+is private. Anonymous users can't access your diary via the
+web. If an anonymous user views DTML that tries to access your
+diary they will be denied::
+
+  <dtml-var Diary>
+
+DTML verifies that the current user is authorized to access all
+DTML variables.  If the user does not have authorization, then the
+security system will raise an *Unauthorized* error and the user
+will be asked to present more privileged authentication
+credentials.
+
+In the chapter entitled `Users and Security <Security.html>`_ , you
+read about security rules for executable content. There are ways
+to tailor the roles of a DTML Document or Method to allow it to
+access restricted variables regardless of the viewer's roles.
+
+Safe Scripting Limits
+---------------------
+
+DTML will not let you gobble up memory or execute infinite loops
+and recursions.  Because the restrictions on looping and memory
+use are relatively tight, DTML is not the right language for
+complex, expensive programming logic.  For example, you cannot
+create huge lists with the *_.range* utility function. You also
+have no way to access the filesystem directly in DTML.
+
+Keep in mind however that these safety limits are simple and can
+be outsmarted by a determined user.  It's generally not a good
+idea to let anyone you don't trust write DTML code on your site.
+
+Advanced DTML Tags
+------------------
+
+In the rest of this chapter we'll look at the many advanced DTML
+tags. These tags are summarized in Appendix A.  DTML has a set of
+built-in tags, as documented in this book, which can be counted on
+to be present in all Zope installations and perform the most
+common kinds of things. However, it is also possible to add new
+tags to a Zope installation. Instructions for doing this are
+provided at the Zope.org website, along with an interesting set
+of contributed DTML tags.
+
+This section covers what could be referred to as Zope
+*miscellaneous* tags.  These tags don't really fit into any broad
+categories except for one group of tags, the *exception handling*
+DTML tags which are discussed at the end of this chapter.
+
+The *Call* Tag
+--------------
+
+The *var* tag can call methods, but it also inserts the return
+value. Using the *call* tag you can call methods without inserting
+their return value into the output.  This is useful if you are
+more interested in the effect of calling a method rather than its
+return value.
+
+For example, when you want to change the value of a property,
+*animalName*, you are more interested in the effect of calling the
+*manage_changeProperties* method than the return value the method
+gives you.  Here's an example::
+
+  <dtml-if expr="REQUEST.has_key('animalName')">
+    <dtml-call expr="manage_changeProperties(animalName=REQUEST['animalName'])">
+    <h1>The property 'animalName' has changed</h1>
+  <dtml-else>
+    <h1>No properties were changed</h1>
+  </dtml-if>
+
+In this example, the page will change a property depending on whether
+a certain name exists.  The result of the *manage_changeProperties*
+method is not important and does not need to be shown to the user.
+
+Another common usage of the *call* tag is calling methods that affect
+client behavior, like the 'RESPONSE.redirect' method.  In this
+example, you make the client redirect to a different page, to
+change the page that gets redirected, change the value for the
+"target" variable defined in the *let* tag::
+
+  <dtml-var standard_html_header>
+
+  <dtml-let target="'http://example.com/new_location.html'">
+
+    <h1>This page has moved, you will now be redirected to the
+    correct location.  If your browser does not redirect, click <a
+    href="<dtml-var target>"><dtml-var target></a>.</h1>
+
+    <dtml-call expr="RESPONSE.redirect(target)">
+
+  </dtml-let>
+
+  <dtml-var standard_html_footer>  
+
+In short, the *call* tag works exactly like the *var* tag with the
+exception that it doesn't insert the results of calling the
+variable.
+
+Another possibility for use of the *call* tag would be to call a
+ZSQL Method or or preprocess the REQUEST.  Two examples of calling
+a ZSQL method::
+
+  <dtml-call "insertLogEntry(REQUEST)">
+
+or::
+
+  <dtml-call "insertLogEntry(logInfo=REQUEST.get('URL0'), severity=1)">
+
+To call a python script that might do any number of things,
+including preprocessing the REQUEST::
+
+  <dtml-call "preprocess(REQUEST)">
+
+The *Comment* Tag
+-----------------
+
+DTML can be documented with comments using the *comment* tag::
+
+  <dtml-var standard_html_header>
+
+  <dtml-comment>
+
+    This is a DTML comment and will be removed from the DTML code
+    before it is returned to the client.  This is useful for
+    documenting DTML code.  Unlike HTML comments, DTML comments
+    are NEVER sent to the client.
+
+  </dtml-comment>
+
+  <!-- 
+
+    This is an HTML comment, this is NOT DTML and will be treated
+    as HTML and like any other HTML code will get sent to the
+    client.  Although it is customary for an HTML browser to hide
+    these comments from the end user, they still get sent to the
+    client and can be easily seen by 'Viewing the Source' of a
+    document.
+
+  -->
+
+  <dtml-var standard_html_footer>        
+
+The *comment* block is removed from DTML output.
+
+In addition to documenting DTML you can use the *comment* tag to
+temporarily comment out other DTML tags. Later you can remove the
+*comment* tags to re-enable the DTML.
+
+The *Tree* Tag
+--------------
+
+The *tree* tag lets you easily build dynamic trees in HTML to
+display hierarchical data.  A *tree* is a graphical representation
+of data that starts with a "root" object that has objects
+underneath it often referred to as "branches".  Branches can have
+their own branches, just like a real tree.  This concept should be
+familiar to anyone who has used a file manager program like
+Microsoft Windows Explorer to navigate a file system.  And, in
+fact, the left hand "navigation" view of the Zope management
+interface is created using the tree tag.
+
+For example here's a tree that represents a collection of folders
+and sub-folders.
+
+.. figure:: ../Figures/7-5.png
+
+   HTML tree generated by the tree tag
+
+Here's the DTML that generated this tree display::
+
+  <dtml-var standard_html_header>
+
+  <dtml-tree>
+
+    <dtml-var getId>
+
+  </dtml-tree>
+
+  <dtml-var standard_html_footer>
+
+The *tree* tag queries objects to find their sub-objects and takes
+care of displaying the results as a tree. The *tree* tag block works
+as a template to display nodes of the tree.
+
+Now, since the basic protocol of the web, HTTP, is stateless, you
+need to somehow remember what state the tree is in every time you
+look at a page.  To do this, Zope stores the state of the tree in
+a *cookie*.  Because this tree state is stored in a cookie, only
+one tree can appear on a web page at a time, otherwise they will
+confusingly use the same cookie.
+
+You can tailor the behavior of the *tree* tag quite a bit with *tree*
+tag attributes and special variables. Here is a sampling of *tree*
+tag attributes.
+
+branches
+  The name of the method used to find sub-objects. This
+  defaults to *tpValues*, which is a method defined by a number of
+  standard Zope objects.
+
+leaves
+  The name of a method used to display objects that do
+  not have sub-object branches.
+
+nowrap
+  Either 0 or 1. If 0, then branch text will wrap to fit in
+  available space, otherwise, text may be truncated. The default
+  value is 0.
+
+sort
+  Sort branches before text insertion is performed. The
+  attribute value is the name of the attribute that items should be
+  sorted on.
+
+assume_children
+  Either 0 or 1. If 1, then all objects are
+  assumed to have sub-objects, and will therefore always have a
+  plus sign in front of them when they are collapsed. Only when an
+  item is expanded will sub-objects be looked for. This could be a
+  good option when the retrieval of sub-objects is a costly
+  process.  The defalt value is 0.
+
+single
+  Either 0 or 1. If 1, then only one branch of the tree can
+  be expanded. Any expanded branches will collapse when a new branch
+  is expanded.  The default value is 0.
+
+skip_unauthorized
+  Either 0 or 1. If 1, then no errors will be
+  raised trying to display sub-objects for which the user does not
+  have sufficient access. The protected sub-objects are not
+  displayed.  The default value is 0.
+
+Suppose you want to use the *tree* tag to create a dynamic site
+map. You don't want every page to show up in the site map. Let's
+say that you put a property on folders and documents that you want
+to show up in the site map.
+
+Let's first define a Script with the id of *publicObjects*
+that returns public objects::
+
+  ## Script (Python) "publicObjects"
+  ##
+  """
+  Returns sub-folders and DTML documents that have a
+  true 'siteMap' property.
+  """
+  results=[]
+  for object in context.objectValues(['Folder', 'DTML Document']):
+      if object.hasProperty('siteMap') and object.siteMap:
+          results.append(object)
+  return results
+
+Now we can create a DTML Method that uses the *tree* tag and our
+Scripts to draw a site map::
+
+  <dtml-var standard_html_header>
+
+  <h1>Site Map</h1>
+
+  <p><a href="&dtml-URL0;?expand_all=1">Expand All</a> |
+     <a href="&dtml-URL0;?collapse_all=1">Collapse All</a>
+  </p>
+
+  <dtml-tree branches="publicObjects" skip_unauthorized="1">
+    <a href="&dtml-absolute_url;"><dtml-var title_or_id></a>
+  </dtml-tree>
+
+  <dtml-var standard_html_footer>
+
+This DTML Method draws a link to all public resources and displays
+them in a tree. Here's what the resulting site map looks like.
+
+.. figure:: ../Figures/7-6.png
+
+   Dynamic site map using the tree tag
+
+For a summary of the *tree* tag arguments and special variables see
+Appendix A.
+
+The *Return* Tag
+----------------
+
+In general DTML creates textual output. You can however, make DTML
+return other values besides text. Using the *return* tag you can
+make a DTML Method return an arbitrary value just like a Python or
+Perl-based Script.
+
+Here's an example::
+
+  <p>This text is ignored.</p>
+
+  <dtml-return expr="42">
+
+This DTML Method returns the number 42.
+
+Another upshot of using the *return* tag is that DTML execution
+will stop after the *return* tag.
+
+If you find yourself using the *return* tag, you almost certainly
+should be using a Script instead. The *return* tag was developed
+before Scripts, and is largely useless now that you can easily
+write scripts in Python and Perl.
+
+The *Sendmail* Tag
+------------------
+
+The *sendmail* tag formats and sends a mail messages. You can use
+the *sendmail* tag to connect to an existing Mail Host, or you can
+manually specify your SMTP host.
+
+Here's an example of how to send an email message with the
+*sendmail* tag::
+
+  <dtml-sendmail>
+  To: <dtml-var recipient>
+  From: <dtml-var sender>
+  Subject: Make Money Fast!!!!
+
+  Take advantage of our exciting offer now! Using our exclusive method
+  you can build unimaginable wealth very quickly. Act now!
+  </dtml-sendmail>
+
+Notice that there is an extra blank line separating the mail
+headers from the body of the message.
+
+A common use of the *sendmail* tag is to send an email message
+generated by a feedback form. The *sendmail* tag can contain any
+DTML tags you wish, so it's easy to tailor your message with form
+data.
+
+The *Mime* Tag
+--------------
+
+The *mime* tag allows you to format data using MIME (Multipurpose
+Internet Mail Extensions). MIME is an Internet standard for
+encoding data in email message. Using the *mime* tag you can use
+Zope to send emails with attachments.
+
+Suppose you'd like to upload your resume to Zope and then have Zope
+email this file to a list of potential employers.
+
+Here's the upload form::
+
+  <dtml-var standard_html_header>
+
+  <p>Send you resume to potential employers</p>
+
+  <form method=post action="sendresume" ENCTYPE="multipart/form-data">
+  <p>Resume file: <input type="file" name="resume_file"></p>
+  <p>Send to:</p>
+  <p>
+  <input type="checkbox" name="send_to:list" value="jobs at yahoo.com">
+    Yahoo<br>
+
+  <input type="checkbox" name="send_to:list" value="jobs at microsoft.com">
+    Microsoft<br>
+
+  <input type="checkbox" name="send_to:list" value="jobs at mcdonalds.com">
+    McDonalds</p>
+
+  <input type=submit value="Send Resume">
+  </form>
+
+  <dtml-var standard_html_footer>
+
+Note:  The text *:list* added to the name of the input fields directs 
+Zope to treat the received information as a list type. For example if 
+the first two checkboxes were selected in the above upload form, the 
+REQUEST variable send_to would have the value [jobs at yahoo.com, jobs at microsoft.com]
+
+Create another DTML Method called *sendresume* to process the form
+and send the resume file::
+
+  <dtml-var standard_html_header>
+
+  <dtml-if send_to>
+
+    <dtml-in send_to> 
+
+      <dtml-sendmail smtphost="my.mailserver.com">
+      To: <dtml-var sequence-item>
+      Subject: Resume
+      <dtml-mime type=text/plain encode=7bit>
+
+      Hi, please take a look at my resume.
+
+      <dtml-boundary type=application/octet-stream disposition=attachment 
+      encode=base64><dtml-var expr="resume_file.read()"></dtml-mime>
+      </dtml-sendmail>
+
+    </dtml-in>
+
+    <p>Your resume was sent.</p>
+
+  <dtml-else>
+
+    <p>You didn't select any recipients.</p>
+
+  </dtml-if>
+
+  <dtml-var standard_html_footer>    
+
+This method iterates over the *sendto* variable and sends one
+email for each item.
+
+Notice that there is no blank line between the 'To:' header and
+the starting *mime* tag.  If a blank line is inserted between them
+then the message will not be interpreted as a *multipart* message
+by the receiving mail reader.
+
+Also notice that there is no newline between the *boundary* tag
+and the *var* tag, or the end of the *var* tag and the closing
+*mime* tag.  This is important, if you break the tags up with
+newlines then they will be encoded and included in the MIME part,
+which is probably not what you're after.
+
+As per the MIME spec, *mime* tags may be nested within *mime* tags
+arbitrarily.
+
+The *Unless* Tag
+----------------
+
+The *unless* tag executes a block of code unless the given condition is
+true. The *unless* tag is the opposite of the *if* tag.  The DTML
+code::
+
+  <dtml-if expr="not butter">
+    I can't believe it's not butter.
+  </dtml-if>
+
+is equivalent to::
+
+  <dtml-unless expr="butter">
+    I can't believe it's not butter.
+  </dtml-unless>
+
+What is the purpose of the *unless* tag? It is simply a convenience
+tag. The *unless* tag is more limited than the *if* tag, since it
+cannot contain an *else* or *elif* tag.
+
+Like the *if* tag, calling the *unless* tag by name does existence
+checking, so::
+
+  <dtml-unless the_easter_bunny>
+    The Easter Bunny does not exist or is not true.
+  </dtml-unless>
+
+Checks for the existence of *the_easter_bunny* as well as its
+truth. While this example only checks for the truth of
+*the_easter_bunny*::
+
+  <dtml-unless expr="the_easter_bunny">
+    The Easter Bunny is not true.
+  </dtml-unless>
+
+This example will raise an exception if *the_easter_bunny* does not
+exist.
+
+Anything that can be done by the *unless* tag can be done by the
+*if* tag.  Thus, its use is totally optional and a matter of
+style.
+
+Batch Processing With The *In* Tag
+----------------------------------
+
+Often you want to present a large list of information but only
+show it to the user one screen at a time.  For example, if a
+user queried your database and got 120 results, you will probably
+only want to show them to the user a small batch, say 10 or 20
+results per page.  Breaking up large lists into parts is called
+*batching*. Batching has a number of benefits.
+
+  o The user only needs to download a reasonably sized document
+  rather than a potentially huge document. This makes pages load
+  faster since they are smaller.
+
+  o Because smaller batches of results are being used, often less
+  memory is consumed by Zope.
+
+  o *Next* and *Previous* navigation interfaces makes scanning
+  large batches relatively easy.
+
+The *in* tag provides several variables to facilitate batch
+processing.  Let's look at a complete example that shows how to
+display 100 items in batches of 10 at a time::
+
+  <dtml-var standard_html_header>
+
+    <dtml-in expr="_.range(100)" size=10 start=query_start>
+
+      <dtml-if sequence-start>
+
+        <dtml-if previous-sequence>
+          <a href="<dtml-var URL><dtml-var sequence-query
+             >query_start=<dtml-var previous-sequence-start-number>">
+             (Previous <dtml-var previous-sequence-size> results)
+          </a>
+        </dtml-if>
+
+        <h1>These words are displayed at the top of a batch:</h1>
+        <ul>
+
+      </dtml-if>
+
+        <li>Iteration number: <dtml-var sequence-item></li>
+
+      <dtml-if sequence-end>
+
+        </ul>
+        <h4>These words are displayed at the bottom of a batch.</h4>
+
+        <dtml-if next-sequence>
+           <a href="<dtml-var URL><dtml-var sequence-query
+              >query_start=<dtml-var
+              next-sequence-start-number>">
+           (Next <dtml-var next-sequence-size> results)
+           </a>
+
+        </dtml-if>
+
+      </dtml-if>
+
+    </dtml-in>
+
+  <dtml-var standard_html_footer>
+
+Let's take a look at the DTML to get an idea of what's going
+on. First we have an *in* tag that iterates over 100 numbers that
+are generated by the *range* utility function. The *size*
+attribute tells the *in* tag to display only 10 items at a
+time. The *start* attribute tells the *in* tag which item number
+to display first.
+
+Inside the *in* tag there are two main *if* tags. The first one
+tests special variable 'sequence-start'. This variable is only
+true on the first pass through the in block. So the contents of
+this if tag will only be executed once at the beginning of the
+loop. The second *if* tag tests for the special variable
+'sequence-end'. This variable is only true on the last pass
+through the *in* tag. So the second *if* block will only be
+executed once at the end.  The paragraph between the *if* tags is
+executed each time through the loop.
+
+Inside each *if* tag there is another *if* tag that check for the
+special variables 'previous-sequence' and 'next-sequence'. The
+variables are true when the current batch has previous or further
+batches respectively. In other words 'previous-sequence' is true
+for all batches except the first, and 'next-sequence' is true for
+all batches except the last. So the DTML tests to see if there are
+additional batches available, and if so it draws navigation links.
+
+The batch navigation consists of links back to the document with a
+*query_start* variable set which indicates where the *in* tag should
+start when displaying the batch. To better get a feel for how this
+works, click the previous and next links a few times and watch how
+the URLs for the navigation links change.
+
+Finally some statistics about the previous and next batches are
+displayed using the 'next-sequence-size' and
+'previous-sequence-size' special variables.  All of this ends up
+generating the following HTML code::
+
+  <html>
+  <head><title>Zope</title>
+  </head>
+  <body bgcolor="#FFFFFF">
+
+    <h1>These words are displayed at the top of a batch:</h1>
+    <ul>
+      <li>Iteration number: 0</li>
+      <li>Iteration number: 1</li>
+      <li>Iteration number: 2</li>
+      <li>Iteration number: 3</li>
+      <li>Iteration number: 4</li>
+      <li>Iteration number: 5</li>
+      <li>Iteration number: 6</li>
+      <li>Iteration number: 7</li>
+      <li>Iteration number: 8</li>
+      <li>Iteration number: 9</li>
+    </ul>
+    <h4>These words are displayed at the bottom of a batch.</h4>
+
+       <a href="http://pdx:8090/batch?query_start=11">
+         (Next 10 results)
+       </a>
+
+  </body>
+  </html>
+
+Another example utilizes the commonly accepted navigation scheme
+of presenting the the user page numbers from which to select::
+
+   <dtml-in "_.range(1,101) "size=10 start=start>
+             <dtml-if sequence-start>
+               <p>Pages: 
+               <dtml-call "REQUEST.set('actual_page',1)">
+               <dtml-in previous-batches mapping>   
+                 <a href="<dtml-var URL><dtml-var sequence-query>start=<dtml-var "_['batch-start-index']+1">">
+                 <dtml-var sequence-number></a>&nbsp;
+                 <dtml-call "REQUEST.set('actual_page',_['sequence-number']+1)">     
+               </dtml-in>
+               <b><dtml-var "_['actual_page']"></b>  
+             </dtml-if>
+             <dtml-if sequence-end>
+               <dtml-in next-batches mapping>&nbsp;
+                  <a href="<dtml-var URL><dtml-var sequence-query>start=<dtml-var "_['batch-start-index']+1">">
+                  <dtml-var "_['sequence-number']+_['actual_page']"></a>
+                </dtml-in>
+             </dtml-if>
+    </dtml-in>
+
+    <dtml-in "_.range(1,101) "size=10 start=start>
+              <br><dtml-var sequence-item>
+    </dtml-in>      
+
+This quick and easy method to display pages is a nice navigational tool
+for larger batches.  It does present the drawback of having to utilize
+an additional *dtml-in* tag to iterate through the actual items, however.
+
+Batch processing can be complex. A good way to work with batches
+is to use the Searchable Interface object to create a batching
+search report for you. You can then modify the DTML to fit your
+needs.  This is explained more in the chapter entitled `Searching
+and Categorizing Content <SearchingZCatalog.html>`_.
+
+Exception Handling Tags
+-----------------------
+
+Zope has extensive exception handling facilities. You can get
+access to these facilities with the *raise* and *try* tags. For more
+information on exceptions and how they are raised and handled see
+a book on Python or you can read the online `Python
+Tutorial <http://www.python.org/doc/current/tut/node10.html>`_.
+
+The *Raise* Tag
+~~~~~~~~~~~~~~~
+
+You can raise exceptions with the *raise* tag. One reason to raise
+exceptions is to signal an error. For example you could check
+for a problem with the *if* tag, and in case there was something
+wrong you could report the error with the *raise* tag.
+
+The *raise* tag has a type attribute for specifying an error type.
+The error type is a short descriptive name for the error. In
+addition, there are some standard error types, like
+*Unauthorized* and *Redirect* that are returned as HTTP
+errors. *Unauthorized* errors cause a log-in prompt to be
+displayed on the user's browser. You can raise HTTP errors to
+make Zope send an HTTP error. For example::
+
+  <dtml-raise type="404">Not Found</dtml-raise>
+
+This raises an HTTP 404 (Not Found) error. Zope responds by
+sending the HTTP 404 error back to the client's browser.
+
+The *raise* tag is a block tag. The block enclosed by the
+*raise* tag is rendered to create an error message. If the
+rendered text contains any HTML markup, then Zope will display
+the text as an error message on the browser, otherwise a generic
+error message is displayed.
+
+Here is a *raise* tag example::
+
+  <dtml-if expr="balance >= debit_amount">
+
+    <dtml-call expr="debitAccount(account, debit_amount)">
+
+    <p><dtml-var debit_amount> has been deducted from your
+    account <dtml-var account>.</p>
+
+  <dtml-else>
+
+    <dtml-raise type="Insufficient funds">
+
+      <p>There is not enough money in account <dtml-account> 
+      to cover the requested debit amount.</p>
+
+    </dtml-raise>
+
+  </dtml-if>
+
+There is an important side effect to raising an exception,
+exceptions cause the current transaction to be rolled back. This
+means any changes made by a web request are ignored. So in
+addition to reporting errors, exceptions allow you to back out
+changes if a problem crops up.
+
+The *Try* Tag
+~~~~~~~~~~~~~
+
+If an exception is raised either manually with the *raise* tag, or
+as the result of some error that Zope encounters, you can catch
+it with the *try* tag.
+
+Exceptions are unexpected errors that Zope encounters during the
+execution of a DTML document or method. Once an exception is
+detected, the normal execution of the DTML stops. Consider the
+following example::
+
+  Cost per unit: <dtml-var
+                       expr="_.float(total_cost/total_units)" 
+                       fmt=dollars-and-cents>
+
+This DTML works fine if *total_units* is not zero. However, if
+*total_units* is zero, a *ZeroDivisionError* exception is raised
+indicating an illegal operation. So rather than rendering the
+DTML, an error message will be returned.
+
+You can use the *try* tag to handle these kind of problems. With
+the *try* tag you can anticipate and handle errors yourself,
+rather than getting a Zope error message whenever an exception
+occurs.
+
+The *try* tag has two functions. First, if an exception is raised,
+the *try* tag gains control of execution and handles the exception
+appropriately, and thus avoids returning a Zope error
+message. Second, the *try* tag allows the rendering of any
+subsequent DTML to continue.
+
+Within the *try* tag are one or more *except* tags that identify and
+handle different exceptions. When an exception is raised, each
+*except* tag is checked in turn to see if it matches the
+exception's type. The first *except* tag to match handles the
+exception. If no exceptions are given in an *except* tag, then the
+*except* tag will match all exceptions.
+
+Here's how to use the *try* tag to avoid errors that could occur
+in the last example::
+
+  <dtml-try>
+
+    Cost per unit: <dtml-var 
+                         expr="_.float(total_cost/total_units)"
+                         fmt="dollars-and-cents">
+
+  <dtml-except ZeroDivisionError> 
+
+    Cost per unit: N/A 
+
+  </dtml-try> 
+
+If a *ZeroDivisionError* is raised, control goes to the *except*
+tag, and "Cost per unit: N/A" is rendered. Once the except tag
+block finishes, execution of DTML continues after the *try* block.
+
+DTML's *except* tags work with Python's class-based
+exceptions. In addition to matching exceptions by name, the
+except tag will match any subclass of the named exception. For
+example, if *ArithmeticError* is named in a *except* tag, the
+tag can handle all *ArithmeticError* subclasses including,
+*ZeroDivisionError*. See a Python reference such as the online
+`Python Library Reference
+<http://www.python.org/doc/current/lib/module-exceptions.html>`_
+for a list of Python exceptions and their subclasses.  An
+*except* tag can catch multiple exceptions by listing them all
+in the same tag.
+
+Inside the body of an *except* tag you can access information
+about the handled exception through several special
+variables.
+
+*error_type*
+    The type of the handled exception. 
+
+*error_value*
+    The value of the handled exception.
+
+*error_tb*
+    The traceback of the handled exception.
+
+You can use these variables to provide error messages to users
+or to take different actions such as sending email to the
+webmaster or logging errors depending on the type of error.
+
+The *Try* Tag Optional *Else* Block
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+The *try* tag has an optional *else* block that is rendered if an
+exception didn't occur.  Here's an example of how to use the
+*else* tag within the try tag::
+
+  <dtml-try> 
+
+    <dtml-call feedAlligators>
+
+  <dtml-except NotEnoughFood WrongKindOfFood>
+
+    <p>Make sure you have enough alligator food first.</p>
+
+  <dtml-except NotHungry> 
+
+    <p>The alligators aren't hungry yet.</p>
+
+  <dtml-except> 
+
+    <p>There was some problem trying to feed the alligators.<p>
+    <p>Error type: <dtml-var error_type></p>
+    <p>Error value: <dtml-var error_value></p>
+
+  <dtml-else> 
+
+    <p>The alligator were successfully fed.</p>
+
+  </dtml-try> 
+
+The first *except* block to match the type of error raised is
+rendered. If an *except* block has no name, then it matches all
+raised errors. The optional *else* block is rendered when no
+exception occurs in the *try* block. Exceptions in the *else*
+block are not handled by the preceding *except* blocks.
+
+The *Try* Tag Optional *Finally* Block
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+You can also use the *try* tag in a slightly different
+way. Instead of handling exceptions, the *try* tag can be used
+not to trap exceptions, but to clean up after them.
+
+The *finally* tag inside the *try* tag specifies a cleanup block
+to be rendered even when an exception occurs.
+
+The *finally* block is only useful if you need to clean up
+something that will not be cleaned up by the transaction abort
+code. The *finally* block will always be called, whether there
+is an exception or not and whether a *return* tag is used or
+not. If you use a *return* tag in the try block, any output of
+the *finally* block is discarded. Here's an example of how you
+might use the *finally* tag::
+
+  <dtml-call acquireLock>  
+  <dtml-try>
+      <dtml-call useLockedResource>
+  <dtml-finally>
+      <!-- this always gets done even if an exception is raised -->
+      <dtml-call releaseLock>
+  </dtml-try>
+
+In this example you first acquire a lock on a resource, then
+try to perform some action on the locked resource. If an
+exception is raised, you don't handle it, but you make sure to
+release the lock before passing control off to an exception
+handler. If all goes well and no exception is raised, you
+still release the lock at the end of the *try* block by
+executing the *finally* block.
+
+The *try/finally* form of the *try* tag is seldom used in
+Zope. This kind of complex programming control is often better
+done in Python or Perl.
+
+Other useful examples
+---------------------
+
+In this section are several useful examples of dtml code.  While
+many of these are most often better done in Python scripts, there
+are occasions when knowing how to accomplish this in dtml is
+worthwhile.
+
+Forwarding a REQUEST
+~~~~~~~~~~~~~~~~~~~~
+
+We have seen how to redirect the user's browser to another page
+with the help of the *call* directive.  However, there are times
+when a redirection is not necessary and a simple forwarding of a
+REQUEST from one dtml-method to another would suffice.  In this
+example, the dtml-method shown obtains a variable named *type*
+from the REQUEST object.  A lookup table is reference to obtain
+the name of the dtml-method to which the REQUEST should be
+forwarded.  The code below accomplishes this::
+
+  <dtml-let lookup="{'a' : 'form15', 'b' : 'form75', 'c' : 'form88'}">
+        <dtml-return "_[lookup[REQUEST.get('type')]]">
+  </dtml-let>
+
+This code looks up the name of the desired dtml-method in the
+lookup table (contained in the *let* statement) and in turn,
+looks up the name of this dtml-method in the current namespace.
+As long as the dtml-method exists, control will be passed to the
+method directly.  This example could be made more complete with
+the addition of exception handling which was discussed above.
+
+Sorting with the '<dtml-in>' tag
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are many times when sorting a result set is necessary.
+The *dtml-in* tag has some very interesting sort capabilities
+for both static and dynamic sorting.  In the example below, a
+ZSQL method is called that returns results from a log table.
+The columns returned are logTime, logType, and userName.  The
+dtml-method or document that contains this code will generate
+links back to itself to re-sort the query based upon certain
+search criteria::
+
+  <dtml-comment>
+
+  The sorting is accomplished by looking up a sort type
+  variable in the REQUEST that is comprised of two parts.  All
+  but the last character indicate the name of the column on
+  which to sort.  The last character of the sort type indicates
+  whether the sort should be ascending or descending.
+
+  </dtml-comment>
+
+  <table>
+    <tr>
+      <td>Time&nbsp;<a href="<dtml-var URL>?st=logTimea">A</a>&nbsp;<a href="<dtml-var URL>?st=logTimed">D</a></td>
+      <td>Type&nbsp;<a href="<dtml-var URL>?st=logTypea">A</a>&nbsp;<a href="<dtml-var URL>?st=logTyped">D</a></td>
+      <td>User&nbsp;<a href="<dtml-var URL>?st=userNamea">A</a>&nbsp;<a href="<dtml-var URL>?st=userNamed">D</a></td>
+    </tr>
+
+    <dtml-comment>The line below sets the default sort</dtml-comment>
+    <dtml-if "REQUEST.get('st')==None"><dtml-call "REQUEST.set('st', 'logTimed')"></dtml-if>
+    <dtml-in getLogData sort_expr="REQUEST.get('st')[0:-1]" reverse_expr="REQUEST.get('st')[-1]=='d'">
+      <tr>
+        <td><dtml-var logTime></td>
+        <td><dtml-var logType></td>
+        <td><dtml-var userName></td>
+      </tr>
+    </dtml-in>
+  </table>
+
+Calling a DTML object from a Python Script
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Although calling a DTML method from a Python script isn't really
+an advanced DTML technique, it deals with DTML, so it's being
+included here.  To call a DTML Method or DTML Document from a
+Python script, the following code is used::
+
+  dtmlMethodName = 'index_html'
+  return context[dtmlMethodName](container, container.REQUEST)
+
+It's as simple as that.  Often this is very useful if you wish
+to forward a request and significant processing is needed to
+determine which dtml object is the target.
+
+Explicit Lookups
+~~~~~~~~~~~~~~~~
+
+Occasionally it is useful to "turn off" acquisition when looking
+up an attribute.  In this example, you have a folder which
+contains sub-folders.  Each sub-folder contains Images.  The
+top-level folder, each subfolder, and each image contain a
+property named *desc*.
+
+If you were to query the Image for its *desc* property it would
+return the *desc* property of it's parent folder if the Image
+did not have the property.  This could cause confusion as the
+Image would appear to have the *desc* property when it really
+belonged to the parent folder.  In most cases, this behavior is
+desired.  However, in this case, the user would like to see
+which images have the *desc* property and which don't.  This is
+accomplished by utilizing *aq_explicit* in the call to the
+object in question.
+
+Given the following structure::
+
+ Folder 
+   |
+   |- Folder1 (desc='Folder one')
+   |- Folder2 (desc='Folder two')
+        |- Image1 (desc='Photo one')
+        |- Image2 
+        |- Image3 (desc='Photo three')
+
+when the second image is asked for its *desc* property it will
+return 'Folder two' based on acquisition rules::
+
+  <dtml-var "Image2.desc">
+
+However, utilizing *aq_explicit* will cause Zope to look only
+in the desired location for the property::
+
+  <dtml-var "Image2.aq_explicit.desc">
+
+This will, of course, raise an exception when the *desc*
+property does not exist.  A safer way to do this is::
+
+  <dtml-if "_.hasattr(Image2.aq_explicit, 'desc')">
+    <dtml-var "Image2.aq_explicit.desc">
+  <dtml-else>
+    No desc property.
+  </dtml-if>
+
+As you can see, this can be very useful.
+
+Conclusion
+----------
+
+DTML provides some very powerful functionality for designing web
+applications.  In this chapter, we looked at the more advanced
+DTML tags and some of their options.  A more complete reference
+can be found in Appendix A.
+
+The next chapter teaches you how to become a Page Template
+wizard. While DTML is a powerful tool, Page Templates provide a
+more elegant solution to HTML generation.

Copied: zope2book/trunk/old/DTML.rst (from rev 96449, zope2book/trunk/source/DTML.rst)
===================================================================
--- zope2book/trunk/old/DTML.rst	                        (rev 0)
+++ zope2book/trunk/old/DTML.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -0,0 +1,1448 @@
+Basic DTML
+==========
+
+DTML (Document Template Markup Language) is a templating facility
+which supports the creation of dynamic HTML and text.  It is
+typically used in Zope to create dynamic web pages.  For example,
+you might use DTML to create a web page which "fills in" rows and
+cells of an HTML table contained within the page from data fetched
+out of a database.
+
+DTML is a *tag-based* presentation and scripting language.  This
+means that *tags* (e.g. '<dtml-var name>') embedded in your HTML
+cause parts of your page to be replaced with "computed" content.
+
+DTML is a "server-side" scripting language.  This means that DTML
+commands are executed by Zope at the server, and the result of that
+execution is sent to your web browser. By contrast, "client-side"
+scripting languages like JavaScript are not processed by the server,
+but are rather sent to and executed by your web browser.
+
+How DTML Relates to Similar Languages and Templating Facilities
+---------------------------------------------------------------
+
+DTML is similar in function to "HTML-embedded" scripting languages
+such as JSP, PHP, or mod_perl.  It differs from these facilities
+inasmuch as it will not allow you to create "inline" Python
+*statements* (if... then.. else..)  in the way that JSP, mod_perl
+or PHP will allow you to embed a block of their respective
+language's code into an HTML page. DTML does allow you to embed
+Python *expressions* (a == 1) into HTML-like tags.  It provides
+flow control and conditional logic by way of "special" HTML tags.
+It is more similar to Perl's 'HTML::Template' package than it is
+to mod_perl in this way.  It can also be compared to the web
+server facility of Server Side Includes (SSI), but with far more
+features and flexibility.
+
+When To Use DTML
+----------------
+
+If you want to make a set of dynamic web pages that share bits of
+content with each other, and you aren't working on a project that
+calls for a tremendous amount of collaboration between programmers
+and tool-wielding designers, DTML works well.  Likewise, if you
+want to dynamically create non-HTML text (like CSS stylesheets or
+email messages), DTML can help.
+
+When Not To Use DTML
+--------------------
+
+If you want code which expresses a set of complex algorithms to be
+maintainable (as "logic" programming should be), you shouldn't
+write it in DTML.  DTML is not a general purpose programming
+language, it instead is a special language designed for formatting
+and displaying content.  While it may be possible to implement
+complex algorithms in DTML, it is often painful.
+
+For example, let's suppose you want to write a web page which
+displays a representation of the famous `Fibonacci sequence
+<http://www.mathacademy.com/pr/prime/articles/fibonac/index.asp>`_.
+You would not want to write the program that actually makes the
+calculation of the Fibonacci numbers by writing DTML.  It could be
+done in DTML, but the result would be difficult to understand and
+maintain.  However, DTML is perfect for describing the page that
+the results of the Fibonnacci calculations are inserted into.  You
+can "call out" from DTML to Script (Python) objects as necessary
+and process the results of the call in DTML.  For example, it is
+`trivial in Python <http://www.python.org/doc/current/tut/node6.html>`_
+(search for the word Fibonacci on this page) to implement a Fibonacci
+sequence generator, and trivial in DTML to create a dynamic web
+page which shows these numbers in a readable format.  If you find
+yourself creating complex and hard-to-understand logic in DTML,
+it's likely time to explore the the Zope features which allow you
+to script "logic" in Python, while letting DTML do the
+presentation "dirty work".
+
+String processing is another area where DTML is likely not the
+best choice.  If you want to manipulate input from a user in a
+complex way, by using functions that manipulate strings, you are
+better off doing it in Python, which has more powerful string
+processing capabilities than DTML.
+
+Zope has a technology named `Zope Page emplates <ZPT.html>`_
+which has purpose similar to DTML.  DTML and ZPT are both
+facilities which allow you to create dynamic HTML.  However, DTML
+is capable of creating dynamic text which is *not* HTML, while ZPT
+is limited to creating text which is HTML (or XML).  DTML also
+allows users to embed more extensive "logic" in the form of
+conditionals and flow-control than does ZPT.  While the source to
+a ZPT page is almost always "well-formed" HTML through its
+lifetime, the source to DTML pages are not guaranteed to be
+"well-formed" HTML, and thus don't play well in many cases with
+external editing tools such as Dreamweaver.
+
+Both ZPT and DTML are fully supported technologies in Zope, and
+neither is "going away" any time soon.  A discussion about when to
+use one instead of the other is available in the chapter entitled
+`Using Basic Zope Objects <BasicObject.html>`_ in the section entitled
+"ZPT vs. DTML: Same Purpose, Different Audiences", but the choice
+is sometimes subjective.
+
+The Difference Between DTML Documents and DTML Methods
+------------------------------------------------------
+
+You can use DTML scripting commands in two types of Zope objects,
+*DTML Documents* and *DTML Methods*.  These two types of DTML
+objects are subtly different from one another, and their
+differences cause many would-be DTML programmers to become
+confused when deciding to use one versus the other.  So what is
+the difference?
+
+DTML Methods are used to carry out actions. They are
+*presentation* objects (as used in the vernacular of the `Using
+Basic Zope Objects`_ chapter).  If you want to
+render the properties or attributes of another object like a DTML
+Document or a Folder, you will use a DTML Method.  DTML Methods do
+not have their own properties.
+
+DTML Documents are *content* objects (in the vernacular used in
+the chapter entitled `Using Basic Zope Objects`_).
+If you want to create a "stand-alone" HTML or text document, you
+might create a DTML Document object to hold the HTML or text.
+DTML Document objects have their own *properties* (attributes),
+unlike DTML Methods.
+
+In almost all cases, you will want to use a DTML Method object to
+perform DTML scripting.  DTML Document objects are an artifact of
+Zope's history that is somewhat unfortunate.  In Zope's earlier
+days, a consensus came about that it was important to have objects
+in Zope that could perform DTML commands but have properties of
+their own.  At the time, the other content objects in Zope, such
+as Files and Images were either nonexistent or had limitations in
+functionality that made the concept of a DTML Document attractive.
+That attraction has waned as Zope's other built-in content objects
+have become more functional.  DTML Documents remain in Zope almost
+solely as a backwards-compatibility measure.  If you never use a
+DTML Document in your work with Zope, you won't miss out on
+much!
+
+Details
+-------
+
+DTML Methods are method objects.  The chapter named `Object
+Orientation <ObjectOrientation.html>`_ discusses the concept of a
+"method".  DTML Methods are *methods* of the folder that
+contains them, and thus they do not have regard for their own
+identity as a Zope object when they are used. For example, if
+you had a folder called Folder and a DTML method in that folder
+called Method::
+
+  AFolder/
+          AMethod
+
+AMethod is a *method* of AFolder. This means that AMethod does not
+have any of it's own attributes or properties.  Instead it uses
+those of AFolder. Suppose you put the following DTML string in
+AMethod::
+
+  <dtml-var id>
+
+When you view the AMethod DTML Method, you will see the string
+'AFolder', which is the 'id' of AMethod's containing Folder
+(AFolder). When this DTML method is viewed, it resolves the name
+'id' to the string which is the value of AFolder's 'id' property.
+
+DTML Documents, on the other hand, are not methods.  They are
+"aware" of their own identity as Zope objects. For example, if
+you created a DTML Document in the folder AFolder called
+ADocument, and you put the above DTML string into ADocument and
+viewed it, it would render to the string 'ADocument'.  It
+resolves the name 'id' to the string which is the value of
+its *own* id, not the id of its containing folder.
+
+.. important::
+   
+   For this chapter, unless stated otherwise, use DTML Methods to
+   hold the example DTML text, as opposed to DTML Documents!**
+
+DTML Tag Syntax
+---------------
+
+DTML contains two kinds of tags, *singleton* and *block* tags.
+Singleton tags consist of one tag enclosed by less-than (&lt;) and
+greater-than (&gt;) symbols.  The *var* tag is an example of a
+singleton tag::
+
+  <dtml-var parrot>
+
+There's no need to close the *var* tag with a '</dtml-var>' tag
+because it is a singleton tag.
+
+Block tags consist of two tags, one that opens the block and one that
+closes the block, and content that goes between them::
+
+  <dtml-in mySequence>
+
+    <!-- this is an HTML comment inside the in tag block -->
+
+  </dtml-in>
+
+The opening tag starts the block and the closing tag ends it. The
+closing tag has the same name as the opening tag with a slash
+preceding it. This is the same convention that HTML and XML use.
+
+DTML Tag Names, Targets, and Attributes
+---------------------------------------
+
+All DTML tags have *names*.  The name is simply the word which
+follows 'dtml-'.  For instance, the name of the DTML tag
+'dtml-var' is 'var', and the name of the DTML tag 'dtml-in' is
+'in'.
+
+Most DTML tags have *targets*.  The target of a DTML tag is just
+the word or expression that, after a space, follows the tag
+name.  For example, the target of the DTML tag '<dtml-var
+standard_html_header>' is 'standard_html_header'.  The target of
+the DTML tag '<dtml-in foo>' is 'foo'.  The target of the DTML
+tag '<dtml-var "objectIds()"> is the expression "objectIds()".
+The target typically refers to the name of an object (or a
+Python expression that resolves to an object) that you wish the
+tag to operate upon.
+
+All DTML tags have *attributes*. An attribute provides
+information about how the tag is supposed to work. Some
+attributes are optional. For example, the *var* tag inserts the
+value of its target. It has an optional *missing* attribute that
+specifies a default value in case the variable can't be found::
+
+  <dtml-var wingspan missing="unknown wingspan">
+
+If the *wingspan* variable is not found then 'unknown wingspan'
+is inserted instead.
+
+Some attributes don't have values. For example, you can convert
+an inserted variable to upper case with the *upper* attribute::
+
+  <dtml-var exclamation upper>
+
+Here we are referencing the *exclamation* target, modifying it
+with the attribute *upper*.  Notice that the *upper* attribute,
+unlike the *missing* attribute doesn't need a value.
+
+See the `DTML Reference <AppendixA.html>`_ appendix for more
+information on the syntax of different DTML tags.
+
+Creating a "Sandbox" for the Examples in This Chapter
+-----------------------------------------------------
+
+You should create a Folder in your Zope's root folder named
+"DTML_Examples" if you intend on creating objects from examples in
+this chapter.  Create the example objects within this "sandbox".
+This prevents you from littering your Zope root folder with DTML
+examples.
+
+Examples of Using DTML for Common Tasks
+---------------------------------------
+
+Below, we show how to use DTML to complete three common tasks:
+inserting text into a web page, displaying results by iterating
+over a sequence, and processing form results.
+
+Inserting Text into HTML with DTML
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+DTML commands are written as tags that begin with *dtml-*.  You
+create dynamic content in DTML by mixing HTML tags and DTML tags
+together.  Inserting the value of a variable (a variable is also
+known as a "target") into HTML is the most basic task that you can
+perform with DTML.  Many DTML tags insert variable values, and
+they all do it in a similar way.  Let's look more closely at how
+Zope inserts variable values.
+
+Create a folder in your sandbox with the id "Feedbags" and the
+title "Bob's Fancy Feedbags". While inside the 'Feedbags' folder,
+create a DTML Method with an id of "pricelist". Note: an
+'id' is how you refer to an object such as a DTML Method
+or a Folder later on; titles are for informational
+purposes only. 
+
+Change the contents of the DTML Method to the following::
+
+  <dtml-var standard_html_header>
+
+  <h1>Price list for <dtml-var title></h1>
+
+  <p>Hemp Bag $2.50</p>
+  <p>Silk Bag $5.00</p>
+
+  <dtml-var standard_html_footer>
+
+Now view the DTML Method by clicking the *View* tab. When you view
+the DTML method this way, it will be *rendered*, which means that
+you will not necessarily see a straight representation of the HTML
+that you typed in to the form.  Instead you will see the
+*rendered* version of the page, which will include the extra text
+provided by DTML by way of the tags you've inserted.  You should
+see something like the figure below:
+
+.. figure:: ../Figures/9-1_bobsfeedbags.png
+
+   Viewing the pricelist method
+
+If you tell your browser to view the HTML source of the Workspace
+frame, you will see something not unlike the below::
+
+  <html>
+    <head><title>Bob's Fancy Feedbags</title>
+    </head>
+    <body bgcolor="#FFFFFF">
+      <h1>Price list for Bob's Fancy Feedbags</h1>
+      <p>Hemp Bag $2.50</p>
+      <p>Silk Bag $5.00</p>
+    </body>
+
+  </html>
+
+That's certainly not what you typed in, is it?
+
+DTML makes the reuse of content and layout possible.  In the
+example above, we've made use of the 'standard_html_header' DTML
+Method and the 'standard_html_footer' DTML Method, both of which
+live in the root folder, to insert HTML text into our page.  These
+DTML methods (and any other DTML method) can be used by other DTML
+methods to insert text into our rendered output.
+
+We've seen that DTML inserts an HTML header, an HTML footer, and a
+title into the web page.  But how does the "var" tag *find* the
+values that it inserts in place of "standard_html_header", "title"
+and "standard_html_footer"?
+
+DTML name lookup is somewhat "magical", because you don't need to
+explicitly tell DTML *where* to find a variable.  Instead, it
+tries to guess what you mean by following a preordained set of
+search rules.  DTML gets the values for variable names by
+searching an environment which includes the current object, the
+containment path, and request variables like values submitted by a
+form and cookies.  The `DTML Name Lookup Rules <AppendixE.html>`_
+represent the namespaces searched and their relative precedence.
+As an example, let's follow the 'pricelist' DTML code
+step-by-step.  In our 'pricelist' method, we've asked DTML to look
+up three names: "standard_html_header", "title", and
+"standard_html_footer".  It searches for these variables in the
+order that they are mentioned in the page.
+
+DTML looks first for "standard_html_header".  It looks in the
+"current object" first, which is its container, the 'Feedbags'
+folder. The 'Feedbags' folder doesn't have any methods or
+properties or sub-objects by that name. Next Zope tries to
+`acquire <Acquisition.html>`_ the object from its containers.  It
+examines the 'Feedbags' folder's container (your sandbox folder,
+likely named "DTML_Examples"), which also doesn't turn up
+anything.  It continues searching through any intermediate
+containters, which also don't have a method or property named
+"standard_html_header" unless you've put one there.  It keeps
+going until it gets to the root folder.  The root folder *does*
+have a sub-object named "standard_html_header", which comes as a
+default object in every Zope. The 'standard_html_header' object is
+a DTML Method. So Zope *calls* the 'standard_html_header' method
+in the root folder and inserts the results into the page.  Note
+that once DTML *finds* a property or variable, if it is callable
+(as in the case of a DTML Method, an External Method, a SQL
+Method, or a Script (Python) object), it is called and the results
+of the call are inserted into the page.
+
+Next DTML looks for the name "title". Here, the search is 
+shorter.  On its first try, DTML finds the 'Feedbags' folder's
+'title' property and inserts it.  The 'title' property is not a
+method or a script, so DTML doesn't need to *call* it.  It just
+renders it into the output.
+
+Finally DTML looks for the name *standard_html_footer*. It has to
+search all the way up to the root folder to find it, just like it
+looked for *standard_html_header*.  It calls the
+*standard_html_footer* in the root and inserts the text result.
+
+The resulting page is fully assembled (rendered) at this point,
+and is sent to your browser.
+
+Understanding how DTML looks up variables is important.  We will
+explore the DTML name lookup mechanism further in the chapter
+entitled `Variables and Advanced DTML <AdvDTML.html>`_.
+It is also documented in `Appendix E <AppendixE.html>`_.
+
+Formatting and Displaying Sequences
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is common that people want to use DTML to format and display
+*sequences*.  A sequence is just a list of items, like "Fred, Joe,
+Jim".  Often, you want to create an HTML table or a bulleted list
+that contains elements in a sequence.  Let's use DTML to call out
+to an object which returns a sequence and render its result.
+
+Create a Script (Python) object named "actors" in your
+sandbox folder. Give the script the following body and
+save it::
+
+  ## Script (Python) "actors"
+  ##bind container=container
+  ##bind context=context
+  ##bind namespace=
+  ##bind script=script
+  ##bind subpath=traverse_subpath
+  ##parameters=
+  ##title=
+  ##
+  return ['Jack Lemmon', 'Ed Harris','Al Pacino', 'Kevin Spacey', 'Alan Arkin']
+
+Make sure that all of the lines of this script line up along the
+left-hand side of the textarea to avoid receiving an error when
+you attempt to save the script, since Python is sensitive to
+indentation.  Don't worry about the '##'s for now, we will
+explain these later.  
+
+This Script (Python) object returns a Python data
+structure which is a *list* of *strings*.  A list is a kind of
+*sequence*, which means that DTML can *iterate* over it using the
+*dtml-in* tag.  Now create a DTML Method named "showActors" in
+your sandbox, give it this body, and save it::
+
+  <html>
+  <body>
+  <h1>Actors in the movie Glengarry Glen Ross</h1>
+  <table border="1">
+    <th>Name</th>
+  <dtml-in actors>
+    <tr>
+    <td><dtml-var sequence-item></td>
+    </tr>
+  </dtml-in>
+  </table>
+  </body>
+  </html>
+
+The DTML *in* tag iterates over the results of the *actors* script
+and inserts a table row into a table for each of the actors
+mentioned in the script.  Note that inside the table cell, we use
+a special name *sequence-item*.  *sequence-item* is a special name
+that is meaningful within a *dtml-in* tag.  It refers to the
+"current item" (in this case, the actor name string) during
+processing.  The HTML source of the Workspace frame when you click
+the *View* tab on the 'showActors' method will look something
+like::
+
+  <html>
+  <body>
+  <h1>Actors in the movie Glengarry Glen Ross</h1>
+  <table border="1">
+    <th>Name</th>
+          <tr>
+    <td>Jack Lemmon</td>
+
+    </tr>
+          <tr>
+    <td>Ed Harris</td>
+    </tr>
+          <tr>
+    <td>Al Pacino</td>
+    </tr>
+          <tr>
+
+    <td>Kevin Spacey</td>
+    </tr>
+          <tr>
+    <td>Alan Arkin</td>
+    </tr>
+        </table>
+  </body>
+  </html>
+
+Note that you didn't have to specifically tell DTML that you are
+querying a Script (Python) object.  You just tell it the name of
+the object to call (in this case 'actors'), and it does the work
+of figuring out how to call the object and pass it appropriate
+arguments. If you replace the 'actors' Script with some other kind
+of object that does exactly the same thing, like another DTML
+Method, you won't have to change your 'showActors' DTML Method.
+It will "just work".
+
+Processing Input from Forms
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can use DTML to perform actions based on the information
+contained in the submission of an HTML form.
+
+Create a DTML Method named "infoForm" with the following body::
+
+  <dtml-var standard_html_header>
+
+  <p>Please send me information on your aardvark adoption
+  program.</p>
+
+  <form action="infoAction">
+  name: <input type="text" name="user_name"><br>
+  email: <input type="text" name="email_addr"><br>
+  <input type="submit" name="submit" value=" Submit ">
+  </form>
+
+  <dtml-var standard_html_footer>
+
+This is a web form that asks the user for information,
+specifically his user name and email address.  Note that you refer
+to the name "infoAction" as the *action* of the HTML form.  This
+really has nothing to do with DTML, it's an attribute of the HTML
+*form* tag.  But the name specified in the form action tag can
+name another Zope object which will receive and process the
+results of the form when it is submitted.
+
+Create a DTML Method named *infoAction* in the same folder as the
+'infoForm' method.  This is the *target* of the 'infoForm' form
+action.  This method will display a bland "thanks" message which
+includes the name and email information that was gathered from the
+web form.  Provide the *infoAction* method with the following body
+and save it::
+
+  <dtml-var standard_html_header>
+
+  <h1>Thanks <dtml-var user_name></h1>
+
+  <p>We received your request for information and will send you
+  email at <dtml-var email_addr> describing our aardvark adoption
+  program as soon as it receives final governmental approval.
+  </p>
+
+  <dtml-var standard_html_footer>
+
+Navigate back to the 'infoForm' method and use the *View* tab to
+execute it.  Fill out the form and click the *Submit* button. If
+all goes well you should see a thank you message that includes
+your name and email address, much like the figure below:
+
+.. figure:: ../Figures/aardvarkview.png
+
+   Result of submitting the infoForm method
+
+The Zope object named *REQUEST* contains information about the
+current web request.  This object is in the DTML name lookup path.
+The 'infoAction' method found the form information from the web
+request that happened when you clicked the submit button on the
+rendering of 'infoForm'.  DTML looks for variables in the current
+web request, so you can just refer to the form variable names in
+the target method by name.  In our case, we were able to display
+the values of the form elements *user_name* and *email_addr* in
+the 'infoAction' method just by referring to them by name in their
+respective *dtml-var* tags.  DTML used its `lookup
+rules <AppendixE.html>`_ to search for the variable names.  It found
+the names in the "REQUEST.form" namespace and displayed them.  If
+it had found an object with either name *email_addr* or
+*user_name* earlier in the lookup (if perhaps there was a Zope
+object in your acquisition path named 'user_name') it would have
+found this object first and rendered its results.  But, mostly by
+chance, it didn't, and found the name in REQUEST instead.
+
+Let's examine the contents of the Zope REQUEST object in order to
+shed more light on the situation.  Create a new DTML Method object
+named 'show_request' in your sandbox folder.  Give it the the
+following body::
+
+  <dtml-var REQUEST>
+
+The 'show_request' method will render a human-readable
+representation of Zope's REQUEST object when you click submit on
+the 'infoForm' rendering.  Visit the 'infoForm' method, and change
+it to the following::
+
+  <dtml-var standard_html_header>
+
+  <p>Please send me information on your aardvark adoption
+  program.</p>
+
+  <form action="show_request">
+  name: <input type="text" name="user_name"><br>
+  email: <input type="text" name="email_addr"><br>
+  <input type="submit" name="submit" value=" Submit ">
+  </form>
+
+  <dtml-var standard_html_footer>
+
+We changed the form action of the 'infoForm' method to
+*show_request*.  Now click the *View* tab of the new 'infoForm'
+method.  Fill in some information in the form elements, and click
+*Submit*.  You will see something like the following::
+
+  form
+   submit ' Submit '
+   email_addr 'chrism at zope.com'
+   user_name 'Chris'
+
+  cookies
+   tree-s 'eJzTiFZ3hANPW/VYHU0ALlYElA'
+
+  lazy items
+   SESSION <bound method SessionDataManager.getSessionData of <SessionDataManager instance at 897d020>
+
+  other
+   AUTHENTICATION_PATH ''
+   user_name 'Chris'
+   PUBLISHED <DTMLMethod instance at 8a62670>
+   submit ' Submit '
+   SERVER_URL 'http://localsaints:8084'
+   email_addr 'chrism at zope.com'
+   tree-s 'eJzTiFZ3hANPW/VYHU0ALlYElA'
+   URL 'http://localsaints:8084/DTML_Example/show_request'
+   AUTHENTICATED_USER admin
+   TraversalRequestNameStack []
+   URL0 http://localsaints:8084/DTML_Example/show_request
+   URL1 http://localsaints:8084/DTML_Example
+   URL2 http://localsaints:8084
+   BASE0 http://localsaints:8084
+   BASE1 http://localsaints:8084
+   BASE2 http://localsaints:8084/DTML_Example
+   BASE3 http://localsaints:8084/DTML_Example/show_request
+
+  environ
+   SCRIPT_NAME ''
+   HTTP_ACCEPT_ENCODING 'gzip, deflate, compress;q=0.9'
+   SERVER_PORT '8084'
+   PATH_TRANSLATED '/DTML_Example/show_request'
+   HTTP_ACCEPT 'text/xml...'
+   GATEWAY_INTERFACE 'CGI/1.1'
+   HTTP_COOKIE 'tree-s="eJzTiFZ3hANPW/VYHU0ALlYElA"'
+   HTTP_ACCEPT_LANGUAGE 'en-us, en;q=0.50'
+   REMOTE_ADDR '192.168.1.3'
+   SERVER_NAME 'saints'
+   HTTP_USER_AGENT 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1a+) Gecko/20020629'
+   HTTP_ACCEPT_CHARSET 'ISO-8859-1, utf-8;q=0.66, *;q=0.66'
+   CONNECTION_TYPE 'keep-alive'
+   channel.creation_time 1027876407
+   QUERY_STRING 'user_name=Chris&email_addr=chrism%40zope.com&submit=+Submit+'
+   SERVER_PROTOCOL 'HTTP/1.1'
+   HTTP_KEEP_ALIVE '300'
+   HTTP_HOST 'localsaints:8084'
+   REQUEST_METHOD 'GET'
+   PATH_INFO '/DTML_Example/show_request'
+   SERVER_SOFTWARE 'Zope/(unreleased version, python 2.1.3, linux2) ZServer/1.1b1'
+   HTTP_REFERER 'http://localsaints:8084/DTML_Example/infoForm'
+
+You have instructed the 'show_request' method to render the
+contents of the web request initiated by the 'infoForm' method.
+Note that each section (form, cookies, lazy items, other, and
+environ) represents a *namespace* inside the REQUEST.  DTML
+searches all of these namespaces for the names you refer to in
+your 'infoForm' form.  Note that *email_addr* and *user_name* are
+in the "form" namespace of the REQUEST.  There is lots of
+information in the rendering of the REQUEST, but for us, this is
+the most pertinent.  For more information on the REQUEST object,
+visit the Zope Help system, and choose Zope Help -> API Reference
+-> Request.
+
+Dealing With Errors
+~~~~~~~~~~~~~~~~~~~
+
+Let's perform an experiment. What happens if you try to view the
+'infoAction' method you created in the last section directly, as
+opposed to getting to it by submitting the 'infoForm' method?
+Click on the 'infoAction' method and then click the *View* tab.
+You will see results not unlike those in the figure below.
+
+.. figure:: ../Figures/infokeyerror.png
+
+   DTML error resulting from a failed variable lookup
+
+Zope couldn't find the *user_name* variable since it was not in
+the current object, its containers or the web request. This is an
+error that you're likely to see frequently as you learn
+Zope. Don't fear, it just means that you've tried to insert a
+variable that Zope can't find.  You can examine the error by
+visiting the *error_log* object in your root folder.  In this
+case, we know why the error occurred, so visiting the error in the
+*error_log* isn't really necessary.  In this example, you need to
+either insert a variable that Zope can find, or use the 'missing'
+attribute on the var tag as described above::
+
+  <h1>Thanks <dtml-var user_name missing="Anonymous User"></h1>
+
+Understanding where DTML looks for variables will help you figure
+out how to fix this kind of problem.  In this case, you have
+viewed a method that needs to be called from an HTML form like
+*infoForm* in order to provide variables to be inserted in the
+output.
+
+Dynamically Acquiring Content
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Zope looks for DTML variables in the current object's containers
+(its parent folders) if it can't find the variable first in the
+current object. This behavior allows your objects to find and use
+content and behavior defined in their parents.  Zope uses the term
+*acquisition* to refer to this dynamic use of content and
+behavior.
+
+An example of acquisition that you've already seen is how web
+pages use standard headers and footers. To acquire the standard
+header just ask Zope to insert it with the *var* tag::
+
+  <dtml-var standard_html_header>
+
+It doesn't matter where the 'standard_html_method' object or
+property is located. Zope will search upwards in the object
+database until it finds the 'standard_html_header' that is defined
+in the root folder.
+
+You can take advantage of how Zope looks up variables to customize
+your header in different parts of your site. Just create a new
+'standard_html_header' in a folder and it will override global
+header for all web pages in your folder and below it.
+
+Create a new folder in your "sandbox" folder with an id of
+"Green". Enter the 'Green' folder and create a DTML Method with an
+id of "welcome". Edit the 'welcome' DTML Method to have these
+contents::
+
+  <dtml-var standard_html_header>
+
+  <p>Welcome</p>
+
+  <dtml-var standard_html_footer>
+
+Now view the 'welcome' method. It should look like a simple web
+page with the word *welcome*, as shown in the figure below.
+
+.. figure:: ../Figures/welcomedtml.png
+
+   Welcome method
+
+Now let's customize the header for the *Green* folder. Create a
+DTML Method in the *Green* folder with an id of
+"standard_html_header". Give it the following body::
+
+  <html>
+  <head>
+    <style type="text/css">
+    body {color: #00FF00;}
+    p {font-family: sans-serif;}
+    </style>
+  </head>
+  <body>
+
+Notice that this is not a complete web page. For example, it does
+not have an ending '</html>' tag.  This is just a fragment of HTML
+that will be used as a header, meant to be included into other
+pages. This header uses `CSS <http://www.w3.org/Style/CSS>`_
+(Cascading Style Sheets) to make some changes to the look and feel
+of web pages.
+
+Now revisit the 'welcome' method and click its *View* tab again.
+You will see something like the figure below:
+
+.. figure:: ../Figures/welcomegreen.png
+
+   Welcome method with custom header
+
+The rendering now looks quite different. This is because it is now
+using the new header we introduced in the 'Green' folder. This
+header will be used by all web pages in the 'Green' folder and its
+sub-folders.
+
+You can continue this process of overriding default content by
+creating another folder inside the 'Green' folder and creating a
+'standard_html_header' DTML Method there. Now web pages in the
+sub-folder will use their local header rather than the 'Green'
+folder's header.  You can of course also create a
+'standard_html_footer', providing it with local content as well.
+
+Using this pattern you can quickly change the look and feel of
+different parts of your website. If you later decide that an area
+of the site needs a different header, just create one. You don't
+have to change the DTML in any of the web pages; they'll
+automatically find the closest header and use it.
+
+Using Python Expressions from DTML
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+So far we've looked at simple DTML tags. Here's an example::
+
+  <dtml-var getHippo>
+
+This will insert the value of the variable named *getHippo*,
+whatever that may be.  DTML will automatically take care of the
+details, like finding the object which represents the variable and
+calling it if necessary. We call this basic tag syntax *name*
+syntax to differentiate it from *expression* syntax.
+
+When you use DTML name syntax, DTML tries to do the right thing to
+insert the results of the object looked up by the variable name,
+no matter what that object may be. In general this means that if
+the variable is another DTML Method or DTML Document, it will be
+called with appropriate arguments.  However, if the variable is
+*not* another DTML Method or DTML Document, and it requires
+parameters, you need to explicitly pass the arguments along using
+an expression.
+
+*Expressions* used in DTML allow you to be more explicit about how
+to find and call variables. Expressions are tag attributes that
+contain small snippets of code in the Python programming language.
+These are typically referred to as *Python expressions*.
+
+A Python expression is essentially any bit of code that *is not* a
+Python *statement*.  For example, the Python statement 'a = 1'
+assigns "1" to the "a" variable. You cannot use this statement in
+DTML expressions.  Likewise, you cannot use the statement 'print
+"x"' in DTML.  It is not an expression.  Essentially, an
+expression must be a combination of values, variables, and Python
+*operators*.  To find out more about Python's expression syntax,
+see the `Python Tutorial <http://www.python.org/doc/current/tut>`_
+at the Python.org website.  For more information specifically about
+the differences between Python expressions and statements, see the
+`Variables, expressions, and statements
+<http://www.ibiblio.org/obp/thinkCSpy/chap02.htm>`_
+chapter of *How To Think Like a Computer Scientist Using Python*.
+
+An expression always results in a return value.  For example, the
+Python expression "a == 5" returns the integer 1 if "a" is equal
+to the integer 5 or the integer 0 if "a" is not equal to the
+integer 5.  The return value of an expression is used by DTML as
+the *target* of the DTML command.
+
+The primary difference in DTML between using *expressions* as
+targets and *names* as targets is that DTML does some magic after
+it locates a *named* targets that it does not do after it finds an
+expression targets.  For example, after finding object with the
+name 'standard_html_header' in the root folder via the name-syntax
+DTML command '<dtml-var standard_html_header>', DTML *calls* the
+'standard_html_header' object, inserting the results into the
+page.  However, when you use an expression-syntax DTML command,
+like '<dtml-var expr="standard_html_header">', DTML *will not*
+call the 'standard_html_header' object.  Instead it will return a
+representation of the object as a string.  In order to *call* the
+'standard_html_header' object in an expression-syntax DTML tag,
+you need to do it explicitly by passing along arguments.  When you
+delve into the realm of DTML expression syntax, DTML "magic" goes
+away, and you need to become aware of the arguments accepted by
+the target (if any) and pass them along.
+
+Let's create a Script (Python) object named 'getHippo' that *must*
+be called in DTML with expression syntax, because it takes a
+non-optional argument that *named* DTML syntax cannot provide.
+
+Create a Script (Python) in your sandbox folder named *getHippo*.
+Provide it with the following body::
+
+  ## Script (Python) "getHippo"
+  ##bind container=container
+  ##bind context=context
+  ##bind namespace=
+  ##bind script=script
+  ##bind subpath=traverse_subpath
+  ##parameters=trap
+  ##title=
+  ##
+  return 'The hippo was captured with a %s.' % trap
+
+Note that this Script (Python) object takes a single parameter
+named "trap".  It is not an optional parameter, so we need to pass
+a value in to this script for it to do anything useful.
+
+Now let's make a DTML method to call 'getHippo'.  Instead of
+letting DTML find and call *getHippo*, we can use an expression to
+explicitly pass arguments.  Create a DTML method named *showHippo*
+and give it the following body::
+
+  <dtml-var expr="getHippo('large net')">
+
+Here we've used a Python expression to explicitly call the
+'getHippo' method with the string argument, 'large net'.  View the
+'showHippo' DTML Method.  It will return a result not unlike the
+following::
+
+    The hippo was captured with a large net.
+
+To see why we need to use expression syntax to call this script,
+let's modify the 'showHippo' method to use DTML name syntax::
+
+  <dtml-var getHippo>
+
+View the method.  You will receive an error not unlike the
+following::
+
+  Error Type: TypeError
+  Error Value: getHippo() takes exactly 1 argument (0 given)
+
+The 'getHippo' method requires that you pass in an argument,
+'trap', that cannot be provided using DTML name syntax.  Thus, you
+receive an error when you try to view the 'showHippo' method.
+
+Expressions make DTML pretty powerful. For example, using Python
+expressions, you can easily test conditions::
+
+    <dtml-if expr="foo < bar">
+      Foo is less than bar.
+    </dtml-if>
+
+Without expressions, this very simple task would have to be broken
+out into a separate method and would add a lot of overhead for
+something this trivial.
+
+Before you get carried away with expressions, take
+care. Expressions can make your DTML hard to understand. Code that
+is hard to understand is more likely to contain errors and is
+harder to maintain. Expressions can also lead to mixing logic in
+your presentation. If you find yourself staring blankly at an
+expression for more than five seconds, stop. Rewrite the DTML
+without the expression and use a Script to do your logic. Just
+because you can do complex things with DTML doesn't mean you
+should.
+
+DTML Expression Gotchas
+%%%%%%%%%%%%%%%%%%%%%%%
+
+Using Python expressions can be tricky. One common mistake is
+to confuse expressions with basic tag syntax. For example::
+
+  <dtml-var objectValues>
+
+and::
+
+  <dtml-var expr="objectValues">
+
+These two examples if you are to put them in a DTML Method will
+end up giving you two completely different results. The first
+example of the DTML *var* tag will automatically *call* the
+object which is represented by *objectValues*. 
+
+In an expression, you have complete control over the variable
+rendering.  In the case of our example, *objectValues* is a
+method implemented in Python which returns the values of the
+objects in the current folder.  It has no required arguments.
+So::
+
+  <dtml-var objectValues>
+
+will call the method.
+However:
+
+  <dtml-var expr="objectValues">
+
+... will *not* call the method, it will just try to insert
+it. The result will be not a list of objects but a string such
+as '<Python Method object at 8681298>'. If you ever see results
+like this, there is a good chance that you're returning a
+method, rather than calling it.
+
+To call a Python method which requires no arguments from an
+expression, you must use standard Python calling syntax by using
+parenthesis::
+
+  <dtml-var expr="objectValues()">
+
+The lesson is that if you use Python expressions you must know
+what kind of variable you are inserting and must use the proper
+Python syntax to appropriately render the variable.
+
+Before we leave the subject of variable expressions we should
+mention that there is a deprecated form of the expression
+syntax. You can leave out the "expr=" part on a variable
+expression tag.  But *please* don't do this.  It is far too easy
+to confuse::
+
+  <dtml-var aName>
+
+with::
+
+  <dtml-var "aName">
+
+and get two completely different results.  These "shortcuts" were
+built into DTML long ago, but we do not encourage you to use them now
+unless you are prepared to accept the confusion and debugging
+problems that come from this subtle difference in syntax.
+
+Common DTML Tags
+----------------
+
+Below, we discuss the most common DTML tags: the *var* tag, the
+*if* tag, the *else* tag, the *elif* tag, and the *in* tag,
+providing examples for the usage of each.
+
+The *Var* Tag
+~~~~~~~~~~~~~
+
+The *var* tag inserts variables into DTML Methods and Documents.  We've
+already seen many examples of how the *var* tag can be used to insert
+strings into web pages.
+
+As you've seen, the *var* tag looks up variables first in the
+current object, then in its containers and finally in the web
+request.
+
+The *var* tag can also use Python expressions to provide more
+control in locating and calling variables.
+
+*Var* Tag Attributes
+%%%%%%%%%%%%%%%%%%%%
+
+You can control the behavior of the *var* tag using its
+attributes. The *var* tag has many attributes that help you in
+common formatting situations. The attributes are summarized in
+Appendix A. Here's a sampling of *var* tag attributes.
+
+html_quote
+  This attribute causes the inserted values to be HTML quoted.  This means
+  that '<', '>' and '&' are escaped.  Note that as of Zope 2.6, all string
+  values which are retrieved from the REQUEST namespace are HTML-quoted by
+  default.  This helps to prevent "cross-site scripting" security holes
+  present in earlier Zope versions, where a user could insert some clever
+  JavaScript into a page in order to possibly make you divulge information
+  to him which could be private.  For more information, see the `CERT
+  advisory <http://www.cert.org/advisories/CA-2000-02.html>`_ on the topic.
+
+missing
+  The missing attribute allows you to specify a default value to use in
+  case Zope can't find the variable. For example::
+
+    <dtml-var bananas missing="We have no bananas">
+
+fmt
+  The fmt attribute allows you to control the format of the *var* tags
+  output. There are many possible formats which are detailed in `Appendix
+  A <AppendixA.html>`_.
+
+  One use of the *fmt* attribute is to format monetary
+  values. For example, create a *float* property in your root
+  folder called *adult_rate*.  This property will represent
+  the cost for one adult to visit the Zoo.  Give this property
+  the value '2.2'.
+
+    % Anonymous User - Oct. 31, 2003 11:02 am:
+     I think this is the first mention of Properties.... Would be
+     helpful to explain that the properties are found with the
+     properties tag....since up until nos almost all additions have
+     been done by the pulldown menu.:)
+
+  You can display this cost in a DTML Document or Method like so::
+
+    One Adult pass: <dtml-var adult_rate fmt=dollars-and-cents>
+
+  This will correctly print "$2.20". It will round more
+  precise decimal numbers to the nearest penny.
+
+
+*Var* Tag Entity Syntax
+%%%%%%%%%%%%%%%%%%%%%%%
+
+Zope provides a shortcut DTML syntax just for the simple *var*
+tag.  Because the *var* tag is a singleton, it can be represented
+with an *HTML entity* like syntax::
+
+  &dtml-cockatiel;
+
+This is equivalent to::
+
+  <dtml-var name="cockatiel" html_quote>
+
+Entity-syntax-based DTML tags always "html quote" their
+renderings.  The main reason to use the entity syntax is to
+avoid putting DTML tags inside HTML tags. For example, instead
+of writing::
+
+  <input type="text" value="<dtml-var name="defaultValue" html_quote>">
+
+You can use the entity syntax to make things more readable for
+you and your text editor::
+
+  <input type="text" value="&dtml-defaultValue;">
+
+The *var* tag entity syntax is very limited. You can't use
+Python expressions within entity-based DTML syntax and many DTML
+attributes won't work with it. See `Appendix A`_
+for more information on *var* tag entity syntax.
+
+The *If* Tag
+~~~~~~~~~~~~
+
+One of DTML's important benefits is to let you customize your web
+pages. Often customization means testing conditions and responding
+appropriately.  This *if* tag lets you evaluate a condition and
+carry out different actions based on the result.
+
+What is a condition?  A condition is either a true or false
+value. In general all objects are considered true unless they are
+0, None, an empty sequence or an empty string.
+
+Here's an example condition:
+
+objectValues
+  True if the variable *objectValues* exists and
+  is true. That is to say, when found and rendered *objectValues*
+  is not 0, None, an empty sequence, or an empty string.
+
+As with the *var* tag, you can use both name syntax and expression
+syntax. Here are some conditions expressed as DTML expressions.
+
+expr="1"
+  Always true.
+
+expr="rhino"
+  True if the rhino variable is true.
+
+expr="x < 5"
+  True if x is less than 5.
+
+expr="objectValues('File')"
+  True if calling the *objectValues* method with an argument of *File*
+  returns a true value.  This method is explained in more detail in this
+  chapter.
+
+The *if* tag is a block tag. The block inside the *if* tag is executed
+if the condition is true.
+
+Here's how you might use a variable expression with the *if* tag to
+test a condition::
+
+  <p>How many monkeys are there?</p>
+
+  <dtml-if expr="monkeys > monkey_limit">
+    <p>There are too many monkeys!</p>
+  </dtml-if>
+
+In the above example, if the Python expression 'monkeys > monkey_limit'
+is true then you will see the first and the second paragraphs of
+HTML. If the condition is false, you will only see the first.
+
+*If* tags can be nested to any depth, for example, you
+could have::
+
+  <p>Are there too many blue monkeys?</p>
+
+  <dtml-if "monkeys.color == 'blue'">
+    <dtml-if expr="monkeys > monkey_limit">
+      <p>There are too many blue monkeys!</p>
+    </dtml-if>
+  </dtml-if>
+
+Nested *if* tags work by evaluating the first condition, and if that
+condition is true, then they evaluate the second
+condition.  In general, DTML *if* tags work very much like
+Python *if* statements...
+
+Name and Expression Syntax Differences
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+The name syntax checks for the *existence* of a name, as well as
+its value. For example::
+
+  <dtml-if monkey_house>
+    <p>There <em>is</em> a monkey house, Mom!</p>
+  </dtml-if>  
+
+If the *monkey_house* variable does not exist, then this condition
+is false. If there is a *monkey_house* variable but it is false,
+then this condition is also false. The condition is only true is
+there is a *monkey_house* variable and it is not 0, None, an empty
+sequence or an empty string.
+
+The Python expression syntax does not check for variable
+existence. This is because the expression must be valid
+Python. For example::
+
+  <dtml-if expr="monkey_house">
+    <p>There <em>is</em> a monkey house, Mom!</p>
+  </dtml-if>
+
+This will work as expected as long as *monkey_house* exists.  If
+the *monkey_house* variable does not exist, Zope will raise a
+*KeyError* exception when it tries to find the variable.
+
+*Else* and *Elif* Tags
+%%%%%%%%%%%%%%%%%%%%%%
+
+The *if* tag only lets you take an action if a condition is
+true. You may also want to take a different action if the
+condition is false.  This can be done with the DTML *else* tag.
+The *if* block can also contain an *else* singleton tag. For
+example::
+
+  <dtml-if expr="monkeys > monkey_limit">
+    <p>There are too many monkeys!</p>
+  <dtml-else>
+    <p>The monkeys are happy!</p>
+  </dtml-if>
+
+The *else* tag splits the *if* tag block into two blocks, the first
+is executed if the condition is true, the second is executed if
+the condition is not true.
+
+A *if* tag block can also contain a *elif* singleton tag. The *elif*
+tag specifies another condition just like an addition *if* tag.
+This lets you specify multiple conditions in one block::
+
+  <dtml-if expr="monkeys > monkey_limit">
+    <p>There are too many monkeys!</p>
+  <dtml-elif expr="monkeys < minimum_monkeys">
+    <p>There aren't enough monkeys!</p>
+  <dtml-else>
+    <p>There are just enough monkeys.</p>
+  </dtml-if>
+
+An *if* tag block can contain any number of *elif* tags but only
+one *else* tag. The *else* tag must always come after the *elif*
+tags.  *Elif* tags can test for condition using either the name
+or expression syntax.
+
+Using Cookies with the *If* Tag
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Let's look at a more meaty *if* tag example.  Often when you have
+visitors to your site you want to give them a cookie to identify
+them with some kind of special value.  Cookies are used frequently
+all over the Internet, and when they are used properly they are
+quite useful.
+
+Suppose we want to differentiate new visitors from folks who have
+already been to our site. When a user visits the site we can set a
+cookie. Then we can test for the cookie when displaying pages. If
+the user has already been to the site they will have the
+cookie. If they don't have the cookie yet, it means that they're
+new.
+
+Suppose we're running a special. First time zoo visitors get in
+for half price. Here's a DTML fragment that tests for a cookie
+using the *hasVisitedZoo* variable and displays the price
+according to whether a user is new or a repeat visitor::
+
+  <dtml-if hasVisitedZoo>
+    <p>Zoo admission <dtml-var adult_rate fmt="dollars-and-cents">.</p>
+  <dtml-else>
+    <p>Zoo admission for first time visitors
+         <dtml-var expr="adult_rate/2" fmt="dollars-and-cents"></p>
+  </dtml-if>  
+
+This fragment tests for the *hasVisitedZoo* variable. If the user
+has visited the zoo before it displays the normal price for
+admission. If the visitor is here for the first time they get in
+for half-price.
+
+Just for completeness sake, here's an implementation of the
+*hasVisitedZoo* method as a Python-based Script that has no
+parameters.::
+
+  ## Script(Python) "hasVisitedZoo"
+  ##
+  """
+  Returns true if the user has previously visited
+  the Zoo. Uses cookies to keep track of zoo visits.
+  """
+  request = context.REQUEST
+  response = request.RESPONSE
+  if request.has_key('zooVisitCookie'):
+      return 1
+  else:
+      response.setCookie('zooVisitCookie', '1')
+      return 0
+
+In the chapter entitled `Advanced Zope Scripting <ScriptingZope.html>`_,
+we'll look more closely at how to script business logic with Python.  For
+now it is sufficient to see that the method looks for a cookie and returns
+a true or false value depending on whether the cookie is found or not.
+Notice how Python uses if and else statements just like DTML uses if and
+*else* tags. DTML's *if* and *else* tags are based on Python's. In fact
+Python also has an elif statement, just like DTML.
+
+The *In* Tag
+~~~~~~~~~~~~
+
+The DTML *in* tag iterates over a sequence of objects, carrying out
+one block of execution for each item in the sequence.  In
+programming, this is often called *iteration*, or *looping*.
+
+The *in* tag is a block tag like the *if* tag.  The content of the *in*
+tag block is executed once for every iteration in the *in* tag
+loop. For example::
+
+  <dtml-in todo_list>
+    <p><dtml-var description></p>
+  </dtml-in>
+
+This example loops over a list of objects named *todo_list*. For
+each item, it inserts an HTML paragraph with a description of
+the to do item.
+
+Iteration is very useful in many web tasks.  Consider a site that
+display houses for sale.  Users will search your site for houses
+that match certain criteria.  You will want to format all of those
+results in a consistent way on the page, therefore, you will need
+to iterate over each result one at a time and render a similar
+block of HTML for each result.
+
+In a way, the contents of an *in* tag block is a kind of *template*
+that is applied once for each item in a sequence.
+
+Iterating over Folder Contents
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Here's an example of how to iterate over the contents of a
+folder. This DTML will loop over all the files in a folder and
+display a link to each one.  This example shows you how to
+display all the "File" objects in a folder, so in order to run
+this example you will need to upload some files into Zope as
+explained in the chapter entitled `Basic Zope Objects`_.
+Create a DTML Method with the following body::
+
+  <dtml-var standard_html_header>
+  <ul>
+  <dtml-in expr="objectValues('File')">
+    <li><a href="&dtml-absolute_url;"><dtml-var title_or_id></a></li>
+  </dtml-in>
+  </ul>
+  <dtml-var standard_html_footer>
+
+This code displayed the following file listing, as shown in the
+figure below.
+
+.. figure:: ../Figures/4-4.png
+
+   Iterating over a list of files
+
+Let's look at this DTML example step by step.  First, the *var*
+tag is used to insert your common header into the method.  Next,
+to indicate that you want the browser to draw an HTML bulleted
+list, you have the *ul* HTML tag.
+
+Then there is the *in* tag.  The tag has an expression that is
+calling the Zope API method called *objectValues*.  This method
+returns a sequence of objects in the current folder that match a
+given criteria.  In this case, the objects must be files.  This
+method call will return a list of files in the current folder.
+
+The *in* tag will loop over every item in this sequence.  If there are
+four file objects in the current folder, then the *in* tag will execute
+the code in its block four times; once for each object in the
+sequence.
+
+During each iteration, the *in* tag looks for variables in the
+current object, first. In the chapter entitled `Variables and
+Advanced DTML`_ we'll look more closely at how DTML
+looks up variables.
+
+For example, this *in* tag iterates over a collection of File
+objects and uses the *var* tag to look up variables in each
+file::
+
+  <dtml-in expr="objectValues('File')">
+    <li><a href="&dtml-absolute_url;"><dtml-var title_or_id></a></li>
+  </dtml-in>
+
+The first *var* tag is an entity and the second is a normal DTML
+*var* tag.  When the *in* tag loops over the first object its
+*absolute_url* and *title_or_id* variables will be inserted in
+the first bulleted list item::
+
+  <ul>
+    <li><a href="http://localhost:8080/FirstFile">FirstFile</a></li>
+
+During the second iteration the second object's *absolute_url*
+and *title_or_id* variables are inserted in the output::
+
+  <ul>
+    <li><a href="http://localhost:8080/FirstFile">FirstFile</a></li>
+    <li><a href="http://localhost:8080/SecondFile">SecondFile</a></li>
+
+This process will continue until the *in* tag has iterated over
+every file in the current folder.  After the *in* tag you
+finally close your HTML bulleted list with a closing *ul* HTML
+tag and the *standard_html_footer* is inserted.
+
+*In* Tag Special Variables
+%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+The *in* tag provides you with some useful information that
+lets you customize your HTML while you are iterating over a
+sequence.  For example, you can make your file library easier to
+read by putting it in an HTML table and making every other table
+row an alternating color, like this, as shown in the figure below.
+
+.. figure:: ../Figures/4-5.png
+
+   File listing with alternating row colors
+
+The *in* tag makes this easy.  Change your file library method a
+bit to look like this::
+
+  <dtml-var standard_html_header>
+
+  <table>
+  <dtml-in expr="objectValues('File')">
+    <dtml-if sequence-even>
+      <tr bgcolor="grey">
+    <dtml-else>
+      <tr>
+    </dtml-if>    
+    <td>
+    <a href="&dtml-absolute_url;"><dtml-var title_or_id></a>
+    </td></tr>
+  </dtml-in>
+  </table>
+
+  <dtml-var standard_html_footer>
+
+Here an *if* tag is used to test for a special variable called
+'sequence-even'.  The *in* tag sets this variable to a true or false
+value each time through the loop.  If the current iteration number is
+even, then the value is true, if the iteration number is odd, it is
+false.
+
+The result of this test is that a *tr* tag with either a gray
+background or no background is inserted for every other object in
+the sequence.  As you might expect, there is a 'sequence-odd' that
+always has the opposite value of 'sequence-even'.
+
+There are many special variables that the *in* tag defines for you.  Here
+are the most common and useful:
+
+sequence-item
+  This special variable is the current item in the
+  iteration.
+
+  In the case of the file library example, each time through the loop
+  the current file of the iteration is assigned to sequence-item.  It
+  is often useful to have a reference to the current object in the
+  iteration.
+
+sequence-index
+  the current number, starting from 0, of iterations
+  completed so far.  If this number is even, 'sequence-even' is true and
+  'sequence-odd' is false.
+
+sequence-number
+  The current number, starting from 1, of iterations
+  completed so far.  This can be thought of as the cardinal position
+  (first, second, third, etc.) of the current object in the loop.
+  If this number is even, 'sequence-even' is false and 'sequence-odd'
+  is true.
+
+sequence-start
+  This variable is true for the very first iteration.
+
+sequence-end
+  This variable is true for the very last iteration.
+
+These special variables are detailed more thoroughly in `Appendix A`_.
+
+Summary
+-------
+
+DTML is a powerful tool for creating dynamic content. It allows you to
+perform fairly complex calculations. In the chapter entitled `Variables and
+Advanced DTML`_, you'll find out about many more DTML tags, and more
+powerful ways to use the tags you already have seen. Despite its power, you
+should resist the temptation to use DTML for complex scripting. In the
+chapter entitled `Advanced Zope Scripting`_ you'll find out about how to
+use Python for scripting business logic.

Modified: zope2book/trunk/source/Acquisition.rst
===================================================================
--- zope2book/trunk/source/Acquisition.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/Acquisition.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -4,11 +4,21 @@
 Acquisition is the technology that allows dynamic behavior to be
 shared between Zope objects via *containment*.
 
-Acquisition's flavor permeates Zope and can be used almost
-everywhere within Zope: in DTML, in Zope Page Templates, in Script
-(Python) objects, and even in Zope URLs.  Because of its ubiquity in
-Zope, a basic understanding of acquisition is important.
+Acquisition's flavor permeates Zope and can be used almost everywhere within
+Zope: in Zope Page Templates, in Script (Python) objects, and even in Zope
+URLs. Because of its ubiquity in Zope, a basic understanding of acquisition is
+important.
 
+Over the years Acquisition has been proven to be a very powerful but often
+too complex technology to use. While it is predictable in simple interactions,
+it gets increasingly complicated to understand its behavior in most
+real-world-sized projects.
+
+In order to understand Zope, you will still need an understanding of
+Acquisition today. Basing your application logic on it is highly
+discouraged, though.
+
+
 Acquisition vs. Inheritance
 ===========================
 
@@ -107,9 +117,9 @@
 The concept behind acquisition is simple:
 
 - Objects are situated inside other objects, and these objects act as
-  their "containers".  For example, the container of a DTML Method
-  named "amethod" inside the DTML_Example folder is the
-  DTML_Example folder.
+  their "containers".  For example, the container of a Page Template
+  named "apage" inside a Folder "afolder" is the
+  "afolder" folder.
 
 - Objects may acquire behavior from their containers.
 
@@ -128,19 +138,21 @@
 Let's toss aside the formal explanations.  Acquisition can be
 best explained with a simple example.
 
-Place a DTML Method named 'acquisition_test' in your Zope root
+Place a Page Template named 'acquisition_test' in your Zope root
 folder.  Give it the following body::
 
   <html>
   <body>
     <p>
-     I am being called from within the <dtml-var title> Folder!
+     I am being called from within the
+     <span tal:replace="context/title" />
+     Folder!
     </p>
   </body>
   </html>
 
-Save it, and then use the DTML Method "View" tab to see the result
-of the DTML method in your Workspace frame.  You will see
+Save it, and then use the Page Template "View" tab to see the result
+of the template in your Workspace frame.  You will see
 something not unlike the following::
 
   I am being called from within the Zope Folder!
@@ -149,7 +161,7 @@
 sense.  Now create a Folder inside your Zope root folder
 named 'AcquisitionTestFolder' and a title of
 "TheAcquisitionTest".  We're going to invoke the
-'acquisition_test' method *in the context of* the
+'acquisition_test' page *in the context of* the
 AcquisitionTestFolder folder.  To do this, assuming your
 Zope is running on your local machine on port 8080, visit
 the URL
@@ -160,7 +172,7 @@
 
 Note that even though an object named 'acquisition_test' does not
 "live" inside the AcquisitionTestFolder folder, Zope found the
-method and displayed a result anyway!  Not only did Zope display a
+page and displayed a result anyway!  Not only did Zope display a
 result, instead of inserting the 'title' of the Zope root folder, it
 inserted the 'title' of the AcquisitionTestFolder folder!
 
@@ -169,8 +181,7 @@
 searching, its containers are searched until the object is found.
 In this way, acquisition can *add behavior* to objects.  In this
 case, we added a behavior to the AcqusitionTestFolder folder that
-it didn't have before (by way of giving it an 'acquisition_test'
-method).
+it didn't have before (by way of adding an 'acquisition_test' page).
 
 Providing Services
 ==================
@@ -178,7 +189,7 @@
 It can be said that acquisition allows objects to acquire
 *services* by way of containment.  For example, our
 AcquisitionTestFolder folder acquired the services of the
-'acquisition_test' method.
+'acquisition_test' page.
 
 Not only do objects *acquire* services, but they also *provide* them. For
 example, adding a Mail Host object to a Folder named 'AFolder'
@@ -208,17 +219,17 @@
 or what?
 
 The answer is that acquisition works on the entire object
-hierarchy. If, for example, you have a DTML Method, "HappySong",
+hierarchy. If, for example, you have a Page Template, "HappySong",
 in the root folder, and also in the root folder you have three
 nested Folders named "Users", "Barney" and "Songs",
 you may call this URL::
 
   /Users/Barney/Songs/HappySong
 
-The HappySong method is found in the root folder, unless one of the
+The HappySong page is found in the root folder, unless one of the
 other folders "Users", "Barney" or "Songs" happens to also have a
-method named "HappySong", in which case *that* method is used instead.
-The HappySong method is searched for first directly in the "Songs"
+page named "HappySong", in which case *that* page is used instead.
+The HappySong page is searched for first directly in the "Songs"
 folder.  If it is not found, the acquisition hierarchy is searched
 starting at the first container in the hierarchy: "Barney".  If it
 is not found in "Barney", the "Users" folder is searched.  If it
@@ -229,10 +240,7 @@
 Acquisition is not limited to searching a containment hierarchy: it
 can also search a *context hierarchy*.  Acquisition by context is
 terribly difficult to explain, and you should avoid it if at all
-possible.  However, if you want more information about acquiring
-via a context, and you are prepared to allow your brain to explode, please
-see the presentation named `Acquisition Algebra
-<http://zope.org/Members/jim/Info/IPC8/AcquisitionAlgebra/index.html>`_.
+possible.
 
 In the example above, for instance, in order to find and publish
 the "HappySong" template at the end of the URL, acquisition searches
@@ -240,7 +248,7 @@
 "Songs" is contained within "Barney", and "Barney" within "Users",
 the *containment hierarchy* for "Songs" consists of each folder "up"
 from "Users" to the root.
-  
+
 Once the "HappySongs" template is found, there are two hierarchies of
 interest:
 
@@ -256,93 +264,8 @@
 
 As with understanding Python's concept of multiple inheritance, explaining
 the exact strategy used to order that search is not within the scope of this
-book.  Please see the following resources for further enlightenment:
+book.
 
-- Jim Fulton's "Acquisition Algebra presentation",
-  http://zope.org/Members/jim/Info/IPC8/AcquisitionAlgebra/index.html
-  is the authoritative theoretical specification for acquisition.
-
-- Shane Hathaway's "Acquisition Explorer (XXX xp?)",
-  http://hathaway.freezope.org/XXX/path/to/aq_explorer
-  allows you to visualize both the containment and context
-  hierarchies.
-
-The example below uses the Zope debugger to examine the two
-acquisition hierarchies.
-
-
-Example:  The Nitty-Gritty Details of the HappySong Acquisition
-===============================================================
-
-Run 'bin/zopectl debug' in your Zope's instance home (don't call
-'get_transaction().commit()' unless you want to make the example
-a permanent part of your Zope!)::
-
-  $ bin/zopectl debug
-  Starting debugger (the name "app" is bound to the top-level Zope object)
-  >>> app.manage_addFolder('Users')
-  >>> users = app.Users
-  >>> users.manage_addFolder('Barney')
-  >>> barney = users.Barney
-  >>> barney.manage_addFolder('Songs')
-  >>> songs = barney.Songs
-  >>> songs.aq_chain  # show the whole chain
-  [<Folder instance at f651b290>, <Folder instance at f651b260>, <Folder instance at f651b230>, <Application instance at f65b0290>]
-  >>> songs.aq_inner.aq_chain # show only containment;  here its the same
-  [<Folder instance at f651b290>, <Folder instance at f651b260>, <Folder instance at f651b230>, <Application instance at f65b0290>]
-
-In the example so far, we can see the *containment hierarchy* for
-the "Songs" folder; because the only objects searched to find
-"Songs" were also in its *containment hierarchy*, the *context
-hierarchy* and *containment hierarchy* are identical.
-
-Now, let's create the "HappySongs" template and examine its
-*containment hierarchy*.  In this case, the two hierarchies are again
-identical::
-
-  >>> app.manage_addDTMLMethod('HappySong', file="""\
-  ... <dtml-if favorite_color>
-  ...   My favorite color is &dtml-favorite_color;.
-  ... <dtml-else>
-  ...   I don't have a favorite color.
-  ... </dtml-if>
-  ... """)
-  ''
-  >>> happy = app.HappySong
-  >>> happy.aq_chain
-  [<DTMLMethod instance at f649d050>, <Application instance at f65b0290>]
-  >>> happy.aq_inner.aq_chain
-  [<DTMLMethod instance at f649d050>, <Application instance at f65b0290>]
-
-Now we will emulate the method the publisher uses to publish the
-URL, '/Users/Barney/Songs/HappySong', fetching it in the context of
-the "Songs" folder::
-
-  >>> happy2 = app.unrestrictedTraverse('/Users/Barney/Songs/HappySong')
-  >>> happy2.aq_chain
-  [<extension class OFS.DTMLMethod.DTMLMethod at f6b0d980>, <extension class OFS.Application.Application at f6a234d0>]
-  >>> happy2.aq_inner.aq_chain
-  [<DTMLMethod instance at f651b320>, <Application instance at f65b0290>]
-
-Note that the *containment* hierarchy (fetched via
-'happy2.aq_inner.aq_chain' ) is the same as in the previous example,
-except that the *context hierarchy* includes all of the folders through
-which we have traversed.
-
-Now let's experiment with finding things via acquisition using both
-hierarchies.  First, we show the case where the template cannot
-acquire 'favorite_color'::
-
-  >>> happy2(songs, {}, None)
-  "  I don't have a favorite color.\n"
-
-Then, we set the 'favorite_color' attribute on one of the items in
-the *context hierarchy*, and the template is able to use it::
-
-  >>> barney.favorite_color = 'purple'
-  >>> happy2(songs, {}, None)
-  '  My favorite color is purple.\n'
-
 Summary
 =======
 
@@ -362,7 +285,3 @@
 between objects in different folders as well.  You will see how
 you can make use of acquisition within different Zope technologies
 in upcoming chapters.
-
-A more exhaustive technical explanation of the underpinnings of
-Zope's acquisition technology is available in the `Zope Developer's
-Guide <http://www.zope.org/Documentation/ZDG/Acquisition.stx>`_.

Deleted: zope2book/trunk/source/AdvDTML.rst
===================================================================
--- zope2book/trunk/source/AdvDTML.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/AdvDTML.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -1,1664 +0,0 @@
-Advanced DTML
-=============
-
-DTML is the kind of language that appears to "do what you mean."
-That is good when it does what you actually want it to do, but when
-it does something you don't want to do, well, it's no fun at all.
-This chapter tells you how to make DTML do what you *really* mean.
-When you're done reading this chapter you will be able to write DTML
-that will accomplish a number of complex tasks including:
-
-- Inspect and Modify the REQUEST object
-
-- Modify the current namespace
-
-- Call other scripts from within DTML
-
-- Send email with or without MIME attachments
-
-- Handle exceptions within DTML    
-
-A few of caveats before getting started:
-
-- It's a good idea to know something about Python before diving into
-  advanced DTML or any other advanced area of Zope.
-
-- Understand the Zope acquisition model and how it works.
-
-- If you are writing very complex functionality in DTML, consider
-  using a Python Script.  This will ease maintenance, not to mention
-  readability.
-
-- Understand the difference between a DTML Document and a DTML
-  Method before embarking on building a huge site. See the explanation
-  included in this chapter.
-
-It's no lie that DTML has a reputation for complexity.  While it is true
-that DTML is really simple if all you want to do is simple layout,
-using DTML for more advanced tasks requires an understanding of where 
-DTML variables come from.
-
-Here's a very tricky error that almost all newbies encounter.
-Imagine you have a DTML Document called *zooName*.  This
-document contains an HTML form like the following::
-
-  <dtml-var standard_html_header>
-
-    <dtml-if zooName>
-
-      <p><dtml-var zooName></p>
-
-    <dtml-else>
-
-      <form action="<dtml-var URL>" method="GET">
-        <input name="zooName">
-        <input type="submit" value="What is zooName?">
-      </form>
-
-    </dtml-if>  
-
-  <dtml-var standard_html_footer>
-
-This looks simple enough, the idea is, this is an HTML page that calls
-itself.  This is because the HTML action is the *URL* variable, which
-will become the URL of the DTML Document.  
-
-If there is a 'zooName' variable, then the page will print it, if there
-isn't, it shows a form that asks for it.  When you click submit, the data
-you enter will make the "if" evaluate to true, and this code should print
-what was entered in the form.
-
-But unfortunately, this is one of those instances where DTML will not do
-what you mean, because the name of the DTML Document that contains this
-DTML is also named *zooName*, and it doesn't use the variable out of the
-request, it uses itself, which causes it to call itself and call itself, ad
-infinitum, until you get an "excessive recursion" error.  So instead of
-doing what you really meant, you got an error. This is what confuses
-beginners.  In the next couple of sections, we'll show you how to fix this
-example to do what you mean.
-
-How Variables are Looked up
----------------------------
-
-There are actually two ways to fix the DTML error in the
-*zooName* document.  The first is that you can rename the document
-to something like *zopeNameFormOrReply* and always remember this
-special exception and never do it; never knowing why it happens.
-The second is to understand how names are looked up, and to be
-explicit about where you want the name to come from in the
-*namespace*.
-
-The DTML namespace is a collection of objects arranged in a *stack*.  A
-stack is a list of objects that can be manipulated by *pushing* and
-*popping* objects on to and off of the stack. 
-
-When a DTML Document or DTML Method is executed, Zope creates a
-DTML namespace to resolve DTML variable names. It's important to
-understand the workings of the DTML namespace so that you can
-accurately predict how Zope will locate variables. Some of the
-trickiest problems you will run into with DTML can be resolved by
-understanding the DTML namespace.
-
-When Zope looks for names in the DTML namespace stack it first looks at
-the topmost object in the stack.  If the name can't be found
-there, then the next item down is introspected.  Zope will work its way
-down the stack, checking each object in turn until it finds the name
-that it is looking for.
-
-If Zope gets all the way down to the bottom of the stack and
-can't find what it is looking for, then an error is generated.  For
-example, try looking for the non-existent name, *unicorn*::
-
-  <dtml-var unicorn>
-
-As long as there is no variable named *unicorn* viewing this
-DTML will return an error, as shown in the figure below.
-
-.. figure:: ../Figures/7-1.png
-
-   DTML error message indicating that it cannot find a variable
-
-But the DTML stack is not all there is to names because DTML
-doesn't start with an empty stack, before you even begin executing
-DTML in Zope there are already a number of objects pushed on the
-namespace stack.
-
-DTML Namespaces
----------------
-
-DTML namespaces are built dynamically for every request in Zope. When
-you call a DTML Method or DTML Document through the web, the DTML
-namespace starts with the same first two stack elements; the client
-object and the request, as shown in the figure below.
-
-.. figure:: ../Figures/7-2.png
-
-   Initial DTML namespace stack
-
-The client object is the first object on the top of the DTML namespace
-stack when entering a transaction (note:  commands exist to push 
-additional parameters onto the namespace stack during a thread of 
-execution).  What the client object is depends on whether you are
-executing a DTML Method or a DTML Document.  In our example above, this
-means that the client object is named *zooName*.  Which is why it
-breaks.  The form input that we really wanted comes from the web
-request, but the client is looked at first.
-
-The request namespace is always on the bottom of the DTML namespace
-stack, and is therefore the last namespace to be looked in for names.
-This means that we must be explicit in our example about which
-namespace we want.  We can do this with the DTML 'with' tag::
-
-  <dtml-var standard_html_header>
-
-    <dtml-with REQUEST only>
-      <dtml-if zooName>
-        <p><dtml-var zooName></p>
-      <dtml-else>
-        <form action="<dtml-var URL>" method="GET">
-          <input name="zooName">
-          <input type="submit" value="What is zooName?">
-        </form>
-      </dtml-if>
-    </dtml-with>
-
-  <dtml-var standard_html_footer>
-
-Here, the with tag says to look in the 'REQUEST' namespace, and *only*
-the 'REQUEST' namespace, for the name "zooName".
-
-DTML Client Object  
-~~~~~~~~~~~~~~~~~~
-
-The client object in DTML depends on whether or not you are executing a
-DTML Method or a DTML Document.  In the case of a Document, the client
-object is always the document itself, or in other words, a DTML
-Document is its own client object.
-
-A DTML Method however can have different kinds of client objects
-depending on how it is called.  For example, if you had a DTML Method
-that displayed all of the contents of a folder then the client object
-would be the folder that is being displayed.  This client object can
-change depending on which folder the method in question is
-displaying.  For example, consider the following DTML Method named
-*list* in the root folder::
-
-  <dtml-var standard_html_header>
-
-  <ul>
-  <dtml-in objectValues>
-    <li><dtml-var title_or_id></li>
-  </dtml-in>
-  </ul>
-
-  <dtml-var standard_html_footer>
-
-Now, what this method displays depends upon how it is used.  If
-you apply this method to the *Reptiles* folder with the URL
-'http://localhost:8080/Reptiles/list', then you will get
-something that looks like the figure below.
-
-.. figure:: ../Figures/7-3.png
-
-   Applying the *list* method to the *Reptiles* folder
-
-But if you were to apply the method to the *Birds* folder with
-the URL *http://localhost:8080/Birds/list* then you would get
-something different, only two items in the list, *Parrot* and
-*Raptors*.
-
-Same DTML Method, different results. In the first example, the client
-object of the *list* method was the *Reptiles* folder.  In the second
-example, the client object was the *Birds* folder. When Zope looked
-up the *objectValues* variable, in the first case it called the
-*objectValues* method of the *Reptiles* folder, in the second case it
-called the *objectValues* method of the *Birds* folder.
-
-In other words, the client object is where variables such as
-methods, and properties are looked up first.
-
-As you saw in "Dynamic Content with DTML", if Zope
-cannot find a variable in the client object, it searches through
-the object's containers.  Zope uses acquisition to automatically
-inherit variables from the client object's containers.  So when
-Zope walks up the object hierarchy looking for variables it
-always starts at the client object, and works its way up from
-there.
-
-DTML Method vs. DTML Document
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-One of the most potentially confusing choices to make for Zope
-newbies is the choice between a DTML Method and a DTML Document.
-Unfortunately, many Zope newbies develop entire sites using one 
-type of object only to discover that they should have used the 
-other type. In general, keep the following items in mind when 
-deciding upon which type to use:
-
-- **Does the object require properties of its own?** If so,
-    use a DTML Document since DTML Methods have no inherent
-    properties.
-
-- **Does the object need to be called as a "page"?** If so,
-    consider using a DTML Document since it will be easier
-    to control such items as page title by using properties.
-
-- **Does the object need transparency to its context?** If so, 
-    you should probably use a DTML Method since these objects
-    act as though they are directly attached to their calling, 
-    or containing object.
-
-DTML Request Object
-~~~~~~~~~~~~~~~~~~~
-
-The request object is the bottom object on the DTML
-namespace stack.  The request contains all of the information
-specific to the current web request.
-
-Just as the client object uses acquisition to look in a number
-of places for variables, so too the request looks up variables
-in a number of places. When the request looks for a variable it
-consults these sources in order:
-
-1. The CGI environment. The `Common Gateway Interface
-   <http://www.w3.org/CGI/>`_, or CGI interface defines
-   a standard set of environment variables to be used by
-   dynamic web scripts.  These variables are provided by Zope
-   in the REQUEST namespace.
-
-2. Form data. If the current request is a form action, then
-   any form input data that was submitted with the request can
-   be found in the REQUEST object.
-
-3. Cookies. If the client of the current request has any cookies
-   these can be found in the current REQUEST object.
-
-4. Additional variables. The REQUEST namespace provides you
-   with lots of other useful information, such as the URL of
-   the current object and all of its parents.
-
-The request namespace is very useful in Zope since it is the
-primary way that clients (in this case, web browsers)
-communicate with Zope by providing form data, cookies and other
-information about themselves. For more information about the
-request object, see Appendix B.
-
-A very simple and enlightening example is to simply render the REQUEST
-object in a DTML Document or Method::
-
-  <dtml-var standard_html_header>
-
-  <dtml-var REQUEST>
-
-  <dtml-var standard_html_footer>
-
-Try this yourself, you should get something that looks like
-the figure below.
-
-.. figure:: ../Figures/7-4.png
-
-   Displaying the request
-
-Since the request comes after the client object, if there are names
-that exist in both the request and the client object, DTML will
-always find them first in the client object. This can be a
-problem. Next, let's look at some ways to get around this problem by
-controlling more directly how DTML looks up variables.
-
-Rendering Variables
--------------------
-
-When you insert a variable using the *var* tag, Zope first looks
-up the variable using the DTML namespace, it then *renders* it
-and inserts the results. Rendering means turning an object or
-value into a string suitable for inserting into the output. Zope
-renders simple variables by using Python's standard method for
-coercing objects to strings. For complex objects such as DTML
-Methods and SQL Methods, Zope will call the object instead of
-just trying to turn it into a string. This allows you to insert
-DTML Methods into other DTML Methods.
-
-In general Zope renders variables in the way you would
-expect. It's only when you start doing more advanced tricks that
-you become aware of the rendering process. Later in this chapter
-we'll look at some examples of how to control rendering using
-the 'getitem' DTML utility function.
-
-Modifying the DTML Namespace
-----------------------------
-
-Now that you know the DTML namespace is a stack, you may
-be wondering how, or even why, new objects get pushed onto it.
-
-Some DTML tags modify the DTML namespace while they are executing.
-A tag may push some object onto the namespace stack during the
-course of execution.  These tags include the *in* tag, the *with*
-tag, and the *let* tag.
-
-*In* Tag Namespace Modifications
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When the *in* tag iterates over a sequence it pushes the current
-item in the sequence onto the top of the namespace stack::
-
-  <dtml-var getId> <!-- This is the id of the client object -->
-
-  <dtml-in objectValues>
-
-    <dtml-var getId> <!-- this is the id of the current item in the 
-                       objectValues sequence -->
-  </dtml-in>
-
-You've seen this many times throughout the examples in this
-book.  While the *in* tag is iterating over a sequence, each item
-is pushed onto the namespace stack for the duration of the
-contents of the in tag block.  When the block is finished
-executing, the current item in the sequence is popped off the
-DTML namespace stack and the next item in the sequence is pushed
-on.
-
-Additional Notes
-%%%%%%%%%%%%%%%%
-
-To be more accurate, the *in* tag pushes a number of items
-onto the namespace stack.  These include sequence variables,
-grouping variables, and batch variables in addition to the
-object itself.  Some of those variables are:
-
-- sequence-item: The current item within the iteration.
-
-- sequence-start: True if the current item is the first item
-  in the sequence.
-
-- sequence-end: True if the current item is the last item in
-   the sequence.
-
-- sequence-length: The length of the sequence. 
-
-- previous-sequence: True on the first iteration if the
-  current batch is not the first one. Batch size is set with the
-  size attribute.
-
-- next-sequence: True on the last iteration if the current
-  batch is not the last batch.
-
-There are many more variables available when using the *in*
-tag.  See `Appendix A <AppendixA.html>`_ for more detail.
-
-The *With* Tag
-~~~~~~~~~~~~~~
-
-The *with* tag pushes an object that you specify onto 
-the namespace stack for the duration of the with block. This
-allows you to specify where variables should be looked up first.
-When the with block closes, the object is popped off the
-namespace stack.
-
-Consider a folder that contains a bunch of methods and
-properties that you are interested in.  You could access those
-names with Python expressions like this::
-
-  <dtml-var standard_html_header>
-
-  <dtml-var expr="Reptiles.getReptileInfo()">
-  <dtml-var expr="Reptiles.reptileHouseMaintainer">
-
-  <dtml-in expr="Reptiles.getReptiles()">
-    <dtml-var species>
-  </dtml-in>
-
-  <dtml-var standard_html_footer>
-
-Notice that a lot of complexity is added to the code just to get
-things out of the *Reptiles* folder. Using the *with* tag you can
-make this example much easier to read::
-
-  <dtml-var standard_html_header>
-
-  <dtml-with Reptiles>
-
-    <dtml-var getReptileInfo>
-    <dtml-var reptileHouseMaintainer>
-
-    <dtml-in getReptiles>
-      <dtml-var species>
-    </dtml-in>
-
-  </dtml-with>
-
-  <dtml-var standard_html_footer>
-
-Another reason you might want to use the *with* tag is to put the
-request, or some part of the request on top of the namespace
-stack. For example suppose you have a form that includes an input
-named *id*. If you try to process this form by looking up the
-*id* variable like so::
-
-  <dtml-var id>
-
-You will not get your form's id variable, but the client
-object's id. One solution is to push the web request's form on
-to the top of the DTML namespace stack using the *with* tag::
-
-  <dtml-with expr="REQUEST.form">
-    <dtml-var id>
-  </dtml-with>
-
-This will ensure that you get the form's id first. See Appendix
-B for complete API documentation of the request object.
-
-If you submit your form without supplying a value for the *id* input,
-the form on top of the namespace stack will do you no good, since the
-form doesn't contain an *id* variable. You'll still get the client
-object's id since DTML will search the client object after failing to
-find the *id* variable in the form. The *with* tag has an attribute
-that lets you trim the DTML namespace to only include the object you
-pushed onto the namespace stack::
-
-  <dtml-with expr="REQUEST.form" only>
-    <dtml-if id>
-      <dtml-var id>
-    <dtml-else>
-      <p>The form didn't contain an "id" variable.</p>
-    </dtml-if>
-  </dtml-with>
-
-Using the *only* attribute allows you to be sure about where
-your variables are being looked up.
-
-The *Let* Tag
-~~~~~~~~~~~~~
-
-The *let* tag lets you push a new namespace onto the namespace stack.
-This namespace is defined by the tag attributes to the *let* tag::
-
-  <dtml-let person="'Bob'" relation="'uncle'">
-    <p><dtml-var person>'s your <dtml-var relation>.</p>
-  </dtml-let>
-
-This would display::
-
-  <p>Bob's your uncle.</p>
-
-The *let* tag accomplishes much of the same goals as the *with*
-tag. The main advantage of the let tag is that you can use it to
-define multiple variables to be used in a block. The *let* tag
-creates one or more new name-value pairs and pushes a
-namespace object containing those variables and their values on
-to the top of the DTML namespace stack. In general the *with*
-tag is more useful to push existing objects onto the namespace
-stack, while the *let* tag is better suited for defining new
-variables for a block.
-
-When you find yourself writing complex DTML that requires things
-like new variables, there's a good chance that you could do the
-same thing better with Python or Perl. Advanced scripting is
-covered in the chapter entitled `Advanced Zope Scripting
-<ScriptingZope.html>`_ .
-
-The DTML namespace is a complex place, and this complexity evolved
-over a lot of time.  Although it helps to understand where names come
-from, it is much more helpful to always be specific about where you
-are looking for a name.  The 'with' and 'let' tags let you alter
-the namespace in order to obtain references to the objects you
-need.
-
-DTML Namespace Utility Functions 
---------------------------------
-
-Like all things in Zope, the DTML namespace is an object, and it can
-be accessed directly in DTML with the *_* (underscore) object.  The
-*_* namespace is often referred to as "the under namespace".
-
-The under namespace provides you with many useful methods for certain
-programming tasks.  Let's look at a few of them.
-
-Say you wanted to print your name three times.  This can be done
-with the *in* tag, but how do you explicitly tell the *in* tag to
-loop three times?  Just pass it a sequence with three items::
-
-  <dtml-var standard_html_header>
-
-  <ul>
-  <dtml-in expr="_.range(3)">
-    <li><dtml-var sequence-item>: My name is Bob.</li>
-  </dtml-in>
-  </ul>
-
-  <dtml-var standard_html_footer>
-
-The '_.range(3)' Python expression will return a sequence of the
-first three integers, 0, 1, and 2.  The *range* function is a
-*standard Python built-in* and many of Python's built-in functions
-can be accessed through the *_* namespace, including:
-
-'range([start,], stop, [step])'
-  Returns a list of integers
-  from 'start' to 'stop' counting 'step' integers at a
-  time. 'start' defaults to 0 and 'step' defaults to 1.  For example:
-
-'_.range(3,10,2)'
-    gives '[3,5,7,9]'.
-
-'_.len(sequence)'
-  'len' returns the size of *sequence* as an integer.
-
-Many of these names come from the Python language, which contains
-a set of special functions called 'built-ins'.  The Python
-philosophy is to have a small number of built-in names.  The Zope
-philosophy can be thought of as having a large, complex array of
-built-in names.
-
-The under namespace can also be used to explicitly control variable
-look up.  There is a very common usage of this syntax.  As mentioned 
-above the in tag defines a number of special variables, like
-*sequence-item* and *sequence-key* that you can use inside a loop to
-help you display and control it.  What if you wanted to use one of
-these variables inside a Python expression?::
-
-  <dtml-var standard_html_header>
-
-  <h1>The squares of the first three integers:</h1>
-  <ul>
-  <dtml-in expr="_.range(3)">
-    <li>The square of <dtml-var sequence-item> is: 
-      <dtml-var expr="sequence-item * sequence-item">
-    </li>
-  </dtml-in>  
-  </ul>  
-
-  <dtml-var standard_html_footer>
-
-Try this, does it work?  No!  Why not?  The problem lies in this
-var tag::
-
-  <dtml-var expr="sequence-item * sequence-item">
-
-Remember, everything inside a Python expression attribute must be
-a *valid Python expression*.  In DTML, *sequence-item* is the name
-of a variable, but in Python this means "The object *sequence*
-minus the object *item*".  This is not what you want.
-
-What you really want is to look up the variable *sequence-item*.
-One way to solve this problem is to use the *in* tag *prefix*
-attribute. For example::
-
-  <dtml-var standard_html_header>
-
-  <h1>The squares of the first three integers:</h1>
-  <ul>
-  <dtml-in prefix="loop" expr="_.range(3)">
-    <li>The square of <dtml-var loop_item> is: 
-      <dtml-var expr="loop_item * loop_item">
-    </li>
-  </dtml-in>  
-  </ul>  
-
-  <dtml-var standard_html_footer>   
-
-The *prefix* attribute causes *in* tag variables to be renamed
-using the specified prefix and underscores, rather than using
-"sequence" and dashes. So in this example, "sequence-item" becomes
-"loop_item". See Appendix A for more information on the *prefix*
-attribute.
-
-Another way to look up the variable *sequence-item* in a DTML
-expression is to use the *getitem* utility function to explicitly
-look up a variable::
-
-  The square of <dtml-var sequence-item> is:
-  <dtml-var expr="_.getitem('sequence-item') * 
-                  _.getitem('sequence-item')">
-
-The *getitem* function takes the name to look up as its first
-argument. Now, the DTML Method will correctly display the square of the
-first three integers.  The *getitem* method takes an optional second
-argument which specifies whether or not to render the variable. Recall
-that rendering a DTML variable means turning it into a string. By
-default the *getitem* function does not render a variable.
-
-Here's how to insert a rendered variable named *myDoc*::
-
-  <dtml-var expr="_.getitem('myDoc', 1)">
-
-This example is in some ways rather pointless, since it's the
-functional equivalent to::
-
-  <dtml-var myDoc>
-
-However, suppose you had a form in which a user got to select
-which document they wanted to see from a list of choices. Suppose
-the form had an input named *selectedDoc* which contained the name
-of the document. You could then display the rendered document like
-so::
-
-  <dtml-var expr="_.getitem(selectedDoc, 1)">
-
-Notice in the above example that *selectedDoc* is not in
-quotes. We don't want to insert the text *selectedDoc*
-we want to insert the value of the variable named *selectedDoc*. For
-example, the value of *selectedDoc* might be 'chapterOne'. Using this
-method, you can look up an item using a dynamic value instead of 
-static text.
-
-If you are a python programmer and you begin using the more
-complex aspects of DTML, consider doing a lot of your work in
-Python scripts that you call *from* DTML.  This is explained more
-in the chapter entitled `Advanced Zope Scripting`_.
-Using Python sidesteps many of the issues in DTML.
-
-DTML Security
--------------
-
-Zope can be used by many different kinds of users.  For example, the
-Zope site, `Zope.org <http://www.zope.org/>`_, has over 11,000 community
-members at the time of this writing.  Each member can log into Zope,
-add objects and news items, and manage their own personal area.
-
-Because DTML is a scripting language, it is very flexible about
-working with objects and their properties.  If there were no security
-system that constrained DTML then a user could potentially create
-malicious or privacy-invading DTML code.
-
-DTML is restricted by standard Zope security settings. So if you
-don't have permission to access an object by going to its URL you
-also don't have permission to access it via DTML. You can't use
-DTML to trick the Zope security system.
-
-For example, suppose you have a DTML Document named *Diary* which
-is private. Anonymous users can't access your diary via the
-web. If an anonymous user views DTML that tries to access your
-diary they will be denied::
-
-  <dtml-var Diary>
-
-DTML verifies that the current user is authorized to access all
-DTML variables.  If the user does not have authorization, then the
-security system will raise an *Unauthorized* error and the user
-will be asked to present more privileged authentication
-credentials.
-
-In the chapter entitled `Users and Security <Security.html>`_ , you
-read about security rules for executable content. There are ways
-to tailor the roles of a DTML Document or Method to allow it to
-access restricted variables regardless of the viewer's roles.
-
-Safe Scripting Limits
----------------------
-
-DTML will not let you gobble up memory or execute infinite loops
-and recursions.  Because the restrictions on looping and memory
-use are relatively tight, DTML is not the right language for
-complex, expensive programming logic.  For example, you cannot
-create huge lists with the *_.range* utility function. You also
-have no way to access the filesystem directly in DTML.
-
-Keep in mind however that these safety limits are simple and can
-be outsmarted by a determined user.  It's generally not a good
-idea to let anyone you don't trust write DTML code on your site.
-
-Advanced DTML Tags
-------------------
-
-In the rest of this chapter we'll look at the many advanced DTML
-tags. These tags are summarized in Appendix A.  DTML has a set of
-built-in tags, as documented in this book, which can be counted on
-to be present in all Zope installations and perform the most
-common kinds of things. However, it is also possible to add new
-tags to a Zope installation. Instructions for doing this are
-provided at the Zope.org website, along with an interesting set
-of contributed DTML tags.
-
-This section covers what could be referred to as Zope
-*miscellaneous* tags.  These tags don't really fit into any broad
-categories except for one group of tags, the *exception handling*
-DTML tags which are discussed at the end of this chapter.
-
-The *Call* Tag
---------------
-
-The *var* tag can call methods, but it also inserts the return
-value. Using the *call* tag you can call methods without inserting
-their return value into the output.  This is useful if you are
-more interested in the effect of calling a method rather than its
-return value.
-
-For example, when you want to change the value of a property,
-*animalName*, you are more interested in the effect of calling the
-*manage_changeProperties* method than the return value the method
-gives you.  Here's an example::
-
-  <dtml-if expr="REQUEST.has_key('animalName')">
-    <dtml-call expr="manage_changeProperties(animalName=REQUEST['animalName'])">
-    <h1>The property 'animalName' has changed</h1>
-  <dtml-else>
-    <h1>No properties were changed</h1>
-  </dtml-if>
-
-In this example, the page will change a property depending on whether
-a certain name exists.  The result of the *manage_changeProperties*
-method is not important and does not need to be shown to the user.
-
-Another common usage of the *call* tag is calling methods that affect
-client behavior, like the 'RESPONSE.redirect' method.  In this
-example, you make the client redirect to a different page, to
-change the page that gets redirected, change the value for the
-"target" variable defined in the *let* tag::
-
-  <dtml-var standard_html_header>
-
-  <dtml-let target="'http://example.com/new_location.html'">
-
-    <h1>This page has moved, you will now be redirected to the
-    correct location.  If your browser does not redirect, click <a
-    href="<dtml-var target>"><dtml-var target></a>.</h1>
-
-    <dtml-call expr="RESPONSE.redirect(target)">
-
-  </dtml-let>
-
-  <dtml-var standard_html_footer>  
-
-In short, the *call* tag works exactly like the *var* tag with the
-exception that it doesn't insert the results of calling the
-variable.
-
-Another possibility for use of the *call* tag would be to call a
-ZSQL Method or or preprocess the REQUEST.  Two examples of calling
-a ZSQL method::
-
-  <dtml-call "insertLogEntry(REQUEST)">
-
-or::
-
-  <dtml-call "insertLogEntry(logInfo=REQUEST.get('URL0'), severity=1)">
-
-To call a python script that might do any number of things,
-including preprocessing the REQUEST::
-
-  <dtml-call "preprocess(REQUEST)">
-
-The *Comment* Tag
------------------
-
-DTML can be documented with comments using the *comment* tag::
-
-  <dtml-var standard_html_header>
-
-  <dtml-comment>
-
-    This is a DTML comment and will be removed from the DTML code
-    before it is returned to the client.  This is useful for
-    documenting DTML code.  Unlike HTML comments, DTML comments
-    are NEVER sent to the client.
-
-  </dtml-comment>
-
-  <!-- 
-
-    This is an HTML comment, this is NOT DTML and will be treated
-    as HTML and like any other HTML code will get sent to the
-    client.  Although it is customary for an HTML browser to hide
-    these comments from the end user, they still get sent to the
-    client and can be easily seen by 'Viewing the Source' of a
-    document.
-
-  -->
-
-  <dtml-var standard_html_footer>        
-
-The *comment* block is removed from DTML output.
-
-In addition to documenting DTML you can use the *comment* tag to
-temporarily comment out other DTML tags. Later you can remove the
-*comment* tags to re-enable the DTML.
-
-The *Tree* Tag
---------------
-
-The *tree* tag lets you easily build dynamic trees in HTML to
-display hierarchical data.  A *tree* is a graphical representation
-of data that starts with a "root" object that has objects
-underneath it often referred to as "branches".  Branches can have
-their own branches, just like a real tree.  This concept should be
-familiar to anyone who has used a file manager program like
-Microsoft Windows Explorer to navigate a file system.  And, in
-fact, the left hand "navigation" view of the Zope management
-interface is created using the tree tag.
-
-For example here's a tree that represents a collection of folders
-and sub-folders.
-
-.. figure:: ../Figures/7-5.png
-
-   HTML tree generated by the tree tag
-
-Here's the DTML that generated this tree display::
-
-  <dtml-var standard_html_header>
-
-  <dtml-tree>
-
-    <dtml-var getId>
-
-  </dtml-tree>
-
-  <dtml-var standard_html_footer>
-
-The *tree* tag queries objects to find their sub-objects and takes
-care of displaying the results as a tree. The *tree* tag block works
-as a template to display nodes of the tree.
-
-Now, since the basic protocol of the web, HTTP, is stateless, you
-need to somehow remember what state the tree is in every time you
-look at a page.  To do this, Zope stores the state of the tree in
-a *cookie*.  Because this tree state is stored in a cookie, only
-one tree can appear on a web page at a time, otherwise they will
-confusingly use the same cookie.
-
-You can tailor the behavior of the *tree* tag quite a bit with *tree*
-tag attributes and special variables. Here is a sampling of *tree*
-tag attributes.
-
-branches
-  The name of the method used to find sub-objects. This
-  defaults to *tpValues*, which is a method defined by a number of
-  standard Zope objects.
-
-leaves
-  The name of a method used to display objects that do
-  not have sub-object branches.
-
-nowrap
-  Either 0 or 1. If 0, then branch text will wrap to fit in
-  available space, otherwise, text may be truncated. The default
-  value is 0.
-
-sort
-  Sort branches before text insertion is performed. The
-  attribute value is the name of the attribute that items should be
-  sorted on.
-
-assume_children
-  Either 0 or 1. If 1, then all objects are
-  assumed to have sub-objects, and will therefore always have a
-  plus sign in front of them when they are collapsed. Only when an
-  item is expanded will sub-objects be looked for. This could be a
-  good option when the retrieval of sub-objects is a costly
-  process.  The defalt value is 0.
-
-single
-  Either 0 or 1. If 1, then only one branch of the tree can
-  be expanded. Any expanded branches will collapse when a new branch
-  is expanded.  The default value is 0.
-
-skip_unauthorized
-  Either 0 or 1. If 1, then no errors will be
-  raised trying to display sub-objects for which the user does not
-  have sufficient access. The protected sub-objects are not
-  displayed.  The default value is 0.
-
-Suppose you want to use the *tree* tag to create a dynamic site
-map. You don't want every page to show up in the site map. Let's
-say that you put a property on folders and documents that you want
-to show up in the site map.
-
-Let's first define a Script with the id of *publicObjects*
-that returns public objects::
-
-  ## Script (Python) "publicObjects"
-  ##
-  """
-  Returns sub-folders and DTML documents that have a
-  true 'siteMap' property.
-  """
-  results=[]
-  for object in context.objectValues(['Folder', 'DTML Document']):
-      if object.hasProperty('siteMap') and object.siteMap:
-          results.append(object)
-  return results
-
-Now we can create a DTML Method that uses the *tree* tag and our
-Scripts to draw a site map::
-
-  <dtml-var standard_html_header>
-
-  <h1>Site Map</h1>
-
-  <p><a href="&dtml-URL0;?expand_all=1">Expand All</a> |
-     <a href="&dtml-URL0;?collapse_all=1">Collapse All</a>
-  </p>
-
-  <dtml-tree branches="publicObjects" skip_unauthorized="1">
-    <a href="&dtml-absolute_url;"><dtml-var title_or_id></a>
-  </dtml-tree>
-
-  <dtml-var standard_html_footer>
-
-This DTML Method draws a link to all public resources and displays
-them in a tree. Here's what the resulting site map looks like.
-
-.. figure:: ../Figures/7-6.png
-
-   Dynamic site map using the tree tag
-
-For a summary of the *tree* tag arguments and special variables see
-Appendix A.
-
-The *Return* Tag
-----------------
-
-In general DTML creates textual output. You can however, make DTML
-return other values besides text. Using the *return* tag you can
-make a DTML Method return an arbitrary value just like a Python or
-Perl-based Script.
-
-Here's an example::
-
-  <p>This text is ignored.</p>
-
-  <dtml-return expr="42">
-
-This DTML Method returns the number 42.
-
-Another upshot of using the *return* tag is that DTML execution
-will stop after the *return* tag.
-
-If you find yourself using the *return* tag, you almost certainly
-should be using a Script instead. The *return* tag was developed
-before Scripts, and is largely useless now that you can easily
-write scripts in Python and Perl.
-
-The *Sendmail* Tag
-------------------
-
-The *sendmail* tag formats and sends a mail messages. You can use
-the *sendmail* tag to connect to an existing Mail Host, or you can
-manually specify your SMTP host.
-
-Here's an example of how to send an email message with the
-*sendmail* tag::
-
-  <dtml-sendmail>
-  To: <dtml-var recipient>
-  From: <dtml-var sender>
-  Subject: Make Money Fast!!!!
-
-  Take advantage of our exciting offer now! Using our exclusive method
-  you can build unimaginable wealth very quickly. Act now!
-  </dtml-sendmail>
-
-Notice that there is an extra blank line separating the mail
-headers from the body of the message.
-
-A common use of the *sendmail* tag is to send an email message
-generated by a feedback form. The *sendmail* tag can contain any
-DTML tags you wish, so it's easy to tailor your message with form
-data.
-
-The *Mime* Tag
---------------
-
-The *mime* tag allows you to format data using MIME (Multipurpose
-Internet Mail Extensions). MIME is an Internet standard for
-encoding data in email message. Using the *mime* tag you can use
-Zope to send emails with attachments.
-
-Suppose you'd like to upload your resume to Zope and then have Zope
-email this file to a list of potential employers.
-
-Here's the upload form::
-
-  <dtml-var standard_html_header>
-
-  <p>Send you resume to potential employers</p>
-
-  <form method=post action="sendresume" ENCTYPE="multipart/form-data">
-  <p>Resume file: <input type="file" name="resume_file"></p>
-  <p>Send to:</p>
-  <p>
-  <input type="checkbox" name="send_to:list" value="jobs at yahoo.com">
-    Yahoo<br>
-
-  <input type="checkbox" name="send_to:list" value="jobs at microsoft.com">
-    Microsoft<br>
-
-  <input type="checkbox" name="send_to:list" value="jobs at mcdonalds.com">
-    McDonalds</p>
-
-  <input type=submit value="Send Resume">
-  </form>
-
-  <dtml-var standard_html_footer>
-
-Note:  The text *:list* added to the name of the input fields directs 
-Zope to treat the received information as a list type. For example if 
-the first two checkboxes were selected in the above upload form, the 
-REQUEST variable send_to would have the value [jobs at yahoo.com, jobs at microsoft.com]
-
-Create another DTML Method called *sendresume* to process the form
-and send the resume file::
-
-  <dtml-var standard_html_header>
-
-  <dtml-if send_to>
-
-    <dtml-in send_to> 
-
-      <dtml-sendmail smtphost="my.mailserver.com">
-      To: <dtml-var sequence-item>
-      Subject: Resume
-      <dtml-mime type=text/plain encode=7bit>
-
-      Hi, please take a look at my resume.
-
-      <dtml-boundary type=application/octet-stream disposition=attachment 
-      encode=base64><dtml-var expr="resume_file.read()"></dtml-mime>
-      </dtml-sendmail>
-
-    </dtml-in>
-
-    <p>Your resume was sent.</p>
-
-  <dtml-else>
-
-    <p>You didn't select any recipients.</p>
-
-  </dtml-if>
-
-  <dtml-var standard_html_footer>    
-
-This method iterates over the *sendto* variable and sends one
-email for each item.
-
-Notice that there is no blank line between the 'To:' header and
-the starting *mime* tag.  If a blank line is inserted between them
-then the message will not be interpreted as a *multipart* message
-by the receiving mail reader.
-
-Also notice that there is no newline between the *boundary* tag
-and the *var* tag, or the end of the *var* tag and the closing
-*mime* tag.  This is important, if you break the tags up with
-newlines then they will be encoded and included in the MIME part,
-which is probably not what you're after.
-
-As per the MIME spec, *mime* tags may be nested within *mime* tags
-arbitrarily.
-
-The *Unless* Tag
-----------------
-
-The *unless* tag executes a block of code unless the given condition is
-true. The *unless* tag is the opposite of the *if* tag.  The DTML
-code::
-
-  <dtml-if expr="not butter">
-    I can't believe it's not butter.
-  </dtml-if>
-
-is equivalent to::
-
-  <dtml-unless expr="butter">
-    I can't believe it's not butter.
-  </dtml-unless>
-
-What is the purpose of the *unless* tag? It is simply a convenience
-tag. The *unless* tag is more limited than the *if* tag, since it
-cannot contain an *else* or *elif* tag.
-
-Like the *if* tag, calling the *unless* tag by name does existence
-checking, so::
-
-  <dtml-unless the_easter_bunny>
-    The Easter Bunny does not exist or is not true.
-  </dtml-unless>
-
-Checks for the existence of *the_easter_bunny* as well as its
-truth. While this example only checks for the truth of
-*the_easter_bunny*::
-
-  <dtml-unless expr="the_easter_bunny">
-    The Easter Bunny is not true.
-  </dtml-unless>
-
-This example will raise an exception if *the_easter_bunny* does not
-exist.
-
-Anything that can be done by the *unless* tag can be done by the
-*if* tag.  Thus, its use is totally optional and a matter of
-style.
-
-Batch Processing With The *In* Tag
-----------------------------------
-
-Often you want to present a large list of information but only
-show it to the user one screen at a time.  For example, if a
-user queried your database and got 120 results, you will probably
-only want to show them to the user a small batch, say 10 or 20
-results per page.  Breaking up large lists into parts is called
-*batching*. Batching has a number of benefits.
-
-  o The user only needs to download a reasonably sized document
-  rather than a potentially huge document. This makes pages load
-  faster since they are smaller.
-
-  o Because smaller batches of results are being used, often less
-  memory is consumed by Zope.
-
-  o *Next* and *Previous* navigation interfaces makes scanning
-  large batches relatively easy.
-
-The *in* tag provides several variables to facilitate batch
-processing.  Let's look at a complete example that shows how to
-display 100 items in batches of 10 at a time::
-
-  <dtml-var standard_html_header>
-
-    <dtml-in expr="_.range(100)" size=10 start=query_start>
-
-      <dtml-if sequence-start>
-
-        <dtml-if previous-sequence>
-          <a href="<dtml-var URL><dtml-var sequence-query
-             >query_start=<dtml-var previous-sequence-start-number>">
-             (Previous <dtml-var previous-sequence-size> results)
-          </a>
-        </dtml-if>
-
-        <h1>These words are displayed at the top of a batch:</h1>
-        <ul>
-
-      </dtml-if>
-
-        <li>Iteration number: <dtml-var sequence-item></li>
-
-      <dtml-if sequence-end>
-
-        </ul>
-        <h4>These words are displayed at the bottom of a batch.</h4>
-
-        <dtml-if next-sequence>
-           <a href="<dtml-var URL><dtml-var sequence-query
-              >query_start=<dtml-var
-              next-sequence-start-number>">
-           (Next <dtml-var next-sequence-size> results)
-           </a>
-
-        </dtml-if>
-
-      </dtml-if>
-
-    </dtml-in>
-
-  <dtml-var standard_html_footer>
-
-Let's take a look at the DTML to get an idea of what's going
-on. First we have an *in* tag that iterates over 100 numbers that
-are generated by the *range* utility function. The *size*
-attribute tells the *in* tag to display only 10 items at a
-time. The *start* attribute tells the *in* tag which item number
-to display first.
-
-Inside the *in* tag there are two main *if* tags. The first one
-tests special variable 'sequence-start'. This variable is only
-true on the first pass through the in block. So the contents of
-this if tag will only be executed once at the beginning of the
-loop. The second *if* tag tests for the special variable
-'sequence-end'. This variable is only true on the last pass
-through the *in* tag. So the second *if* block will only be
-executed once at the end.  The paragraph between the *if* tags is
-executed each time through the loop.
-
-Inside each *if* tag there is another *if* tag that check for the
-special variables 'previous-sequence' and 'next-sequence'. The
-variables are true when the current batch has previous or further
-batches respectively. In other words 'previous-sequence' is true
-for all batches except the first, and 'next-sequence' is true for
-all batches except the last. So the DTML tests to see if there are
-additional batches available, and if so it draws navigation links.
-
-The batch navigation consists of links back to the document with a
-*query_start* variable set which indicates where the *in* tag should
-start when displaying the batch. To better get a feel for how this
-works, click the previous and next links a few times and watch how
-the URLs for the navigation links change.
-
-Finally some statistics about the previous and next batches are
-displayed using the 'next-sequence-size' and
-'previous-sequence-size' special variables.  All of this ends up
-generating the following HTML code::
-
-  <html>
-  <head><title>Zope</title>
-  </head>
-  <body bgcolor="#FFFFFF">
-
-    <h1>These words are displayed at the top of a batch:</h1>
-    <ul>
-      <li>Iteration number: 0</li>
-      <li>Iteration number: 1</li>
-      <li>Iteration number: 2</li>
-      <li>Iteration number: 3</li>
-      <li>Iteration number: 4</li>
-      <li>Iteration number: 5</li>
-      <li>Iteration number: 6</li>
-      <li>Iteration number: 7</li>
-      <li>Iteration number: 8</li>
-      <li>Iteration number: 9</li>
-    </ul>
-    <h4>These words are displayed at the bottom of a batch.</h4>
-
-       <a href="http://pdx:8090/batch?query_start=11">
-         (Next 10 results)
-       </a>
-
-  </body>
-  </html>
-
-Another example utilizes the commonly accepted navigation scheme
-of presenting the the user page numbers from which to select::
-
-   <dtml-in "_.range(1,101) "size=10 start=start>
-             <dtml-if sequence-start>
-               <p>Pages: 
-               <dtml-call "REQUEST.set('actual_page',1)">
-               <dtml-in previous-batches mapping>   
-                 <a href="<dtml-var URL><dtml-var sequence-query>start=<dtml-var "_['batch-start-index']+1">">
-                 <dtml-var sequence-number></a>&nbsp;
-                 <dtml-call "REQUEST.set('actual_page',_['sequence-number']+1)">     
-               </dtml-in>
-               <b><dtml-var "_['actual_page']"></b>  
-             </dtml-if>
-             <dtml-if sequence-end>
-               <dtml-in next-batches mapping>&nbsp;
-                  <a href="<dtml-var URL><dtml-var sequence-query>start=<dtml-var "_['batch-start-index']+1">">
-                  <dtml-var "_['sequence-number']+_['actual_page']"></a>
-                </dtml-in>
-             </dtml-if>
-    </dtml-in>
-
-    <dtml-in "_.range(1,101) "size=10 start=start>
-              <br><dtml-var sequence-item>
-    </dtml-in>      
-
-This quick and easy method to display pages is a nice navigational tool
-for larger batches.  It does present the drawback of having to utilize
-an additional *dtml-in* tag to iterate through the actual items, however.
-
-Batch processing can be complex. A good way to work with batches
-is to use the Searchable Interface object to create a batching
-search report for you. You can then modify the DTML to fit your
-needs.  This is explained more in the chapter entitled `Searching
-and Categorizing Content <SearchingZCatalog.html>`_.
-
-Exception Handling Tags
------------------------
-
-Zope has extensive exception handling facilities. You can get
-access to these facilities with the *raise* and *try* tags. For more
-information on exceptions and how they are raised and handled see
-a book on Python or you can read the online `Python
-Tutorial <http://www.python.org/doc/current/tut/node10.html>`_.
-
-The *Raise* Tag
-~~~~~~~~~~~~~~~
-
-You can raise exceptions with the *raise* tag. One reason to raise
-exceptions is to signal an error. For example you could check
-for a problem with the *if* tag, and in case there was something
-wrong you could report the error with the *raise* tag.
-
-The *raise* tag has a type attribute for specifying an error type.
-The error type is a short descriptive name for the error. In
-addition, there are some standard error types, like
-*Unauthorized* and *Redirect* that are returned as HTTP
-errors. *Unauthorized* errors cause a log-in prompt to be
-displayed on the user's browser. You can raise HTTP errors to
-make Zope send an HTTP error. For example::
-
-  <dtml-raise type="404">Not Found</dtml-raise>
-
-This raises an HTTP 404 (Not Found) error. Zope responds by
-sending the HTTP 404 error back to the client's browser.
-
-The *raise* tag is a block tag. The block enclosed by the
-*raise* tag is rendered to create an error message. If the
-rendered text contains any HTML markup, then Zope will display
-the text as an error message on the browser, otherwise a generic
-error message is displayed.
-
-Here is a *raise* tag example::
-
-  <dtml-if expr="balance >= debit_amount">
-
-    <dtml-call expr="debitAccount(account, debit_amount)">
-
-    <p><dtml-var debit_amount> has been deducted from your
-    account <dtml-var account>.</p>
-
-  <dtml-else>
-
-    <dtml-raise type="Insufficient funds">
-
-      <p>There is not enough money in account <dtml-account> 
-      to cover the requested debit amount.</p>
-
-    </dtml-raise>
-
-  </dtml-if>
-
-There is an important side effect to raising an exception,
-exceptions cause the current transaction to be rolled back. This
-means any changes made by a web request are ignored. So in
-addition to reporting errors, exceptions allow you to back out
-changes if a problem crops up.
-
-The *Try* Tag
-~~~~~~~~~~~~~
-
-If an exception is raised either manually with the *raise* tag, or
-as the result of some error that Zope encounters, you can catch
-it with the *try* tag.
-
-Exceptions are unexpected errors that Zope encounters during the
-execution of a DTML document or method. Once an exception is
-detected, the normal execution of the DTML stops. Consider the
-following example::
-
-  Cost per unit: <dtml-var
-                       expr="_.float(total_cost/total_units)" 
-                       fmt=dollars-and-cents>
-
-This DTML works fine if *total_units* is not zero. However, if
-*total_units* is zero, a *ZeroDivisionError* exception is raised
-indicating an illegal operation. So rather than rendering the
-DTML, an error message will be returned.
-
-You can use the *try* tag to handle these kind of problems. With
-the *try* tag you can anticipate and handle errors yourself,
-rather than getting a Zope error message whenever an exception
-occurs.
-
-The *try* tag has two functions. First, if an exception is raised,
-the *try* tag gains control of execution and handles the exception
-appropriately, and thus avoids returning a Zope error
-message. Second, the *try* tag allows the rendering of any
-subsequent DTML to continue.
-
-Within the *try* tag are one or more *except* tags that identify and
-handle different exceptions. When an exception is raised, each
-*except* tag is checked in turn to see if it matches the
-exception's type. The first *except* tag to match handles the
-exception. If no exceptions are given in an *except* tag, then the
-*except* tag will match all exceptions.
-
-Here's how to use the *try* tag to avoid errors that could occur
-in the last example::
-
-  <dtml-try>
-
-    Cost per unit: <dtml-var 
-                         expr="_.float(total_cost/total_units)"
-                         fmt="dollars-and-cents">
-
-  <dtml-except ZeroDivisionError> 
-
-    Cost per unit: N/A 
-
-  </dtml-try> 
-
-If a *ZeroDivisionError* is raised, control goes to the *except*
-tag, and "Cost per unit: N/A" is rendered. Once the except tag
-block finishes, execution of DTML continues after the *try* block.
-
-DTML's *except* tags work with Python's class-based
-exceptions. In addition to matching exceptions by name, the
-except tag will match any subclass of the named exception. For
-example, if *ArithmeticError* is named in a *except* tag, the
-tag can handle all *ArithmeticError* subclasses including,
-*ZeroDivisionError*. See a Python reference such as the online
-`Python Library Reference
-<http://www.python.org/doc/current/lib/module-exceptions.html>`_
-for a list of Python exceptions and their subclasses.  An
-*except* tag can catch multiple exceptions by listing them all
-in the same tag.
-
-Inside the body of an *except* tag you can access information
-about the handled exception through several special
-variables.
-
-*error_type*
-    The type of the handled exception. 
-
-*error_value*
-    The value of the handled exception.
-
-*error_tb*
-    The traceback of the handled exception.
-
-You can use these variables to provide error messages to users
-or to take different actions such as sending email to the
-webmaster or logging errors depending on the type of error.
-
-The *Try* Tag Optional *Else* Block
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-The *try* tag has an optional *else* block that is rendered if an
-exception didn't occur.  Here's an example of how to use the
-*else* tag within the try tag::
-
-  <dtml-try> 
-
-    <dtml-call feedAlligators>
-
-  <dtml-except NotEnoughFood WrongKindOfFood>
-
-    <p>Make sure you have enough alligator food first.</p>
-
-  <dtml-except NotHungry> 
-
-    <p>The alligators aren't hungry yet.</p>
-
-  <dtml-except> 
-
-    <p>There was some problem trying to feed the alligators.<p>
-    <p>Error type: <dtml-var error_type></p>
-    <p>Error value: <dtml-var error_value></p>
-
-  <dtml-else> 
-
-    <p>The alligator were successfully fed.</p>
-
-  </dtml-try> 
-
-The first *except* block to match the type of error raised is
-rendered. If an *except* block has no name, then it matches all
-raised errors. The optional *else* block is rendered when no
-exception occurs in the *try* block. Exceptions in the *else*
-block are not handled by the preceding *except* blocks.
-
-The *Try* Tag Optional *Finally* Block
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-You can also use the *try* tag in a slightly different
-way. Instead of handling exceptions, the *try* tag can be used
-not to trap exceptions, but to clean up after them.
-
-The *finally* tag inside the *try* tag specifies a cleanup block
-to be rendered even when an exception occurs.
-
-The *finally* block is only useful if you need to clean up
-something that will not be cleaned up by the transaction abort
-code. The *finally* block will always be called, whether there
-is an exception or not and whether a *return* tag is used or
-not. If you use a *return* tag in the try block, any output of
-the *finally* block is discarded. Here's an example of how you
-might use the *finally* tag::
-
-  <dtml-call acquireLock>  
-  <dtml-try>
-      <dtml-call useLockedResource>
-  <dtml-finally>
-      <!-- this always gets done even if an exception is raised -->
-      <dtml-call releaseLock>
-  </dtml-try>
-
-In this example you first acquire a lock on a resource, then
-try to perform some action on the locked resource. If an
-exception is raised, you don't handle it, but you make sure to
-release the lock before passing control off to an exception
-handler. If all goes well and no exception is raised, you
-still release the lock at the end of the *try* block by
-executing the *finally* block.
-
-The *try/finally* form of the *try* tag is seldom used in
-Zope. This kind of complex programming control is often better
-done in Python or Perl.
-
-Other useful examples
----------------------
-
-In this section are several useful examples of dtml code.  While
-many of these are most often better done in Python scripts, there
-are occasions when knowing how to accomplish this in dtml is
-worthwhile.
-
-Forwarding a REQUEST
-~~~~~~~~~~~~~~~~~~~~
-
-We have seen how to redirect the user's browser to another page
-with the help of the *call* directive.  However, there are times
-when a redirection is not necessary and a simple forwarding of a
-REQUEST from one dtml-method to another would suffice.  In this
-example, the dtml-method shown obtains a variable named *type*
-from the REQUEST object.  A lookup table is reference to obtain
-the name of the dtml-method to which the REQUEST should be
-forwarded.  The code below accomplishes this::
-
-  <dtml-let lookup="{'a' : 'form15', 'b' : 'form75', 'c' : 'form88'}">
-        <dtml-return "_[lookup[REQUEST.get('type')]]">
-  </dtml-let>
-
-This code looks up the name of the desired dtml-method in the
-lookup table (contained in the *let* statement) and in turn,
-looks up the name of this dtml-method in the current namespace.
-As long as the dtml-method exists, control will be passed to the
-method directly.  This example could be made more complete with
-the addition of exception handling which was discussed above.
-
-Sorting with the '<dtml-in>' tag
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-There are many times when sorting a result set is necessary.
-The *dtml-in* tag has some very interesting sort capabilities
-for both static and dynamic sorting.  In the example below, a
-ZSQL method is called that returns results from a log table.
-The columns returned are logTime, logType, and userName.  The
-dtml-method or document that contains this code will generate
-links back to itself to re-sort the query based upon certain
-search criteria::
-
-  <dtml-comment>
-
-  The sorting is accomplished by looking up a sort type
-  variable in the REQUEST that is comprised of two parts.  All
-  but the last character indicate the name of the column on
-  which to sort.  The last character of the sort type indicates
-  whether the sort should be ascending or descending.
-
-  </dtml-comment>
-
-  <table>
-    <tr>
-      <td>Time&nbsp;<a href="<dtml-var URL>?st=logTimea">A</a>&nbsp;<a href="<dtml-var URL>?st=logTimed">D</a></td>
-      <td>Type&nbsp;<a href="<dtml-var URL>?st=logTypea">A</a>&nbsp;<a href="<dtml-var URL>?st=logTyped">D</a></td>
-      <td>User&nbsp;<a href="<dtml-var URL>?st=userNamea">A</a>&nbsp;<a href="<dtml-var URL>?st=userNamed">D</a></td>
-    </tr>
-
-    <dtml-comment>The line below sets the default sort</dtml-comment>
-    <dtml-if "REQUEST.get('st')==None"><dtml-call "REQUEST.set('st', 'logTimed')"></dtml-if>
-    <dtml-in getLogData sort_expr="REQUEST.get('st')[0:-1]" reverse_expr="REQUEST.get('st')[-1]=='d'">
-      <tr>
-        <td><dtml-var logTime></td>
-        <td><dtml-var logType></td>
-        <td><dtml-var userName></td>
-      </tr>
-    </dtml-in>
-  </table>
-
-Calling a DTML object from a Python Script
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Although calling a DTML method from a Python script isn't really
-an advanced DTML technique, it deals with DTML, so it's being
-included here.  To call a DTML Method or DTML Document from a
-Python script, the following code is used::
-
-  dtmlMethodName = 'index_html'
-  return context[dtmlMethodName](container, container.REQUEST)
-
-It's as simple as that.  Often this is very useful if you wish
-to forward a request and significant processing is needed to
-determine which dtml object is the target.
-
-Explicit Lookups
-~~~~~~~~~~~~~~~~
-
-Occasionally it is useful to "turn off" acquisition when looking
-up an attribute.  In this example, you have a folder which
-contains sub-folders.  Each sub-folder contains Images.  The
-top-level folder, each subfolder, and each image contain a
-property named *desc*.
-
-If you were to query the Image for its *desc* property it would
-return the *desc* property of it's parent folder if the Image
-did not have the property.  This could cause confusion as the
-Image would appear to have the *desc* property when it really
-belonged to the parent folder.  In most cases, this behavior is
-desired.  However, in this case, the user would like to see
-which images have the *desc* property and which don't.  This is
-accomplished by utilizing *aq_explicit* in the call to the
-object in question.
-
-Given the following structure::
-
- Folder 
-   |
-   |- Folder1 (desc='Folder one')
-   |- Folder2 (desc='Folder two')
-        |- Image1 (desc='Photo one')
-        |- Image2 
-        |- Image3 (desc='Photo three')
-
-when the second image is asked for its *desc* property it will
-return 'Folder two' based on acquisition rules::
-
-  <dtml-var "Image2.desc">
-
-However, utilizing *aq_explicit* will cause Zope to look only
-in the desired location for the property::
-
-  <dtml-var "Image2.aq_explicit.desc">
-
-This will, of course, raise an exception when the *desc*
-property does not exist.  A safer way to do this is::
-
-  <dtml-if "_.hasattr(Image2.aq_explicit, 'desc')">
-    <dtml-var "Image2.aq_explicit.desc">
-  <dtml-else>
-    No desc property.
-  </dtml-if>
-
-As you can see, this can be very useful.
-
-Conclusion
-----------
-
-DTML provides some very powerful functionality for designing web
-applications.  In this chapter, we looked at the more advanced
-DTML tags and some of their options.  A more complete reference
-can be found in Appendix A.
-
-The next chapter teaches you how to become a Page Template
-wizard. While DTML is a powerful tool, Page Templates provide a
-more elegant solution to HTML generation.

Modified: zope2book/trunk/source/AdvZPT.rst
===================================================================
--- zope2book/trunk/source/AdvZPT.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/AdvZPT.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -24,7 +24,7 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 You've already seen how 'tal:content' and 'tal:replace' work in
-the chapter entitled `Using Zope Page Templates`_. In
+the chapter entitled `Using Zope Page Templates  <ZPT.html>`_. In
 this section you'll learn some advanced tricks for inserting
 content.
 
@@ -41,25 +41,24 @@
 precede the expression with the 'structure' keyword.
 
 This feature is useful when you are inserting a fragment of
-HTML or XML that is stored in a property or generated by
+HTML or XML that is stored by an object or generated by
 another Zope object.  For instance, you may have news items
 that contain simple HTML markup such as bold and italic text
 when they are rendered, and you want to preserve this when
 inserting them into a "Top News" page.  In this case, you
 might write::
 
-  <p tal:repeat="newsItem here/topNews"
+  <p tal:repeat="newsItem context/topNews"
      tal:content="structure newsItem">
     A news item with<code>HTML</code> markup.
   </p>
 
-This will insert the news items' HTML into a series of
-paragraphs.  The built-in variable 'here' refers to the folder
-in which the template is rendered; See the "Expressions"
-section further below in this chapter for more information on
-'here'.  In this case, we use 'here' as the starting point for
-finding the Zope object 'topNews', which is presumably a list
-of news items or a Script which fetches such a list.
+This will insert the news items' HTML into a series of paragraphs. The built-in
+variable 'context' refers to the folder in which the template is rendered; See
+the "Expressions" section further below in this chapter for more information on
+'context'. In this case, we use 'context' as the starting point for finding the
+Zope object 'topNews', which is presumably a list of news items or a Script
+which fetches such a list.
 
 The 'structure' keyword prevents the text of each newsItem
 value from being escaped.  It doesn't matter whether the text
@@ -102,7 +101,7 @@
 Most often you will want to selectively include default
 content, rather than always including it. For example::
 
-  <p tal:content="python:here.getFood() or default">Spam</p>
+  <p tal:content="python:context.getFood() or default">Spam</p>
 
 .. note:
    
@@ -115,7 +114,7 @@
 
 You've already seen most of what you can do with the
 'tal:repeat' statement in the chapter entitled `Using Zope Page
-Templates`_. This section covers a few advanced features
+Templates  <ZPT.html>`_. This section covers a few advanced features
 of the 'tal:repeat' statement.
 
 Repeat Variables
@@ -141,12 +140,6 @@
 - *length* - length of the sequence, which will be the total number
   of repetitions.
 
-- *letter* - count reps with lower-case letters: "a" - "z",
-  "aa" - "az", "ba" - "bz", ..., "za" - "zz", "aaa" - "aaz", and
-  so forth.
-
-- *Letter* - upper-case version of *letter*.
-
 You can access the contents of a repeat variable using path
 expressions or Python expressions.  In path expressions, you
 write a three-part path consisting of the name 'repeat', the
@@ -169,7 +162,7 @@
 it from appearing in the rendered page. You can do this with
 the 'tal:omit-tag' statement::
 
-  <div tal:repeat="section here/getSections"
+  <div tal:repeat="section context/getSections"
        tal:omit-tag="">
     <h4 tal:content="section/title">Title</h4>
     <p tal:content="section/text">quotation</p>
@@ -197,33 +190,18 @@
     </tr>
   </table>
 
-This example uses Python expressions, which are covered later
-in this chapter.
+This example uses Python expressions, which are covered later in this chapter.
 
-If you've done much work with the 'dtml-in' DTML repetition
-statement, you will have encountered batching. Batching is the
-process of chopping up a large list into smaller lists. You
-typically use it to display a small number of items from a
-large list on a web page. Think of how a search engine batches
-its search results. The 'tal:repeat' statement does not
-support batching, but Zope comes with a batching utility. See
-the section, "Batching" later in this chapter.
+One useful feature that isn't supplied by 'tal:repeat' is sorting. If you want
+to sort a list you can either write your own sorting script (which is quite
+easy in Python) or you can use the 'sequence.sort' utility function. Here's an
+example of how to sort a list of objects by title::
 
-Another useful feature that isn't supplied by 'tal:repeat' is
-sorting. If you want to sort a list you can either write
-your own sorting script (which is quite easy in Python) or you
-can use the 'sequence.sort' utility function. Here's an
-example of how to sort a list of objects by title, and then by
-modification date::
-
-  <table tal:define="objects here/objectValues;
-                     sort_on python:(('title', 'nocase', 'asc'),
-                                     ('bobobase_modification_time', 'cmp', 'desc'));
+  <table tal:define="objects context/objectValues;
+                     sort_on python:(('title', 'nocase', 'asc'),);
                      sorted_objects python:sequence.sort(objects, sort_on)">
     <tr tal:repeat="item sorted_objects">
       <td tal:content="item/title">title</td>
-      <td tal:content="item/bobobase_modification_time">
-        modification date</td>  
     </tr>
   </table>
 
@@ -246,14 +224,14 @@
 "href" and a "class" attribute::
 
   <a href="link"
-     tal:attributes="href here/getLink;
-                     class here/getClass">link</a>
+     tal:attributes="href context/getLink;
+                     class context/getClass">link</a>
 
 You can also define attributes with XML namespaces. For example::
 
   <Description 
       dc:Creator="creator name"
-      tal:attributes="dc:Creator here/owner/getUserName">
+      tal:attributes="dc:Creator context/owner/getUserName">
     Description</Description>
 
 Simply put the XML namespace prefix before the attribute name
@@ -294,29 +272,23 @@
 are no items, you want to show a message.  To do this, place the
 following before the list::
 
-  <h4 tal:condition="not:container/objectIds">There
-  Are No Items</h4>
+  <h4 tal:condition="not:container/objectIds">
+    There Are No Items
+  </h4>
 
 The expression, 'not:container/objectIds' is true when
 'container/objectIds' is false, and vice versa. See the section,
 "Not Expressions" later in this chapter for more information.
 
-You can't use your 'items' variable here, because it isn't
-defined yet.  If you move the definition of 'items' to the 'h4'
-element, then you can't use it in the 'ul' element any more, because it
-becomes a *local* variable of the 'h4' element.  You could place the
-definition on some element that enclosed both the 'h4' and the 'ul',
-but there is a simpler solution.  By placing the keyword
-'global' in front of the variable name, you can make the
-definition last from the 'span' tag to the bottom of the
-template::
+You can't use your 'items' variable here, because it isn't defined yet. If you
+move the definition of 'items' to the 'h4' element, then you can't use it in
+the 'ul' element any more, because it becomes a *local* variable of the 'h4'
+element. To have it available on both tags, you can place the definition on
+some element that encloses both the 'h4' and the 'ul' for example the 'body'.
 
-  <span tal:define="global items container/objectIds"></span>
-  <h4 tal:condition="not:items">There Are No Items</h4>
+You can define more than one variable using 'tal:define' by separating them
+with semicolons. For example::
 
-You can define more than one variable using 'tal:define' by
-separating them with semicolons. For example::
-
   <p tal:define="ids container/objectIds; 
                  title container/title">
 
@@ -325,13 +297,11 @@
 earlier defined variables in later definitions. For example::
 
   <p tal:define="title template/title;
-                 global untitled not:title;
+                 untitled not:title;
                  tlen python:len(title);">
 
-In this case, both 'title' and 'tlen' are local to the
-paragraph, but 'untitled' is global. With judicious use of
-'tal:define' you can improve the efficiency and readability of
-your templates.
+With judicious use of 'tal:define' you can improve the efficiency and
+readability of your templates.
 
 Omitting Tags
 ~~~~~~~~~~~~~
@@ -360,7 +330,7 @@
 This will produce a list of friends, with our "best" friend's
 name in bold.
 
-Error Handling  
+Error Handling
 ~~~~~~~~~~~~~~
 
 If an error occurs in your page template, you can catch that
@@ -369,7 +339,7 @@
 variable using form data::
 
   ...
-  <span tal:define="global prefs request/form/prefs"
+  <span tal:define="prefs request/form/prefs"
         tal:omit-tag="" />
   ...
 
@@ -380,7 +350,7 @@
 'tal:on-error' statement::
 
   ...
-  <span tal:define="global prefs here/scriptToGetPreferences"
+  <span tal:define="prefs context/scriptToGetPreferences"
         tal:omit-tag=""
         tal:on-error="string:An error occurred">
   ...
@@ -402,7 +372,7 @@
 For more flexible error handling you can call a script. For
 example::
 
-  <div tal:on-error="structure here/handleError">
+  <div tal:on-error="structure context/handleError">
   ...
   </div>
 
@@ -552,13 +522,13 @@
 can make up any tag name you like within the TAL namespace, and
 use it to make an element, like so::
 
-  <tal:series define="items here/getItems">
+  <tal:series define="items context/getItems">
     <tal:items repeat="item items">
     <tal:parts repeat="part item">
-      <part tal:content="part">Part</part>
+      <p tal:content="part">Part</p>
     </tal:parts>
     </tal:items>
-    <noparts tal:condition="not:items" />
+    <p tal:condition="not:items">No parts!</p>
   </tal:series>
 
 The 'tal:series', 'tal:items', and 'tal:parts' tags in this
@@ -573,27 +543,11 @@
 Form Processing
 ~~~~~~~~~~~~~~~
 
-You can process forms in DTML using a common pattern called the
-"form/action pair".  A form/action pair consists of two DTML
-methods or documents: one that contains a form that collects
-input from the user, and one that contains an action that is
-taken on that input and returns the user a response.  The form
-calls the action.  See the chapter entitled `Dynamic Content
-with DTML <DTML.html>`_ for more information on the form/action
-pattern.
+With Zope Page Templates you can use the form/action/response pattern. The form
+and response should be Page Templates and the action should be a script. The
+form template gathers the input and calls the action script. The action script
+should process the input and return a response template.
 
-Zope Page Templates don't work particularly well with the
-form/action pattern since it assumes that input processing and
-response presentation are handled by the same object (the
-action). Instead of the form/action pattern you should use
-form/action/response pattern with Page Templates. The form and
-response should be Page Templates and the action should be a
-script. The form template gathers the input and calls the action
-script. The action script should process the input and return a
-response template. This pattern is more flexible than the
-form/action pattern since it allows the script to return any of
-a number of different response objects.
-
 For example here's a part of a form template::
 
   ...
@@ -635,7 +589,7 @@
 
 This script validates the form input and returns the form
 template with an error message if there's a problem. The
-Script's 'context' variable is equivalent to 'here' in
+Script's 'context' variable is equivalent to 'context' in
 TALES. You can pass Page Templates extra information with
 keyword arguments. The keyword arguments are available to the
 template via the 'options' built-in variable. So the form
@@ -662,12 +616,11 @@
 create a version of the form-action pair using Page Templates
 alone. You should only do this when you don't care about error
 handling and when the response will always be the same, no
-matter what the user submits. Since Page Templates don't have an
-equivalent of 'dtml-call', you can use one of any number of
+matter what the user submits. You can use one of any number of
 hacks to call an input processing method without inserting its
 results. For example::
 
-  <span tal:define="unused here/processInputs" 
+  <span tal:define="unused context/processInputs" 
         tal:omit-tag=""/>
 
 This sample calls the 'processInputs' method and assigns the
@@ -730,22 +683,21 @@
   from fixed locations, no matter where your template is placed or
   called.
 
-'here'
+'context'
   The object on which the template is being called.
   This is often the same as the *container*, but can be different
   if you are using acquisition.  Use this to get Zope objects that
   you expect to find in different places depending on how the
-  template is called. The 'here' variable is analogous to the
-  'context' variable in Python-based scripts.
+  template is called.
 
 'container'
   The container (usually a Folder) in which the
   template is kept.  Use this to get Zope objects from locations
   relative to the template's permanent home. The 'container' and
-  'here' variables refer to the same object when a template is
+  'context' variables refer to the same object when a template is
   called from its normal location. However, when a template is
   applied to another object (for example, a ZSQL Method) the
-  'container' and 'here' will not refer to the same object.
+  'container' and 'context' will not refer to the same object.
 
 'modules'
   The collection of Python modules available to
@@ -832,11 +784,11 @@
 
 When a path doesn't exist, you may have a fall-back path or
 value that you would like to use instead.  For instance, if
-'request/form/x' doesn't exist, you might want to use 'here/x'
+'request/form/x' doesn't exist, you might want to use 'context/x'
 instead.  You can do this by listing the paths in order of
 preference, separated by vertical bar characters ('|')::
 
-  <h4 tal:content="request/form/x | here/x">Header</h4>
+  <h4 tal:content="request/form/x | context/x">Header</h4>
 
 Two variables that are very useful as the last path in a list
 of alternates are 'nothing' and 'default'.  For example,
@@ -856,19 +808,6 @@
 paths. Note, you can only use a non-path expression as the
 last alternative.
 
-.. note::
-
-   TODO:
-
-   This spec should describe the following path expression syntax::
-
-    <span tal:content="here/?myvar" />
-
-   The "here/?myvar" expression is evaluated by traversing from
-   "here" to the name given by the value of "myvar". For
-   example, if "myvar" is set to "title", "here/?myvar" is
-   equivalent to "here/title".
-
 You can also test the existence of a path directly with the
 *exists* expression type prefix. See the section "Exists
 Expressions" below for more information on exists expressions.
@@ -876,10 +815,10 @@
 Not Expressions
 ~~~~~~~~~~~~~~~
 
-Not expressions let you negate the value of other
+`Not` expressions let you negate the value of other
 expressions. For example::
 
-  <p tal:condition="not:here/objectIds">
+  <p tal:condition="not:context/objectIds">
     There are no contained objects.
   </p>
 
@@ -900,16 +839,16 @@
 Script, Method, or some other kind of executable thing, then
 the expression will evaluate to the result of calling the object.
 This is usually what you want, but not always.  For example,
-if you want to put a DTML Document into a variable so that
+if you want to put a page template into a variable so that
 you can refer to its properties, you can't use a normal path
-expression because it will render the Document into a string.
+expression because it will render the template into a string.
 
 If you put the 'nocall:' expression type prefix in front of a
 path, it prevents the rendering and simply gives you the
 object.  For example::
 
-  <span tal:define="doc nocall:here/aDoc"
-        tal:content="string:${doc/getId}: ${doc/title}">
+  <span tal:define="page nocall:context/aPage"
+        tal:content="string:${page/getId}: ${page/title}">
   Id: Title</span>
 
 This expression type is also valuable when you want to define
@@ -965,7 +904,7 @@
 some security restrictions to keep you from accessing protected
 information, changing secured data, and creating problems such
 as infinite loops. See the chapter entitled `Advanced Zope
-Scripting`_ for more information on Python
+Scripting <ScriptingZope.html>`_ for more information on Python
 security restrictions.
 
 Comparisons
@@ -992,11 +931,11 @@
 
 Sometimes you want to choose different values inside a single
 statement based on one or more conditions.  You can do this
-with the 'test' function, like this::
+with the and and or operators, like this::
 
   You <span tal:define="name user/getUserName"
-       tal:replace="python:test(name=='Anonymous User',
-                               'need to log in', default)">
+       tal:replace="python:name=='Anonymous User' and
+                           'need to log in' or default">
         are logged in as
         <span tal:replace="name">Name</span>
       </span>
@@ -1006,20 +945,17 @@
 default content is used, which is in this case 'are logged in
 as ...'.
 
-The 'test' function works like an if/then/else statement. See
-`Appendix A: DTML Reference <AppendixA.html>`_ for more
-information on the 'test' function. Here's another example of
-how you can use the 'test' function::
+This operator combinaion works like an if/then/else statement.
+Here's another example of how you can use this pattern::
 
   <tr tal:define="oddrow repeat/item/odd"
-      tal:attributes="class python:test(oddrow, 'oddclass',
-                                        'evenclass')">
+      tal:attributes="class python:oddrow and 'oddclass' or 'evenclass'">
 
 This assigns 'oddclass' and 'evenclass' class attributes to
 alternate rows of the table, allowing them to be styled
 differently in HTML output, for example.
 
-Without the 'test' function you'd have to write two 'tr'
+Without this pattern you could also write two 'tr'
 elements with different conditions, one for even rows,
 and the other for odd rows.
 
@@ -1032,8 +968,8 @@
 'exists()', and 'nocall()'.  This allows you to write
 expressions such as::
 
-  "python:path('here/%s/thing' % foldername)"
-  "python:path(string('here/$foldername/thing'))"
+  "python:path('context/%s/thing' % foldername)"
+  "python:path(string('context/$foldername/thing'))"
   "python:path('request/form/x') or default"
 
 The final example has a slightly different meaning than the
@@ -1054,20 +990,20 @@
 template's title with the expression "template.title". Most
 Zope objects support acquisition, which allows you to get
 attributes from "parent" objects.  This means that the Python
-expression "here.Control_Panel" will acquire the Control Panel
+expression "context.Control_Panel" will acquire the Control Panel
 object from the root Folder.  Object methods are attributes,
-as in "here.objectIds" and "request.set".  Objects contained
+as in "context.objectIds" and "request.set".  Objects contained
 in a Folder can be accessed as attributes of the Folder, but
 since they often have Ids that are not valid Python
 identifiers, you can't use the normal notation.  For example,
 you cannot access the 'penguin.gif' object with the following
 Python expression::
 
-  "python:here.penguin.gif"
+  "python:context.penguin.gif"
 
 Instead, you must write::
 
-  "python:getattr(here, 'penguin.gif')"
+  "python:getattr(context, 'penguin.gif')"
 
 since Python doesn't support attribute names with periods.
 
@@ -1076,7 +1012,7 @@
 
   request['URL']
   modules['math']
-  here['thing']
+  context['thing']
 
 When you use item access on a Folder, it doesn't try to
 acquire the name, so it will only succeed if there is actually
@@ -1087,11 +1023,11 @@
 Zope tries attribute access, then item access.  You can
 write::
 
-  "here/images/penguin.gif"
+  "context/images/penguin.gif"
 
 instead of::
 
-  "python:getattr(here.images, 'penguin.gif')"
+  "python:getattr(context.images, 'penguin.gif')"
 
 and::
 
@@ -1134,8 +1070,8 @@
 will need to use a Python expression in order to supply the
 argument, like this::
 
-  "python:here.myscript(1, 2)"
-  "python:here.myscript('arg', foo=request.form['x'])"
+  "python:context.myscript(1, 2)"
+  "python:context.myscript('arg', foo=request.form['x'])"
 
 If you want to return more than one item of data from a Script
 to a Page Template, it is a good idea to return it in a
@@ -1144,53 +1080,13 @@
 example, suppose the 'getPerson' script returns a dictionary
 with 'name' and 'age' keys::
 
-  <span tal:define="person here/getPerson"
+  <span tal:define="person context/getPerson"
         tal:replace="string:${person/name} is ${person/age}">
   Name is 30</span> years old.
 
 Of course, it's fine to return Zope objects and Python lists
 as well.
 
-Calling DTML
-%%%%%%%%%%%%
-
-Unlike Scripts, DTML Methods and Documents don't have an
-explicit parameter list.  Instead, they expect to be passed a
-client, a mapping, and keyword arguments.  They use these
-parameters to construct a namespace.  See the chapter entitled
-`Variables and Advanced DTML <AdvDTML.html>`_ for more information
-on explicitly calling DTML.
-
-When Zope publishes a DTML object through the web, it
-passes the context of the object as the client, and the
-REQUEST as the mapping.  When one DTML object calls another,
-it passes its own namespace as the mapping, and no client.
-
-If you use a path expression to render a DTML object, it will
-pass a namespace with 'request', 'here', and the template's
-variables already on it.  This means that the DTML object will
-be able to use the same names as if it were being published in
-the same context as the template, plus the variable names
-defined in the template.  For example, here is a template that
-uses a DTML Method to generate JavaScript::
-
-  <head tal:define="items here/getItems.sql">
-    <title tal:content="template/title">Title</title>
-    <script tal:content="structure here/jsItems"></script>
-  </head>
-  ...etc...
-
-...and here is the DTML Method 'jsItems'::
-
-  <dtml-let prefix="template.id">
-  <dtml-in items>
-  &dtml-prefix;_&dtml-name; = &dtml-value; ;
-  </dtml-in>
-  </dtml-let>
-
-The DTML uses the template's 'id', and the 'items' variable
-that it defined just before the call.
-
 Python Modules
 %%%%%%%%%%%%%%
 
@@ -1210,10 +1106,10 @@
 The "string" module is hidden in Python expressions by the
 "string" expression type function, so you need to access it
 through the 'modules' variable.  You can do this directly in
-an expression in which you use it, or define a global variable
+an expression in which you use it, or define a variable
 for it, like this::
 
-  tal:define="global mstring modules/string"
+  tal:define="mstring modules/string"
   tal:replace="python:mstring.join(slist, ':')"
 
 In practice you'll rarely need to do this since you can use
@@ -1224,50 +1120,21 @@
 of organizing and naming related modules.  For instance,
 Zope's Python-based Scripts are provided by a collection of
 modules in the "PythonScripts" subpackage of the Zope
-"Products" package.  In particular, the "standard" module in
-this package provides a number of useful formatting functions
-that are standard in the DTML "var" tag.  The full name of
-this module is "Products.PythonScripts.standard", so you could
+"Products" namespace package.  In particular, the "standard" module in
+this package provides a number of useful formatting functions. The full name
+of this module is "Products.PythonScripts.standard", so you could
 get access to it using either of the following statements::
 
   tal:define="global pps modules/Products.PythonScripts.standard"
   tal:define="global pps python:modules['Products.PythonScripts.standard']"
 
-Many Python modules cannot be accessed from Page Templates,
-DTML, or Scripts unless you add Zope security assertions to
+Many Python modules cannot be accessed from Page Templates
+or Scripts unless you add Zope security assertions to
 them.  See the `Zope Developer's Guide's security
 chapter <http://www.zope.org/Documentation/ZDG/Security.stx>`_
 for more information on making more Python modules available
 to your templates and scripts by using "ModuleSecurityInfo".
 
-Remote Editing with FTP and WebDAV
-----------------------------------
-
-You can edit Page Templates remotely with FTP and WebDAV, as well
-as HTTP PUT publishing.  Using these methods, you can use Page
-Templates without leaving advanced WYSIWYG editors such as
-Macromedia Dreamweaver.  Follow these steps:
-
-1. Make sure your server and editor are configured correctly.  See
-   `Using External Tools <ExternalTools.html>`_ for instructions.
-
-2. If you want to create a new *Page Template* with your editor, add a
-   '.pt' suffix to the file name before saving it.  This way Zope adds a
-   *Page Template* object. To add a template with an other suffix like
-   '.html' or '.zpt' or without a suffix like 'index_html', either rename
-   it after adding it with a '.pt' suffix are create it through the ZMI.
-
-3. Edit your file with your editor and then save it.  When you save it
-   you should use the same URL you used to retrieve it.
-
-4. Optionally reload your page after you edit it, to check for error
-   comments.
-
-If you want to create files without the '.pt' suffix, it's also possible
-to customize the *PUT factory*.  See the *PUT_factory* section of the
-chapter entitled `Using External Tools`_ for more
-information.
-
 Caching Templates
 -----------------
 
@@ -1291,9 +1158,9 @@
 
   ## Script (Python) "long.py"
   ##
-  for i in range(500):
-    for j in range(500):
-      for k in range(5):
+  for i in range(250):
+    for j in range(250):
+      for k in range(250):
         pass
   return 'Done'
 
@@ -1303,7 +1170,7 @@
 
   <html>
     <body>
-      <p tal:content="here/long.py">results</p>
+      <p tal:content="context/long.py">results</p>
     </body>
   </html>
 
@@ -1333,16 +1200,15 @@
 caching for performance-critical applications.
 
 For more information on caching in the context of Zope, see the
-chapter entitled `Zope Services`_.
+chapter entitled `Zope Services <ZopeServices.html>`_.
 
 Page Template Utilities
 -----------------------
 
-Zope Page Templates are powerful but simple. Unlike DTML, Page
-Templates don't give you a lot of convenience features for things
+Zope Page Templates are powerful but simple.
+They don't give you a lot of convenience features for things
 like batching, drawing trees, sorting, etc. The creators of Page
-Templates wanted to keep them simple. However, you may miss some
-of the built-in features that DTML provides. To address these
+Templates wanted to keep them simple. To address these
 needs, Zope comes with utilities designed to enhance Page
 Templates.
 
@@ -1355,7 +1221,6 @@
 page. Breaking up large lists into smaller lists is called
 *batching*.
 
-Unlike DTML, which provides batching built into the language,
 Page Templates support batching by using a special 'Batch'
 object that comes from the 'ZTUtils' utility module.  See
 `Appendix B: API Reference`_, for more information
@@ -1403,7 +1268,7 @@
     <head>
       <title tal:content="template/title">The title</title>
     </head>
-    <body tal:define="employees here/getEmployees;
+    <body tal:define="employees context/getEmployees;
            start python:int(path('request/start | nothing') or 0);
            batch python:modules['ZTUtils'].Batch(employees, 
                                                  size=3, 
@@ -1489,7 +1354,7 @@
 when using Page Templates. The 'string', 'math', and 'random'
 modules can be used in Python expressions for string formatting,
 math function, and pseudo-random number generation. These same
-modules are available from DTML and Python-based scripts. 
+modules are available in Python-based scripts.
 
 The 'Products.PythonScripts.standard' module is designed to
 provide utilities to Python-based scripts, but it's also useful

Modified: zope2book/trunk/source/AppendixA.rst
===================================================================
--- zope2book/trunk/source/AppendixA.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/AppendixA.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -39,7 +39,7 @@
 See Also
 --------
 
-var tag
+- var tag
 
 
 comment: Comments DTML
@@ -90,26 +90,22 @@
 Functions
 ---------
 
-- abs(number)
-
+abs(number)
   Return the absolute value of a number. The argument may be a plain or long
   integer or a floating point number. If the argument is a complex number, its
   magnitude is returned.
 
-- chr(integer)
-
+chr(integer)
   Return a string of one character whose ASCII code is the integer, e.g.,
   'chr(97)' returns the string 'a'. This is the inverse of ord(). The argument
   must be in the range 0 to 255, inclusive; 'ValueError' will be raised if the
   integer is outside that range.
 
-- DateTime()
-
+DateTime()
   Returns a Zope 'DateTime' object given constructor arguments. See the
   DateTime API reference for more information on constructor arguments.
 
-- divmod(number, number)
-
+divmod(number, number)
   Take two numbers as arguments and return a pair of numbers consisting of
   their quotient and remainder when using long division. With mixed operand
   types, the rules for binary arithmetic operators apply. For plain and long
@@ -119,8 +115,7 @@
   *a*, if 'a % b' is non-zero it has the same sign as *b*, and '0 <= abs(a % b)
   < abs(b)'.
 
-- float(number)
-
+float(number)
   Convert a string or a number to floating point. If the argument is a string,
   it must contain a possibly signed decimal or floating point number, possibly
   embedded in whitespace; this behaves identical to 'string.atof(number)'.
@@ -128,39 +123,33 @@
   number, and a floating point number with the same value (within Python's
   floating point precision) is returned.
 
-- getattr(object, string)
-
+getattr(object, string)
   Return the value of the named attributed of object. name must be a string. If
   the string is the name of one of the object's attributes, the result is the
   value of that attribute. For example, 'getattr(x, "foobar")' is equivalent to
   'x.foobar'. If the named attribute does not exist, default is returned if
   provided, otherwise 'AttributeError' is raised.
 
-- getitem(variable, render=0)
-
+getitem(variable, render=0)
   Returns the value of a DTML variable. If 'render' is true, the variable is
   rendered. See the 'render' function.
 
-- hasattr(object, string)
-
+hasattr(object, string)
   The arguments are an object and a string. The result is 1 if the string is
   the name of one of the object's attributes, 0 if not. (This is implemented by
   calling getattr(object, name) and seeing whether it raises an exception or
   not.)
 
-- hash(object)
-
+hash(object)
   Return the hash value of the object (if it has one). Hash values are
   integers. They are used to quickly compare dictionary keys during a
   dictionary lookup. Numeric values that compare equal have the same hash value
   (even if they are of different types, e.g. 1 and 1.0).
 
-- has_key(variable)
-
+has_key(variable)
   Returns true if the DTML namespace contains the named variable.
 
-- hex(integer)
-
+hex(integer)
   Convert an integer number (of any size) to a hexadecimal string. The result
   is a valid Python expression. Note: this always yields an unsigned literal,
   e.g. on a 32-bit machine, 'hex(-1)' yields '0xffffffff'. When evaluated on a
@@ -168,8 +157,7 @@
   different word size, it may turn up as a large positive number or raise an
   'OverflowError' exception.
 
-- int(number)
-
+int(number)
   Convert a string or number to a plain integer. If the argument is a string,
   it must contain a possibly signed decimal number representable as a Python
   integer, possibly embedded in whitespace; this behaves identical to
@@ -180,30 +168,25 @@
   Conversion of floating point numbers to integers is defined by the C
   semantics; normally the conversion truncates towards zero.
 
-- len(sequence)
-
+len(sequence)
   Return the length (the number of items) of an object. The argument may be a
   sequence (string, tuple or list) or a mapping (dictionary).
 
-- max(s)
-
+max(s)
   With a single argument s, return the largest item of a non-empty sequence
   (e.g., a string, tuple or list). With more than one argument, return the
   largest of the arguments.
 
-- min(s)
-
+min(s)
   With a single argument s, return the smallest item of a non-empty sequence
   (e.g., a string, tuple or list). With more than one argument, return the
   smallest of the arguments.
 
-- namespace([name=value]...)
-
+namespace([name=value]...)
   Returns a new DTML namespace object. Keyword argument 'name=value' pairs are
   pushed into the new namespace.
 
-- oct(integer)
-
+oct(integer)
   Convert an integer number (of any size) to an octal string. The result is a
   valid Python expression. Note: this always yields an unsigned literal, e.g.
   on a 32-bit machine, 'oct(-1)' yields '037777777777'. When evaluated on a
@@ -211,13 +194,11 @@
   different word size, it may turn up as a large positive number or raise an
   OverflowError exception.
 
-- ord(character)
-
+ord(character)
   Return the ASCII value of a string of one character. E.g., 'ord("a")' returns
   the integer 97. This is the inverse of 'chr()'.
 
-- pow(x, y [,z])
-
+pow(x, y [,z])
   Return *x* to the power *y*; if *z* is present, return *x* to the power *y*,
   modulo *z* (computed more efficiently than 'pow(x, y) % z'). The arguments
   must have numeric types. With mixed operand types, the rules for binary
@@ -225,8 +206,7 @@
   the result; if the result is not expressible in this type, the function
   raises an exception; e.g., 'pow(2, -1)' or 'pow(2, 35000)' is not allowed.
 
-- range([start,] stop [,step])
-
+range([start,] stop [,step])
   This is a versatile function to create lists containing arithmetic
   progressions. The arguments must be plain integers. If the step argument is
   omitted, it defaults to 1. If the start argument is omitted, it defaults to
@@ -236,78 +216,66 @@
   is the largest 'start + i * step' greater than *stop*. *step* must not be
   zero (or else 'ValueError' is raised).
 
-- round(x [,n])
-
+round(x [,n])
   Return the floating point value *x* rounded to *n* digits after the decimal
   point. If n is omitted, it defaults to zero. The result is a floating point
   number. Values are rounded to the closest multiple of 10 to the power minus
   n; if two multiples are equally close, rounding is done away from 0 (so e.g.
   round(0.5) is 1.0 and round(-0.5) is -1.0).
 
-- render(object)
-
+render(object)
   Render 'object'. For DTML objects this evaluates the DTML code with the
   current namespace. For other objects, this is equivalent to 'str(object)'.
 
-- reorder(s [,with] [,without])
-
+reorder(s [,with] [,without])
   Reorder the items in s according to the order given in 'with' and without the
   items mentioned in 'without'. Items from s not mentioned in with are removed.
   s, with, and without are all either sequences of strings or sequences of
   key-value tuples, with ordering done on the keys. This function is useful for
   constructing ordered select lists.
 
-- SecurityCalledByExecutable()
-
+SecurityCalledByExecutable()
   Return a true if the current object (e.g. DTML document or method) is being
   called by an executable (e.g. another DTML document or method, a script or a
   SQL method).
 
-- SecurityCheckPermission(permission, object)
-
+SecurityCheckPermission(permission, object)
   Check whether the security context allows the given permission on the given
   object. For example, 'SecurityCheckPermission("Add Documents, Images, and
   Files", this())' would return true if the current user was authorized to
   create documents, images, and files in the current location.
 
-- SecurityGetUser()
-
+SecurityGetUser()
   Return the current user object. This is normally the same as the
   'REQUEST.AUTHENTICATED_USER' object. However, the 'AUTHENTICATED_USER' object
   is insecure since it can be replaced.
 
-- SecurityValidate([object] [,parent] [,name] [,value])
-
+SecurityValidate([object] [,parent] [,name] [,value])
   Return true if the value is accessible to the current user. 'object' is the
   object the value was accessed in, 'parent' is the container of the value, and
   'name' is the named used to access the value (for example, if it was obtained
   via 'getattr'). You may omit some of the arguments, however it is best to
   provide all available arguments.
 
-- SecurityValidateValue(object)
-
+SecurityValidateValue(object)
   Return true if the object is accessible to the current user. This function is
   the same as calling 'SecurityValidate(None, None, None, object)'.
 
-- str(object)
-
+str(object)
   Return a string containing a nicely printable representation of an object.
   For strings, this returns the string itself.
 
-- test(condition, result [,condition, result]... [,default])
-
+test(condition, result [,condition, result]... [,default])
   Takes one or more condition, result pairs and returns the result of the first
   true condition. Only one result is returned, even if more than one condition
   is true. If no condition is true and a default is given, the default is
   returned. If no condition is true and there is no default, None is returned.
 
-- unichr(number)
-
+unichr(number)
   Return a unicode string representing the value of number as a unicode
   character. This is the inverse of ord() for unicode characters.
 
-- unicode(string[, encoding[, errors ] ])
-
+unicode(string[, encoding[, errors ] ])
   Decodes string using the codec for encoding. Error handling is done according
   to errors. The default behavior is to decode UTF-8 in strict mode, meaning
   that encoding errors raise ValueError.
@@ -315,31 +283,22 @@
 Attributes
 ----------
 
-- None
-
+None
   The 'None' object is equivalent to the Python built-in object 'None'. This is
   usually used to represent a Null or false value.
 
 See Also
 --------
 
-- `string module`_
+- `string module <http://www.python.org/doc/current/lib/module-string.html>`_
 
-.. _string module: http://www.python.org/doc/current/lib/module-string.html
+- `random module <http://www.python.org/doc/current/lib/module-random.html>`_
 
-- `random module`_
+- `math module <http://www.python.org/doc/current/lib/module-math.html>`_
 
-.. _random module: http://www.python.org/doc/current/lib/module-random.html
+- `sequence module <http://www.python.org/doc/current/lib/built-in-funcs.html>`_
 
-- `math module`_
 
-.. _math module: http://www.python.org/doc/current/lib/module-math.html
-
-- `sequence module`_
-
-.. _sequence module: http://www.python.org/doc/current/lib/built-in-funcs.html
-
-
 if: Tests Conditions
 ====================
 
@@ -393,11 +352,9 @@
 See Also
 --------
 
-`Python Tutorial If Statements`_
+`Python Tutorial If Statements <http://docs.python.org/tutorial/controlflow.html#if-statements>`_
 
-.. _Python Tutorial If Statements: http://docs.python.org/tutorial/controlflow.html#if-statements
 
-
 in: Loops over sequences
 ========================
 
@@ -429,37 +386,29 @@
 Attributes
 ----------
 
-- mapping
-
+mapping
   Iterates over mapping objects rather than instances. This allows values of
   the mapping objects to be accessed as DTML variables.
 
-- reverse
-
+reverse
   Reverses the sequence.
 
-- sort=string
-
+sort=string
   Sorts the sequence by the given attribute name.
 
-- start=int
-
+start=int
   The number of the first item to be shown, where items are numbered from 1.
 
-- end=int
-
+end=int
   The number of the last item to be shown, where items are numbered from 1.
 
-- size=int
-
+size=int
   The size of the batch.
 
-- skip_unauthorized
-
+skip_unauthorized
   Don't raise an exception if an unauthorized item is encountered.
 
-- orphan=int
-
+orphan=int
   The desired minimum batch size. This controls how sequences are split into
   batches. If a batch smaller than the orphan size would occur, then no split
   is performed, and a batch larger than the batch size results.
@@ -470,34 +419,28 @@
 
   The default value is 0.
 
-- overlap=int
-
+overlap=int
   The number of items to overlap between batches. The default is no overlap.
 
-- previous
-
+previous
   Iterates once if there is a previous batch. Sets batch variables for previous
   sequence.
 
-- next
-
+next
   Iterates once if there is a next batch. Sets batch variables for the next
   sequence.
 
-- prefix=string
-
+prefix=string
   Provide versions of the tag variables that start with this prefix instead of
   "sequence", and that use underscores (_) instead of hyphens (-). The prefix
   must start with a letter and contain only alphanumeric characters and
   underscores (_).
 
-- sort_expr=expression
-
+sort_expr=expression
   Sorts the sequence by an attribute named by the value of the expression. This
   allows you to sort on different attributes.
 
-- reverse_expr=expression
-
+reverse_expr=expression
   Reverses the sequence if the expression evaluates to true. This allows you to
   selectively reverse the sequence.
 
@@ -509,69 +452,54 @@
 
 These variables describe the current item.
 
-- sequence-item
-
+sequence-item
   The current item.
 
-- sequence-key
-
+sequence-key
   The current key. When looping over tuples of the form '(key,value)', the 'in'
   tag interprets them as '(sequence-key, sequence-item)'.
 
-- sequence-index
-
+sequence-index
   The index starting with 0 of the current item.
 
-- sequence-number
-
+sequence-number
   The index starting with 1 of the current item.
 
-- sequence-roman
-
+sequence-roman
   The index in lowercase Roman numerals of the current item.
 
-- sequence-Roman
-
+sequence-Roman
   The index in uppercase Roman numerals of the current item.
 
-- sequence-letter
-
+sequence-letter
   The index in lowercase letters of the current item.
 
-- sequence-Letter
-
+sequence-Letter
   The index in uppercase letters of the current item.
 
-- sequence-start
-
+sequence-start
   True if the current item is the first item.
 
-- sequence-end
-
+sequence-end
   True if the current item is the last item.
 
-- sequence-even
-
+sequence-even
   True if the index of the current item is even.
 
-- sequence-odd
-
+sequence-odd
   True if the index of the current item is odd.
 
-- sequence-length
-
+sequence-length
   The length of the sequence.
 
-- sequence-var-*variable*
-
+sequence-var-*variable*
   A variable in the current item. For example, 'sequence-var-title' is the
   'title' variable of the current item. Normally you can access these variables
   directly since the current item is pushed on the DTML namespace. However
   these variables can be useful when displaying previous and next batch
   information.
 
-- sequence-index-*variable*
-
+sequence-index-*variable*
   The index of a variable of the current item.
 
 Summary Variables
@@ -581,40 +509,31 @@
 variable you must loop over objects (like database query results) that have
 numeric variables.
 
-- total-*variable*
-
+total-*variable*
   The total of all occurrences of an item variable. 
 
-- count-*variable*
-
+count-*variable*
   The number of occurrences of an item variable.
 
-- min-*variable*
-
+min-*variable*
   The minimum value of an item variable.
 
-- max-*variable*
-
+max-*variable*
   The maximum value of an item variable.
 
-- mean-*variable*
-
+mean-*variable*
   The mean value of an item variable.
 
-- variance-*variable*
-
+variance-*variable*
   The variance of an item variable with count-1 degrees of freedom.
 
-- variance-n-*variable*
-
+variance-n-*variable*
   The variance of an item variable with n degrees of freedom.
 
-- standard-deviation-*variable*
-
+standard-deviation-*variable*
   The standard-deviation of an item variable with count-1 degrees of freedom.
 
-- standard-deviation-n-*variable*
-
+standard-deviation-n-*variable*
   The standard-deviation of an item variable with n degrees of freedom.
 
 Grouping Variables
@@ -622,88 +541,70 @@
 
 These variables allow you to track changes in current item variables.
 
-- first-*variable*
-
+first-*variable*
   True if the current item is the first with a particular value for a variable.
 
-- last-*variable*
-
+last-*variable*
   True if the current item is the last with a particular value for a variable.
 
 Batch Variables
 +++++++++++++++
 
-- sequence-query
-
+sequence-query
   The query string with the 'start' variable removed. You can use this variable
   to construct links to next and previous batches.
 
-- sequence-step-size
-
+sequence-step-size
   The batch size.
 
-- previous-sequence
-
+previous-sequence
   True if the current batch is not the first one. Note, this variable is only
   true for the first loop iteration.
 
-- previous-sequence-start-index
-
+previous-sequence-start-index
   The starting index of the previous batch.
 
-- previous-sequence-start-number
-
+previous-sequence-start-number
   The starting number of the previous batch. Note, this is the same as
   'previous-sequence-start-index' + 1.
 
-- previous-sequence-end-index
-
+previous-sequence-end-index
   The ending index of the previous batch.
 
-- previous-sequence-end-number
-
+previous-sequence-end-number
   The ending number of the previous batch. Note, this is the same as
   'previous-sequence-end-index' + 1.
 
-- previous-sequence-size
-
+previous-sequence-size
   The size of the previous batch.
 
-- previous-batches
-
+previous-batches
   A sequence of mapping objects with information about all previous batches.
   Each mapping object has these keys 'batch-start-index', 'batch-end-index',
   and 'batch-size'.
 
-- next-sequence
-
+next-sequence
   True if the current batch is not the last batch. Note, this variable is only
   true for the last loop iteration.
 
-- next-sequence-start-index
-
+next-sequence-start-index
   The starting index of the next sequence.
 
-- next-sequence-start-number
-
+next-sequence-start-number
   The starting number of the next sequence. Note, this is the same as
   'next-sequence-start-index' + 1.
 
-- next-sequence-end-index
-
+next-sequence-end-index
   The ending index of the next sequence.
 
-- next-sequence-end-number
-
+next-sequence-end-number
   The ending number of the next sequence. Note, this is the same as
   'next-sequence-end-index' + 1.
 
-- next-sequence-size
-
+next-sequence-size
   The size of the next index.
 
-- next-batches
-
+next-batches
   A sequence of mapping objects with information about all following batches.
   Each mapping object has these keys 'batch-start-index', 'batch-end-index',
   and 'batch-size'.
@@ -827,8 +728,9 @@
 See Also
 --------
 
-with tag
+- with tag
 
+
 mime: Formats data with MIME
 ============================
 
@@ -854,52 +756,42 @@
 
 Both the 'mime' and 'boundry' tags have the same attributes.
 
-- encode=string
-
+encode=string
   MIME Content-Transfer-Encoding header, defaults to 'base64'. Valid encoding
   options include 'base64', 'quoted-printable', 'uuencode', 'x-uuencode',
   'uue', 'x-uue', and '7bit'. If the 'encode' attribute is set to '7bit' no
   encoding is done on the block and the data is assumed to be in a valid MIME
   format.
 
-- type=string
-
+type=string
   MIME Content-Type header.
 
-- type_expr=string
-
+type_expr=string
   MIME Content-Type header as a variable expression. You cannot use both 'type'
   and 'type_expr'.
 
-- name=string
-
+name=string
   MIME Content-Type header name.
 
-- name_expr=string
-
+name_expr=string
   MIME Content-Type header name as a variable expression. You cannot use both
   'name' and 'name_expr'.
 
-- disposition=string
-
+disposition=string
   MIME Content-Disposition header.
 
-- disposition_expr=string
-
+disposition_expr=string
   MIME Content-Disposition header as a variable expression. You cannot use both
   'disposition' and 'disposition_expr'.
 
-- filename=string
-
+filename=string
   MIME Content-Disposition header filename.
 
-- filename_expr=string
-
+filename_expr=string
   MIME Content-Disposition header filename as a variable expression. You cannot
   use both 'filename' and 'filename_expr'.
 
-- skip_expr=string
-
+skip_expr=string
   A variable expression that if true, skips the block. You can use this
   attribute to selectively include MIME blocks.
 
@@ -920,11 +812,10 @@
   </dtml-sendmail>
 
 See Also
+--------
 
-`Python Library mimetools`_
+- `Python Library mimetools <http://www.python.org/doc/current/lib/module-mimetools.html>`_
 
-.. _Python Library mimetools: http://www.python.org/doc/current/lib/module-mimetools.html
-
 raise: Raises an exception
 ==========================
 
@@ -957,16 +848,12 @@
 See Also
 --------
 
-try tag
+- try tag
 
-`Python Tutorial Errors and Exceptions`_
+- `Python Tutorial Errors and Exceptions <http://www.python.org/doc/current/tut/node10.html>`_
 
-.. _Python Tutorial Errors and Exceptions: http://www.python.org/doc/current/tut/node10.html
+- `Python Built-in Exceptions <http://www.python.org/doc/current/lib/module-exceptions.html>`_
 
-`Python Built-in Exceptions`_
-
-.. _Python Built-in Exceptions: http://www.python.org/doc/current/lib/module-exceptions.html
-
 return: Returns data
 ====================
 
@@ -1016,32 +903,26 @@
 Attributes
 ----------
 
-- mailhost
-
+mailhost
   The name of a Zope MailHost object to use to send email. You cannot specify
   both a mailhost and a smtphost.
 
-- smtphost
-
+smtphost
   The name of a SMTP server used to send email. You cannot specify both a
   mailhost and a smtphost.
 
-- port
-
+port
   If the smtphost attribute is used, then the port attribute is used to specify
   a port number to connect to. If not specified, then port 25 will be used.
 
-- mailto
-
+mailto
   The recipient address or a list of recipient addresses separated by commas.
   This can also be specified with the 'To' header.
 
-- mailfrom
-
+mailfrom
   The sender address. This can also be specified with the 'From' header.
 
-- subject
-
+subject
   The email subject. This can also be specified with the 'Subject' header.
 
 Examples
@@ -1063,11 +944,10 @@
 See Also
 --------
 
-`RFC 821 (SMTP Protocol)`_
+- `RFC 821 (SMTP Protocol) <http://www.ietf.org/rfc/rfc0821.txt>`_
 
-.. _RFC 821 (SMTP Protocol): http://www.ietf.org/rfc/rfc0821.txt
+- mime tag
 
-mime tag
 
 sqlgroup: Formats complex SQL expressions
 =========================================
@@ -1094,13 +974,11 @@
 Attributes
 ----------
 
-- required=boolean
-
+required=boolean
   Indicates whether the group is required. If it is not required and contains
   nothing, it is excluded from the DTML output.
 
-- where=boolean
-
+where=boolean
   If true, includes the string "where". This is useful for the outermost
   'sqlgroup' tag in a SQL 'select' query.
 
@@ -1166,8 +1044,9 @@
 See Also
 --------
 
-sqltest tag
+- sqltest tag
 
+
 sqltest: Formats SQL condition tests
 ====================================
 
@@ -1189,43 +1068,44 @@
 Attributes
 ----------
 
-- type=string
-
+type=string
   The type of the variable. Valid types include: 'string', 'int', 'float' and
   'nb'. 'nb' means non-blank string, and should be used instead of 'string'
   unless you want to test for blank values. The type attribute is required and
   is used to properly escape inserted variable.
 
-- column=string
-
+column=string
   The name of the SQL column to test against. This attribute defaults to the
   variable name.
 
-- multiple=boolean
-
+multiple=boolean
   If true, then the variable may be a sequence of values to test the column
   against.
 
-- optional=boolean
-
+optional=boolean
   If true, then the test is optional and will not be rendered if the variable
   is empty or non-existent.
 
-- op=string
-
+op=string
   The comparison operation. Valid comparisons include: 
 
-  eq -- equal to
+  eq
+    equal to
 
-  gt -- greater than
+  gt
+    greater than
 
-  lt -- less than
+  lt
+    less than
 
-  ne -- not equal to
+  ne
+    not equal to
 
-  ge -- greater than or equal to
+  ge
+    greater than or equal to
 
-  le -- less than or equal to
+  le
+    less than or equal to
 
   The comparison defaults to equal to. If the comparison is not
   recognized it is used anyway. Thus you can use comparisons such
@@ -1257,10 +1137,11 @@
 See Also
 --------
 
-sqlgroup tag
+- sqlgroup tag
 
-sqlvar tag
+- sqlvar tag
 
+
 sqlvar: Inserts SQL variables
 =============================
 
@@ -1281,15 +1162,13 @@
 Attributes
 ----------
 
-- type=string
-
+type=string
   The type of the variable. Valid types include: 'string', 'int', 'float' and
   'nb'. 'nb' means non-blank string and should be used in place of 'string'
   unless you want to use blank strings. The type attribute is required and is
   used to properly escape inserted variable.
 
-- optional=boolean
-
+optional=boolean
   If true and the variable is null or non-existent, then nothing is inserted.
 
 Examples
@@ -1305,8 +1184,9 @@
 See Also
 --------
 
-sqltest tag
+- sqltest tag
 
+
 tree: Inserts a tree widget
 ===========================
 
@@ -1332,78 +1212,63 @@
 Attributes
 ----------
 
-- branches=string
-
+branches=string
   Finds tree branches by calling the named method. The default method is
   'tpValues' which most Zope objects support.
 
-- branches_expr=string
-
+branches_expr=string
   Finds tree branches by evaluating the expression.
 
-- id=string
-
+id=string
   The name of a method or id to determine tree state. It defaults to 'tpId'
   which most Zope objects support. This attribute is for advanced usage only.
 
-- url=string
-
+url=string
   The name of a method or attribute to determine tree item URLs. It defaults to
   'tpURL' which most Zope objects support. This attribute is for advanced usage
   only.
 
-- leaves=string
-
+leaves=string
   The name of a DTML Document or Method used to render nodes that don't have
   any children. Note: this document should begin with '<dtml-var
   standard_html_header>' and end with '<dtml-var standard_html_footer>' in
   order to ensure proper display in the tree.
 
-- header=string
-
+header=string
   The name of a DTML Document or Method displayed before expanded nodes. If the
   header is not found, it is skipped.
 
-- footer=string
-
+footer=string
   The name of a DTML Document or Method displayed after expanded nodes. If the
   footer is not found, it is skipped.
 
-- nowrap=boolean
-
+nowrap=boolean
   If true then rather than wrap, nodes may be truncated to fit available space.
 
-- sort=string
-
+sort=string
   Sorts the branches by the named attribute.
 
-- reverse
-
+reverse
   Reverses the order of the branches.
 
-- assume_children=boolean
-
+assume_children=boolean
   Assumes that nodes have children. This is useful if fetching and querying
   child nodes is a costly process. This results in plus boxes being drawn next
   to all nodes.
 
-- single=boolean
-
+single=boolean
   Allows only one branch to be expanded at a time. When you expand a new
   branch, any other expanded branches close.
 
-- skip_unauthorized
-
+skip_unauthorized
   Skips nodes that the user is unauthorized to see, rather than raising an
   error.
 
-- urlparam=string
-
+urlparam=string
   A query string which is included in the expanding and contracting widget
   links. This attribute is for advanced usage only.
 
-- prefix=string
-
+prefix=string
   Provide versions of the tag variables that start with this prefix instead of
   "tree", and that use underscores (_) instead of hyphens (-). The prefix must
   start with a letter and contain only alphanumeric characters and underscores
@@ -1412,30 +1277,24 @@
 Tag Variables
 -------------
 
-- tree-item-expanded
-
+tree-item-expanded
   True if the current node is expanded.
 
-- tree-item-url
-
+tree-item-url
   The URL of the current node.
 
-- tree-root-url
-
+tree-root-url
   The URL of the root node.
 
-- tree-level
-
+tree-level
   The depth of the current node. Top-level nodes have a depth of zero.
 
-- tree-colspan
-
+tree-colspan
   The number of levels deep the tree is being rendered. This variable along
   with the 'tree-level' variable can be used to calculate table rows and
   colspan settings when inserting table rows into the tree table.
 
-- tree-state
-
+tree-state
   The tree state expressed as a list of ids and sub-lists of ids. This variable
   is for advanced usage only.
 
@@ -1444,12 +1303,10 @@
 
 You can control the tree tag by setting these variables.
 
-- expand_all
-
+expand_all
   If this variable is true then the entire tree is expanded.
 
-- collapse_all
-
+collapse_all
   If this variable is true then the entire tree is collapsed.
 
 Examples
@@ -1513,8 +1370,7 @@
 Attributes
 ----------
 
-- except
-
+except
   Zero or more exception names. If no exceptions are listed then the except tag
   will handle all exceptions.
 
@@ -1523,16 +1379,13 @@
 
 Inside the 'except' block these variables are defined.
 
-- error_type
-
+error_type
   The exception type.
 
-- error_value
-
+error_value
   The exception value.
 
-- error_tb
-
+error_tb
   The traceback.
 
 Examples
@@ -1569,16 +1422,13 @@
 See Also
 --------
 
-raise tag
+- raise tag
 
-`Python Tutorial Errors and Exceptions`_
+- `Python Tutorial Errors and Exceptions <http://www.python.org/doc/current/tut/node10.html>`_
 
-.. _Python Tutorial Errors and Exceptions: http://www.python.org/doc/current/tut/node10.html
+- `Python Built-in Exceptions <http://www.python.org/doc/current/lib/module-exceptions.html>`_
 
-`Python Built-in Exceptions`_
 
-.. _Python Built-in Exceptions: http://www.python.org/doc/current/lib/module-exceptions.html
-
 unless: Tests a condition
 =========================
 
@@ -1612,8 +1462,9 @@
 See Also
 --------
 
-if tag
+- if tag
 
+
 var: Inserts a variable
 =======================
 
@@ -1651,86 +1502,69 @@
 Attributes
 ----------
 
-- html_quote
-
+html_quote
   Convert characters that have special meaning in HTML to HTML character
   entities.
 
-- missing=string
-
+missing=string
   Specify a default value in case Zope cannot find the variable.
 
-- fmt=string
-
+fmt=string
   Format a variable. Zope provides a few built-in formats including C-style
   format strings. For more information on C-style format strings see the
-  `Python Library Reference`_. If the format string is not a built-in format,
-  then it is assumed to be a method of the object, and it called.
+  `Python Library Reference <http://www.python.org/doc/current/lib/typesseq-strings.html>`_.
+  If the format string is not a built-in format, then it is assumed to be a
+  method of the object, and it called.
 
-  * collection-length
-
+  collection-length
     The length of the variable, assuming it is a sequence.
 
-- null=string
-
+null=string
   A default value to use if the variable is None.
 
-- lower
-
+lower
   Converts upper-case letters to lower case. 
 
-- upper
-
+upper
   Converts lower-case letters to upper case. 
 
-- capitalize
-
+capitalize
   Capitalizes the first character of the inserted word.
 
-- spacify
-
+spacify
   Changes underscores in the inserted value to spaces.
 
-- thousands_commas
-
+thousands_commas
   Inserts commas every three digits to the left of a decimal point in values
   containing numbers for example '12000' becomes '12,000'.
 
-- url
-
+url
   Inserts the URL of the object, by calling its 'absolute_url' method.
 
-- url_quote
-
+url_quote
   Converts characters that have special meaning in URLs to HTML character
   entities.
 
-- url_quote_plus
-
+url_quote_plus
   URL quotes character, like 'url_quote' but also converts spaces to plus
   signs.
 
-- sql_quote
-
+sql_quote
   Converts single quotes to pairs of single quotes. This is needed to safely
   include values in SQL strings.
 
-- newline_to_br
-
+newline_to_br
   Convert newlines (including carriage returns) to HTML break tags.
 
-- size=arg
-
+size=arg
   Truncates the variable at the given length (Note: if a space occurs in the
   second half of the truncated string, then the string is further truncated to
   the right-most space).
 
-- etc=arg
-
+etc=arg
   Specifies a string to add to the end of a string which has been truncated (by
   setting the 'size' attribute listed above). By default, this is '...'
 
-.. _Python Library Reference: http://www.python.org/doc/current/lib/typesseq-strings.html
 
 Examples
 --------
@@ -1789,12 +1623,10 @@
 Attributes
 ----------
 
-- only
-
+only
   Limits the DTML namespace to only include the one defined in the 'with' tag.
 
-- mapping
-
+mapping
   Indicates that the variable or expression is a mapping object. This ensures
   that variables are looked up correctly in the mapping object.
 
@@ -1820,4 +1652,4 @@
 See Also
 --------
 
-let tag
+- let tag

Modified: zope2book/trunk/source/BasicObject.rst
===================================================================
--- zope2book/trunk/source/BasicObject.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/BasicObject.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -26,32 +26,26 @@
 
 Presentation
   You can control the look and feel of your site with Zope objects that act
-  as web page "templates". Zope comes with two facilities to help you
-  manage presentation: DTML (which also handles "logic"), and Zope Page
-  Templates (ZPT).  The difference between DTML and ZPT is that DTML allows
-  you to mix presentation and logic, while ZPT does not.
+  as web page "templates". Zope comes with one facility to help you
+  manage presentation: Zope Page Templates (ZPT).
 
 Logic
-  Zope has facilities for scripting business logic using three facilities:
-  Document Template Markup Language (DTML), Python, and Perl (Perl is only
-  available as an add-on).  "Logic" is any kind of programming that does
-  not involve presentation, but rather involves the carrying out of tasks
-  such as changing objects, sending messages, testing conditions, and
-  responding to events.
+  Scripting business logic in Zope is done using Python. "Logic" is any kind of
+  programming that does not involve presentation, but rather involves the
+  carrying out of tasks such as changing objects, sending messages, testing
+  conditions, and responding to events.
 
-The lines between these object categories can become slightly
-fuzzy.  For example, some aspects of DTML fit into *each* of the
-three categories, but since DTML is mostly for presentation, we stick it
-in there.  Zope also has other kinds of objects that fit into none
-of these categories, which are explored further in the chapter
-entitled `Zope Services <ZopeServices.html>`_.  You may also install
-"third party" Zope objects , typically called "Products", to expand 
-Zope's capabilities.  You can browse a list of available Zope Products at
-`Zope.org <http://www.zope.org/Products>`_.
+Zope also has other kinds of objects that fit into none of these categories,
+which are explored further in the chapter entitled `Zope Services
+<ZopeServices.html>`_. You may also install "third party" Zope objects ,
+defined in Python packages, to expand Zope's capabilities. You can browse a
+list of packages specifically aimed at Zope at the
+`Python Package Index <http://pypi.python.org/pypi?:action=browse&c=514>`_.
 
-Content Objects:  Folders, Files, and Images
-============================================
 
+Content Objects: Folders, Files, and Images
+===========================================
+
 Folders
 -------
 
@@ -66,8 +60,7 @@
 presentation is influenced by your site's folder structure.  Folder
 structure should be very familiar to anyone who has worked with files and
 folders on their computer using a file manager like Microsoft *Windows
-Explorer* or any one of the popular UNIX file managers, like *xfm*, *kfm*,
-and the Gnome file manager.
+Explorer*.
 
 Files
 -----
@@ -76,7 +69,7 @@
 Software, audio, video and documents are typically transported around the
 Internet and the world as files. A Zope File object is an analogue to these
 kinds of files.  You can use Files to hold any kind of information that
-Zope doesn't specifically support, such as Flash files, Java applets,
+Zope doesn't specifically support, such as Flash files, audio files,
 "tarballs", etc. 
 
 Files do not consider their contents to be of any special format, textual
@@ -133,12 +126,6 @@
 type the new content type into the *Content Type* field and click the *Save
 Changes* button.
 
-You can specify a *precondition* for a file.  A precondition is the name of
-an executable Zope object (such as a DTML Method, a Script (Python), or an
-external method), which is executed before the File is viewed or
-downloaded.  If the precondition raises an exception (an error), the file
-cannot be viewed.  This is a seldom-used feature of Files.
-
 You can change the contents of an existing File object by selecting a new
 file from your local filesystem in the *File Data* form element and
 clicking *Upload*.
@@ -180,41 +167,33 @@
 images. In addition, Image objects display a preview of their images once
 they have been uploaded to Zope.
 
-Presentation Objects:  Zope Page Templates and DTML Objects
-===========================================================
+Presentation Objects:  Zope Page Templates
+==========================================
 
 Zope encourages you to keep your presentation and logic separate by
 providing different objects that are intended to be used expressly for
 "presentation".  "Presentation" is defined as the task of dynamically
 defining layout of web pages and other user-visible data.  Presentation
-objects typically render HTML (and sometimes XML or WML).
+objects typically render HTML (and sometimes XML).
 
-Zope has two "presentation" facilities: *Zope Page Templates* (ZPT) and
-*Document Template Markup Language* (DTML).  ZPT and DTML are similar but
-have slight differences in scope and audience that are explained in a
-succeeding section.
+Zope has one "presentation" facility: *Zope Page Templates* (ZPT). Zope Page
+Templates are objects that allow you to define dynamic presentation for a web
+page. The HTML in your template is made dynamic by inserting special XML
+namespace elements into your HTML that define the dynamic behavior for that
+page.
 
-Zope Page Templates are objects that allow you to define dynamic
-presentation for a web page.  The HTML in your template is made dynamic by
-inserting special XML namespace elements into your HTML that define the
-dynamic behavior for that page.
+ZPT has characteristics of a "server-side" scripting language, like SSI, PHP or
+JSP. This means that ZPT commands are executed by Zope on the server, and the
+result of that execution is sent to your web browser. By contrast, client-side
+scripting languages, like Javascript, are not processed by the server, but are
+rather sent to and executed by your web browser.
 
-Document Template Markup Language objects are objects that also allow you
-to define presentation for a web page.  The HTML in your template is made
-dynamic by inserting special "tags" (directives surrounded by angle
-brackets, typically) into your HTML that define the dynamic behavior for
-that page.
+Zope also has an older version of a presentation facility included, which is
+called *Document Template Markup Language* or short DTML.
 
-Both ZPT and DTML are "server-side" scripting languages, like SSI, PHP,
-Embperl, or JSP.  This means that DTML and ZPT commands are executed by
-Zope on the server, and the result of that execution is sent to your web
-browser. By contrast, client-side scripting languages, like Javascript, are
-not processed by the server, but are rather sent to and executed by your
-web browser.
+ZPT vs. DTML: Same Purpose, Different Approach
+----------------------------------------------
 
-ZPT vs. DTML:  Same Purpose, Different Audiences
-------------------------------------------------
-
 There is a major problem with many languages designed for the purpose of
 creating dynamic HTML content: they don't allow for "separation of
 presentation and logic" very well.  For example, "tag-based" scripting
@@ -249,46 +228,15 @@
 
 Zope's original dynamic presentation language was DTML.  It soon became
 apparent that DTML was great at allowing programmers to quickly generate
-dynamic web pages, but it failed at times to allow programmers to work
+dynamic web pages, but it failed to allow programmers to work
 effectively together with non-technical graphics designers.  Thus, ZPT was
 born.  ZPT is an "attribute-based" presentation language that tries to
 allow for the "round-tripping" of templates between programmers and
 non-technical designers.
 
-Both ZPT and DTML are fully supported in Zope, for now and in the future.
-Because ZPT and DTML have an overlapping scope, many people are confused
-about which to choose for a given task.  A set of "rules of thumb" are
-appropriate here:
+While DTML is still supported in Zope, its use is discouraged and you
+shouldn't use it anymore for new projects.
 
-- ZPT is the "tool of choice" if you have a mixed team of programmers
-  and non-technical designers.  Design tools like Macromedia Dreamweaver do
-  not "stomp on" ZPT embedded in a page template, while these tools *do*
-  "stomp on" DTML tags embedded in an HTML page.  Additionally, any given
-  ZPT page template is typically viewable in a browser with "default"
-  (static) content even if it has commands embedded in it, which makes it
-  easier for both programmers and designers to preview their work "on the
-  fly".  Dynamic DTML content, on the other hand, may not be "preview-able"
-  in any meaningful way until it is rendered.
-
-- Use DTML when you need to generate non-XML, non-HTML, or
-  non-XHTML-compliant HTML text.  ZPT requires that you create pages that
-  are XHTML and/or XML-compliant.  ZPT cannot add dynamism to CSS style
-  sheets, SQL statements, or other non-XML-ish text, while DTML excels at
-  this.
-
-- DTML may be easier for some programmers to write because it provides
-  greater control over "conditionals" ("if this, do this; else, do that")
-  than does ZPT.  In this respect, it more closely resembles PHP and
-  ASP-based scripting languages than does ZPT, so it's typically a good
-  "starting place" for programmers coming from these kinds of technologies.
-
-- DTML code can become "logic-heavy" because it does not enforce the
-  "separation of presentation from logic" as strictly as does ZPT.
-  Embedding too much logic in presentation is almost always a bad thing,
-  but it is particularly bad when you are working on a "mixed" team of
-  programmers and designers.  If you're a "separation of presentation from
-  logic" purist, you will almost certainly prefer ZPT.
-
 Zope Page Templates
 -------------------
 
@@ -366,138 +314,10 @@
 
 You can also view a Page Template by visiting its Zope URL directly.
 
-DTML Objects:  DTML Documents and DTML Methods
-----------------------------------------------
 
-DTML is the "other" Zope facility for the creation of presentation in Zope.
-Two kinds of DTML objects may be added from the Zope Management Interface:
-*DTML Documents* and *DTML Methods*.  Both kinds of objects allow you to
-perform *security-constrained* presentation logic.  The code placed into
-DTML objects is constrained by Zope's *security policy*, which means, for
-the most part, that they are unable to import all but a defined set of
-restricted Python "modules", and they cannot directly access files on your
-filesystem.  This is a security feature, as it allows site administrators
-to safely delegate the ability to create DTML to "untrusted" or
-"semi-trusted" users.  For more information about Zope's security features,
-see `Users and Security <Security.html>`_.
+Logic Objects:  Script (Python) Objects
+=======================================
 
-A source of frequent confusion for DTML beginners is the question of when
-to use a DTML Document versus when to use a DTML Method.  On the surface,
-these two options seem identical: they both hold DTML and other content,
-they both execute DTML code, and they both have a similar user interface
-and a similar API. So what's the difference?
-
-DTML Methods are meant to hold bits of dynamic content that are displayed
-by other DTML Methods and other kinds of Zope objects.  For instance, you
-might create a DTML Method that renders the content of a navigation bar, or
-a DTML Method that represents a "standard" header for all of your HTML
-pages.  On the other hand, DTML Documents are meant to hold "document-like"
-content that can stand on its own.  DTML Documents also support properties,
-while DTML Methods do not.  The distinction between DTML Methods and DTML
-Documents is subtle, and if Zope Corporation had it to do "all over
-again", DTML Documents would likely not exist.  (Editor's aside: Believe
-me, I almost certainly enjoy writing about the difference less than you
-like reading about it. ;-) ) There is more information on this topic in
-the chapters entitled `Basic DTML <DTML.html>`_ and `Variables and Advanced
-DTML <AdvDTML.html>`_.
-
-As a general rule, you should use a DTML Method to hold DTML content unless
-you have a really good reason for using a DTML Document, such as a
-requirement that the container of your DTML content must support object
-properties. 
-
-Creating DTML Methods
-~~~~~~~~~~~~~~~~~~~~~
-
-Click on the Sales folder and then choose *DTML Method* from the Add list.
-This process will take you to the Add form for a DTML Method.  Specify the
-'id' "SalesStaff" and the title "The Jungle Sales Staff", and click *Add*.
-An entry for the new DTML Method object will be displayed in the Contents
-view of the Workspace pane.
-
-Editing DTML Methods
-~~~~~~~~~~~~~~~~~~~~
-
-The easiest and quickest way to edit your newly-created DTML Method is
-through the ZMI.  To select your method, click on its name or icon, which
-will bring up the form shown in the following figure:
-
-.. figure:: ../Figures/sales_staff_dtml.jpg
-
-   Editing a DTML Method
-
-This view shows a text area in which you can edit the content of your
-document.  Click the *Save Changes* button to make effective any changes
-you have made in the text area.  You can control the displayed size of the
-text area with the *Taller*, *Shorter*, *Wider*, and *Narrower* buttons.
-You can also upload a new file into the document with the *File* text box
-and the *Upload File* button.
-
-Delete the boilerplate content that is automatically included with a new
-DTML Method, and then add the following HTML content to the textarea::
-
-  <html>
-  <body>
-  <h2>Jungle Sales Staff</h2>
-
-  <ul>
-    <li>Tarzan</li>
-    <li>Cheetah</li>
-    <li>Jane</li>
-  </ul>
-  </body>
-  </html>
-
-Note that the example provided above doesn't do anything "dynamic"; it's
-just some HTML.  We will explore the creation of dynamic content with DTML
-in a later chapter.  For now, we're just getting used to using a DTML
-Method object via the ZMI.
-
-After you have completed the changes to your method, click the *Save
-Changes* button.  Zope returns a message to inform you that your changes
-have taken effect.
-
-Viewing a DTML Method
-~~~~~~~~~~~~~~~~~~~~~
-
-You can view a "rendered" DTML Method in the Workspace frame by clicking
-its *View* tab.  Click the *View* tab of the 'SalesStaff' DTML method, and
-you will be presented with something like the following:
-
-.. figure:: ../Figures/junglesales_view.jpg
-
-   Viewing a Rendered DTML Method
-
-You can also view a DTML Method by visiting its Zope URL directly.  
-
-Uploading an HTML File as Content for a DTML Method
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Suppose you'd prefer not to edit your HTML files in a web browser, or you
-have some existing HTML pages that you'd like to bring into Zope. Zope
-allows you to upload your existing text files and convert them to DTML
-Methods.
-
-Create a text file on your local computer named "upload_dtml.html".
-Populate it with the following content::
-
-  <html>
-    <body>
-      <h1>This is my first uploaded DTML Document!</h1>
-    </body>
-  </html>
-
-While in the Sales folder, choose *DTML Method* from the Add menu, which
-will trigger the DTML Method Add form to be displayed.  The last form
-element on the add form is the *Browse* button.  Click this button, and
-your browser will pop up a file selection dialog.  Choose the
-"upload_dtml.html" file, type in an 'id' of "upload_dtml" for the new DTML
-Method, and click *Add and Edit*.  You will then be taken back to the Edit
-form of your new DTML Method.
-
-Logic Objects:  Script (Python) Objects and External Methods
-============================================================
-
 "Logic" objects in Zope are objects that typically perform some sort of
 "heavy lifting" or "number crunching" in support of presentation objects.
 When they are executed, they need not return HTML or any other sort of
@@ -518,33 +338,24 @@
 logic object can almost always be displayed in a browser, even if the logic
 object does not return HTML.
 
-There are two kinds of logic objects supported by stock Zope: *Script
-(Python)* objects and *External Methods*.  An add-on product allows you to
-code logic in `Perl <http://www.zope.org/Wikis/zope-perl/FAQ>`_.  Several
-community-contributed Products exist which allow you to use Zope to manage
-your PHP and JSP scripts as well, but they are not integrated as tightly as
-the Python- or Perl-based logic objects.  They are
-`PHParser <http://www.zope.org/Members/hewei/PHParser>`_,
-`PHPObject <http://www.zope.org/Members/Ioan/PHPObject>`_, and
-`ZopeJSP <http://www.zope.org/Members/Ioan/ZopeJsp>`_.
+There is one kind of logic objects supported by stock Zope: *Script (Python)*
+objects.
 
-The stock logic objects, External Methods and Script (Python) objects, are
-written in the syntax of the *Python* scripting language.  Python is a
-general-purpose programming language.  You are encouraged to read the
-`Python Tutorial <http://www.python.org/doc/current/tut/tut.html>`_ in
-order to understand the syntax and semantics of the example Script (Python)
-objects and External Methods shown throughout this chapter and throughout
-this book.  And don't panic: Python is very easy to learn and understand.
+The stock logic objects are written in the syntax of the *Python* scripting
+language. Python is a general-purpose programming language. You are encouraged
+to read the `Python Tutorial <http://www.python.org/doc/current/tut/tut.html>`_
+in order to understand the syntax and semantics of the example Script (Python)
+objects shown throughout this chapter and throughout this book. And don't
+panic: Python is very easy to learn and understand.
 
-One important Python feature that must be mentioned here, however: Python
-uses whitespace in the form of indentation to denote block structure.
-Where other languages, such as C, Perl, and PHP might use "curly braces" --
-"{" and "}" -- to express a block of code, Python determines code blocks by
-examining the indentation of code text.  If you're used to other
-programming languages, this may take some "getting-used-to" (typically
-consisting of a few hours of unsavory spoken language ;-) ).  If you have
-problems saving or executing Script or External Method objects, make sure
-to check your Script's indentation.
+One important Python feature that must be mentioned here, however: Python uses
+whitespace in the form of indentation to denote block structure. Where other
+languages, such as C, Perl, and PHP might use "curly braces" -- "{" and "}" --
+to express a block of code, Python determines code blocks by examining the
+indentation of code text. If you're used to other programming languages, this
+may take some "getting-used-to" (typically consisting of a few hours of
+unsavory spoken language ;-) ). If you have problems saving or executing Script
+objects, make sure to check your Script's indentation.
 
 Script (Python) Objects
 -----------------------
@@ -642,7 +453,7 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Uploading the body of a Script (Python) object is much like uploading the
-body of a DTML Method or Page Template.  One significant difference is that
+body of a Page Template.  One significant difference is that
 Script (Python) objects interpret text that is offset by "double-pound"
 ('##') at the beginning of the text as data about their parameters, title,
 and "bindings".  For example, if you entered the following in a text editor
@@ -669,104 +480,6 @@
 be "auto-magically" turned into bindings and parameters for the Script
 (Python) object.
 
-External Methods
-----------------
-
-External Method objects are another type of logic object.  They are very
-similar to Script (Python) objects; in fact, they are scripted in the
-Python programming language, and they are used for the same purpose.  There
-are a few important differences:
-
-- External Methods are not editable using the Zope Management Interface.
-  Instead, their "modules" need to be created on the file system of your
-  Zope server in a special subdirectory of your Zope directory named
-  'Extensions'.
-
-- Because External Methods are not editable via the Zope Management
-  Interface, their execution is not constrained by the Zope "security
-  machinery".  This means that, unlike Script (Python) objects, External
-  Methods can import and execute essentially arbitrary Python code and
-  access files on your Zope server's file system.
-
-- External Methods do not support the concept of "bindings" (which we have
-  not discussed much yet, but please just make note for now).
-
-External methods are often useful as an "escape hatch" when Zope's security
-policy prevents you from using a Script (Python) object or DTML to do a
-particular job that requires more access than is "safe" in
-through-the-web-editable scripts.  For example, a Script (Python) object
-cannot write to files on your server's filesystem that an External Method
-may.
-
-Creating and Editing an External Method File
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Minimize the browser you're using to access the ZMI.  In your Zope's
-INSTANCE_HOME (the place where your Zope instance lives; see the
-Installation chapter for details), locate the subfolder named 'Extensions'.
-Navigate into this folder and create a text file with the name
-'SalesEM.py'.  
-
-Within this file, save the following content::
-
-  def SalesEM(self, name="Chris"):
-      id = self.id
-      return 'Hello, %s from the %s external method' % (name, id)
-
-Creating an External Method Object
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Before you can use an External Method from within Zope, you need to create
-an External Method object in the ZMI that "refers to" the function in the
-file that you just created.  Bring back your browser window and visit the
-ZMI.  Navigate to the Sales folder and select *External Method* from the
-Add list.  The Add form for an External Method will appear.  Provide an
-'Id' of "SalesEM", a 'Title' of "Sales External Method", a 'Module Name' of
-"SalesEM", and a 'Function Name' of "SalesEM".
-
-Then click *Add* at the bottom of the Add form.
-
-Testing an External Method Object
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can test an External Method in the Workspace frame by clicking the
-*Test* tab from the External Method's management screen.  When you test an
-External Method, its output is displayed in your browser.  Unlike Script
-(Python) objects, External Methods provide no mechanism for specifying
-parameter values during testing.  However, like Script (Python) objects,
-their output is influenced by values in a query string when you visit them
-directly.
-
-Click the *Test* tab of the SalesEM object, and you will see something like
-the following figure:
-
-.. figure:: ../Figures/testem.png
-
-   Testing an External Method
-
-If an External Method does not require parameters (or has defaults for its
-parameters, as in the example above), you may visit its URL directly to see
-its output.
-
-Provide alternate values via a query string to influence the execution of
-the External Method.  For example, visiting the SalesEM external Method via
-'http://localhost:8080/Sales/SalesEM?name=Fred' will display the following
-output::
-
-    Hello, Fred from the Sales external method
-
-Astute readers will note that the 'id' provided by the output is *not* the
-'id' of the External Method ('SalesEM'), but is instead the 'id' of the
-"containing" folder, which is named 'Sales'!  This is a demonstration of
-the fact that External Methods (as well as Script (Python) objects) are
-mostly meant to be used in the "context" of another object, which is often
-a Folder.  This is why they are named `methods <ObjectOrientation.html>`_.
-Typically, you don't often want to access information about the External
-Method or Script itself; all the "interesting" information is usually kept
-in other objects (like Folders).  An External Method or Script (Python)
-object "knows about" its context and can display information about the
-context without much fuss.
-
 SQL Methods:  Another Kind of Logic Object
 ------------------------------------------
 
@@ -883,7 +596,7 @@
                       periods request/periods">
       <span tal:content="years">2</span> years is:<br><br>
       <b>$
-      <span tal:content="python: here.calculateCompoundingInterest(principal, 
+      <span tal:content="python: context.calculateCompoundingInterest(principal, 
                                                        interest_rate,
                                                        periods,
                                                        years)" >1.00</span>
@@ -966,28 +679,3 @@
 section <http://www.zope.org/Resources/MailingLists>`_ of Zope.org for
 information about how to subscribe to the Zope (zope at zope.org) mailing
 list.
-
-The Zope Tutorial 
-=================
-
-Zope comes with a built-in tutorial, which reinforces some of the concepts
-you've learned here. As an extension of this book, we recommend that you
-run the tutorial to get a feel for using basic Zope objects, particularly
-DTML objects.  To use the tutorial properly, your browser should support
-*JavaScript* and *cookies*.
-
-To launch the tutorial, navigate to the root folder in the ZMI, and add a
-Zope Tutorial object by choosing *Zope Tutorial* from the Add list. When
-the add form asks for an "id" for the object, give it the id *tutorial* and
-click "Add".  You will be directed to a screen with a "Begin Tutorial"
-button.  When you click "Begin Tutorial", a new browser window that
-resembles the help system will be opened containing the tutorial.  If
-another window does not appear, either your browser does not support
-*JavaScript* or it is configured to disallow the opening of new windows.
-This will prevent you from being able to use the tutorial, so you may want
-to permit these windows to open, or try using a different browser.
-
-If you start the tutorial and want to stop using it before you have
-completed all the lessons, you can later return to your spot in the
-tutorial: just go to the help system and find the appropriate lesson in the
-*Zope Tutorial* help category. There is no need to re-install the tutorial.

Deleted: zope2book/trunk/source/DTML.rst
===================================================================
--- zope2book/trunk/source/DTML.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/DTML.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -1,1448 +0,0 @@
-Basic DTML
-==========
-
-DTML (Document Template Markup Language) is a templating facility
-which supports the creation of dynamic HTML and text.  It is
-typically used in Zope to create dynamic web pages.  For example,
-you might use DTML to create a web page which "fills in" rows and
-cells of an HTML table contained within the page from data fetched
-out of a database.
-
-DTML is a *tag-based* presentation and scripting language.  This
-means that *tags* (e.g. '<dtml-var name>') embedded in your HTML
-cause parts of your page to be replaced with "computed" content.
-
-DTML is a "server-side" scripting language.  This means that DTML
-commands are executed by Zope at the server, and the result of that
-execution is sent to your web browser. By contrast, "client-side"
-scripting languages like JavaScript are not processed by the server,
-but are rather sent to and executed by your web browser.
-
-How DTML Relates to Similar Languages and Templating Facilities
----------------------------------------------------------------
-
-DTML is similar in function to "HTML-embedded" scripting languages
-such as JSP, PHP, or mod_perl.  It differs from these facilities
-inasmuch as it will not allow you to create "inline" Python
-*statements* (if... then.. else..)  in the way that JSP, mod_perl
-or PHP will allow you to embed a block of their respective
-language's code into an HTML page. DTML does allow you to embed
-Python *expressions* (a == 1) into HTML-like tags.  It provides
-flow control and conditional logic by way of "special" HTML tags.
-It is more similar to Perl's 'HTML::Template' package than it is
-to mod_perl in this way.  It can also be compared to the web
-server facility of Server Side Includes (SSI), but with far more
-features and flexibility.
-
-When To Use DTML
-----------------
-
-If you want to make a set of dynamic web pages that share bits of
-content with each other, and you aren't working on a project that
-calls for a tremendous amount of collaboration between programmers
-and tool-wielding designers, DTML works well.  Likewise, if you
-want to dynamically create non-HTML text (like CSS stylesheets or
-email messages), DTML can help.
-
-When Not To Use DTML
---------------------
-
-If you want code which expresses a set of complex algorithms to be
-maintainable (as "logic" programming should be), you shouldn't
-write it in DTML.  DTML is not a general purpose programming
-language, it instead is a special language designed for formatting
-and displaying content.  While it may be possible to implement
-complex algorithms in DTML, it is often painful.
-
-For example, let's suppose you want to write a web page which
-displays a representation of the famous `Fibonacci sequence
-<http://www.mathacademy.com/pr/prime/articles/fibonac/index.asp>`_.
-You would not want to write the program that actually makes the
-calculation of the Fibonacci numbers by writing DTML.  It could be
-done in DTML, but the result would be difficult to understand and
-maintain.  However, DTML is perfect for describing the page that
-the results of the Fibonnacci calculations are inserted into.  You
-can "call out" from DTML to Script (Python) objects as necessary
-and process the results of the call in DTML.  For example, it is
-`trivial in Python <http://www.python.org/doc/current/tut/node6.html>`_
-(search for the word Fibonacci on this page) to implement a Fibonacci
-sequence generator, and trivial in DTML to create a dynamic web
-page which shows these numbers in a readable format.  If you find
-yourself creating complex and hard-to-understand logic in DTML,
-it's likely time to explore the the Zope features which allow you
-to script "logic" in Python, while letting DTML do the
-presentation "dirty work".
-
-String processing is another area where DTML is likely not the
-best choice.  If you want to manipulate input from a user in a
-complex way, by using functions that manipulate strings, you are
-better off doing it in Python, which has more powerful string
-processing capabilities than DTML.
-
-Zope has a technology named `Zope Page emplates <ZPT.html>`_
-which has purpose similar to DTML.  DTML and ZPT are both
-facilities which allow you to create dynamic HTML.  However, DTML
-is capable of creating dynamic text which is *not* HTML, while ZPT
-is limited to creating text which is HTML (or XML).  DTML also
-allows users to embed more extensive "logic" in the form of
-conditionals and flow-control than does ZPT.  While the source to
-a ZPT page is almost always "well-formed" HTML through its
-lifetime, the source to DTML pages are not guaranteed to be
-"well-formed" HTML, and thus don't play well in many cases with
-external editing tools such as Dreamweaver.
-
-Both ZPT and DTML are fully supported technologies in Zope, and
-neither is "going away" any time soon.  A discussion about when to
-use one instead of the other is available in the chapter entitled
-`Using Basic Zope Objects <BasicObject.html>`_ in the section entitled
-"ZPT vs. DTML: Same Purpose, Different Audiences", but the choice
-is sometimes subjective.
-
-The Difference Between DTML Documents and DTML Methods
-------------------------------------------------------
-
-You can use DTML scripting commands in two types of Zope objects,
-*DTML Documents* and *DTML Methods*.  These two types of DTML
-objects are subtly different from one another, and their
-differences cause many would-be DTML programmers to become
-confused when deciding to use one versus the other.  So what is
-the difference?
-
-DTML Methods are used to carry out actions. They are
-*presentation* objects (as used in the vernacular of the `Using
-Basic Zope Objects`_ chapter).  If you want to
-render the properties or attributes of another object like a DTML
-Document or a Folder, you will use a DTML Method.  DTML Methods do
-not have their own properties.
-
-DTML Documents are *content* objects (in the vernacular used in
-the chapter entitled `Using Basic Zope Objects`_).
-If you want to create a "stand-alone" HTML or text document, you
-might create a DTML Document object to hold the HTML or text.
-DTML Document objects have their own *properties* (attributes),
-unlike DTML Methods.
-
-In almost all cases, you will want to use a DTML Method object to
-perform DTML scripting.  DTML Document objects are an artifact of
-Zope's history that is somewhat unfortunate.  In Zope's earlier
-days, a consensus came about that it was important to have objects
-in Zope that could perform DTML commands but have properties of
-their own.  At the time, the other content objects in Zope, such
-as Files and Images were either nonexistent or had limitations in
-functionality that made the concept of a DTML Document attractive.
-That attraction has waned as Zope's other built-in content objects
-have become more functional.  DTML Documents remain in Zope almost
-solely as a backwards-compatibility measure.  If you never use a
-DTML Document in your work with Zope, you won't miss out on
-much!
-
-Details
--------
-
-DTML Methods are method objects.  The chapter named `Object
-Orientation <ObjectOrientation.html>`_ discusses the concept of a
-"method".  DTML Methods are *methods* of the folder that
-contains them, and thus they do not have regard for their own
-identity as a Zope object when they are used. For example, if
-you had a folder called Folder and a DTML method in that folder
-called Method::
-
-  AFolder/
-          AMethod
-
-AMethod is a *method* of AFolder. This means that AMethod does not
-have any of it's own attributes or properties.  Instead it uses
-those of AFolder. Suppose you put the following DTML string in
-AMethod::
-
-  <dtml-var id>
-
-When you view the AMethod DTML Method, you will see the string
-'AFolder', which is the 'id' of AMethod's containing Folder
-(AFolder). When this DTML method is viewed, it resolves the name
-'id' to the string which is the value of AFolder's 'id' property.
-
-DTML Documents, on the other hand, are not methods.  They are
-"aware" of their own identity as Zope objects. For example, if
-you created a DTML Document in the folder AFolder called
-ADocument, and you put the above DTML string into ADocument and
-viewed it, it would render to the string 'ADocument'.  It
-resolves the name 'id' to the string which is the value of
-its *own* id, not the id of its containing folder.
-
-.. important::
-   
-   For this chapter, unless stated otherwise, use DTML Methods to
-   hold the example DTML text, as opposed to DTML Documents!**
-
-DTML Tag Syntax
----------------
-
-DTML contains two kinds of tags, *singleton* and *block* tags.
-Singleton tags consist of one tag enclosed by less-than (&lt;) and
-greater-than (&gt;) symbols.  The *var* tag is an example of a
-singleton tag::
-
-  <dtml-var parrot>
-
-There's no need to close the *var* tag with a '</dtml-var>' tag
-because it is a singleton tag.
-
-Block tags consist of two tags, one that opens the block and one that
-closes the block, and content that goes between them::
-
-  <dtml-in mySequence>
-
-    <!-- this is an HTML comment inside the in tag block -->
-
-  </dtml-in>
-
-The opening tag starts the block and the closing tag ends it. The
-closing tag has the same name as the opening tag with a slash
-preceding it. This is the same convention that HTML and XML use.
-
-DTML Tag Names, Targets, and Attributes
----------------------------------------
-
-All DTML tags have *names*.  The name is simply the word which
-follows 'dtml-'.  For instance, the name of the DTML tag
-'dtml-var' is 'var', and the name of the DTML tag 'dtml-in' is
-'in'.
-
-Most DTML tags have *targets*.  The target of a DTML tag is just
-the word or expression that, after a space, follows the tag
-name.  For example, the target of the DTML tag '<dtml-var
-standard_html_header>' is 'standard_html_header'.  The target of
-the DTML tag '<dtml-in foo>' is 'foo'.  The target of the DTML
-tag '<dtml-var "objectIds()"> is the expression "objectIds()".
-The target typically refers to the name of an object (or a
-Python expression that resolves to an object) that you wish the
-tag to operate upon.
-
-All DTML tags have *attributes*. An attribute provides
-information about how the tag is supposed to work. Some
-attributes are optional. For example, the *var* tag inserts the
-value of its target. It has an optional *missing* attribute that
-specifies a default value in case the variable can't be found::
-
-  <dtml-var wingspan missing="unknown wingspan">
-
-If the *wingspan* variable is not found then 'unknown wingspan'
-is inserted instead.
-
-Some attributes don't have values. For example, you can convert
-an inserted variable to upper case with the *upper* attribute::
-
-  <dtml-var exclamation upper>
-
-Here we are referencing the *exclamation* target, modifying it
-with the attribute *upper*.  Notice that the *upper* attribute,
-unlike the *missing* attribute doesn't need a value.
-
-See the `DTML Reference <AppendixA.html>`_ appendix for more
-information on the syntax of different DTML tags.
-
-Creating a "Sandbox" for the Examples in This Chapter
------------------------------------------------------
-
-You should create a Folder in your Zope's root folder named
-"DTML_Examples" if you intend on creating objects from examples in
-this chapter.  Create the example objects within this "sandbox".
-This prevents you from littering your Zope root folder with DTML
-examples.
-
-Examples of Using DTML for Common Tasks
----------------------------------------
-
-Below, we show how to use DTML to complete three common tasks:
-inserting text into a web page, displaying results by iterating
-over a sequence, and processing form results.
-
-Inserting Text into HTML with DTML
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-DTML commands are written as tags that begin with *dtml-*.  You
-create dynamic content in DTML by mixing HTML tags and DTML tags
-together.  Inserting the value of a variable (a variable is also
-known as a "target") into HTML is the most basic task that you can
-perform with DTML.  Many DTML tags insert variable values, and
-they all do it in a similar way.  Let's look more closely at how
-Zope inserts variable values.
-
-Create a folder in your sandbox with the id "Feedbags" and the
-title "Bob's Fancy Feedbags". While inside the 'Feedbags' folder,
-create a DTML Method with an id of "pricelist". Note: an
-'id' is how you refer to an object such as a DTML Method
-or a Folder later on; titles are for informational
-purposes only. 
-
-Change the contents of the DTML Method to the following::
-
-  <dtml-var standard_html_header>
-
-  <h1>Price list for <dtml-var title></h1>
-
-  <p>Hemp Bag $2.50</p>
-  <p>Silk Bag $5.00</p>
-
-  <dtml-var standard_html_footer>
-
-Now view the DTML Method by clicking the *View* tab. When you view
-the DTML method this way, it will be *rendered*, which means that
-you will not necessarily see a straight representation of the HTML
-that you typed in to the form.  Instead you will see the
-*rendered* version of the page, which will include the extra text
-provided by DTML by way of the tags you've inserted.  You should
-see something like the figure below:
-
-.. figure:: ../Figures/9-1_bobsfeedbags.png
-
-   Viewing the pricelist method
-
-If you tell your browser to view the HTML source of the Workspace
-frame, you will see something not unlike the below::
-
-  <html>
-    <head><title>Bob's Fancy Feedbags</title>
-    </head>
-    <body bgcolor="#FFFFFF">
-      <h1>Price list for Bob's Fancy Feedbags</h1>
-      <p>Hemp Bag $2.50</p>
-      <p>Silk Bag $5.00</p>
-    </body>
-
-  </html>
-
-That's certainly not what you typed in, is it?
-
-DTML makes the reuse of content and layout possible.  In the
-example above, we've made use of the 'standard_html_header' DTML
-Method and the 'standard_html_footer' DTML Method, both of which
-live in the root folder, to insert HTML text into our page.  These
-DTML methods (and any other DTML method) can be used by other DTML
-methods to insert text into our rendered output.
-
-We've seen that DTML inserts an HTML header, an HTML footer, and a
-title into the web page.  But how does the "var" tag *find* the
-values that it inserts in place of "standard_html_header", "title"
-and "standard_html_footer"?
-
-DTML name lookup is somewhat "magical", because you don't need to
-explicitly tell DTML *where* to find a variable.  Instead, it
-tries to guess what you mean by following a preordained set of
-search rules.  DTML gets the values for variable names by
-searching an environment which includes the current object, the
-containment path, and request variables like values submitted by a
-form and cookies.  The `DTML Name Lookup Rules <AppendixE.html>`_
-represent the namespaces searched and their relative precedence.
-As an example, let's follow the 'pricelist' DTML code
-step-by-step.  In our 'pricelist' method, we've asked DTML to look
-up three names: "standard_html_header", "title", and
-"standard_html_footer".  It searches for these variables in the
-order that they are mentioned in the page.
-
-DTML looks first for "standard_html_header".  It looks in the
-"current object" first, which is its container, the 'Feedbags'
-folder. The 'Feedbags' folder doesn't have any methods or
-properties or sub-objects by that name. Next Zope tries to
-`acquire <Acquisition.html>`_ the object from its containers.  It
-examines the 'Feedbags' folder's container (your sandbox folder,
-likely named "DTML_Examples"), which also doesn't turn up
-anything.  It continues searching through any intermediate
-containters, which also don't have a method or property named
-"standard_html_header" unless you've put one there.  It keeps
-going until it gets to the root folder.  The root folder *does*
-have a sub-object named "standard_html_header", which comes as a
-default object in every Zope. The 'standard_html_header' object is
-a DTML Method. So Zope *calls* the 'standard_html_header' method
-in the root folder and inserts the results into the page.  Note
-that once DTML *finds* a property or variable, if it is callable
-(as in the case of a DTML Method, an External Method, a SQL
-Method, or a Script (Python) object), it is called and the results
-of the call are inserted into the page.
-
-Next DTML looks for the name "title". Here, the search is 
-shorter.  On its first try, DTML finds the 'Feedbags' folder's
-'title' property and inserts it.  The 'title' property is not a
-method or a script, so DTML doesn't need to *call* it.  It just
-renders it into the output.
-
-Finally DTML looks for the name *standard_html_footer*. It has to
-search all the way up to the root folder to find it, just like it
-looked for *standard_html_header*.  It calls the
-*standard_html_footer* in the root and inserts the text result.
-
-The resulting page is fully assembled (rendered) at this point,
-and is sent to your browser.
-
-Understanding how DTML looks up variables is important.  We will
-explore the DTML name lookup mechanism further in the chapter
-entitled `Variables and Advanced DTML <AdvDTML.html>`_.
-It is also documented in `Appendix E <AppendixE.html>`_.
-
-Formatting and Displaying Sequences
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-It is common that people want to use DTML to format and display
-*sequences*.  A sequence is just a list of items, like "Fred, Joe,
-Jim".  Often, you want to create an HTML table or a bulleted list
-that contains elements in a sequence.  Let's use DTML to call out
-to an object which returns a sequence and render its result.
-
-Create a Script (Python) object named "actors" in your
-sandbox folder. Give the script the following body and
-save it::
-
-  ## Script (Python) "actors"
-  ##bind container=container
-  ##bind context=context
-  ##bind namespace=
-  ##bind script=script
-  ##bind subpath=traverse_subpath
-  ##parameters=
-  ##title=
-  ##
-  return ['Jack Lemmon', 'Ed Harris','Al Pacino', 'Kevin Spacey', 'Alan Arkin']
-
-Make sure that all of the lines of this script line up along the
-left-hand side of the textarea to avoid receiving an error when
-you attempt to save the script, since Python is sensitive to
-indentation.  Don't worry about the '##'s for now, we will
-explain these later.  
-
-This Script (Python) object returns a Python data
-structure which is a *list* of *strings*.  A list is a kind of
-*sequence*, which means that DTML can *iterate* over it using the
-*dtml-in* tag.  Now create a DTML Method named "showActors" in
-your sandbox, give it this body, and save it::
-
-  <html>
-  <body>
-  <h1>Actors in the movie Glengarry Glen Ross</h1>
-  <table border="1">
-    <th>Name</th>
-  <dtml-in actors>
-    <tr>
-    <td><dtml-var sequence-item></td>
-    </tr>
-  </dtml-in>
-  </table>
-  </body>
-  </html>
-
-The DTML *in* tag iterates over the results of the *actors* script
-and inserts a table row into a table for each of the actors
-mentioned in the script.  Note that inside the table cell, we use
-a special name *sequence-item*.  *sequence-item* is a special name
-that is meaningful within a *dtml-in* tag.  It refers to the
-"current item" (in this case, the actor name string) during
-processing.  The HTML source of the Workspace frame when you click
-the *View* tab on the 'showActors' method will look something
-like::
-
-  <html>
-  <body>
-  <h1>Actors in the movie Glengarry Glen Ross</h1>
-  <table border="1">
-    <th>Name</th>
-          <tr>
-    <td>Jack Lemmon</td>
-
-    </tr>
-          <tr>
-    <td>Ed Harris</td>
-    </tr>
-          <tr>
-    <td>Al Pacino</td>
-    </tr>
-          <tr>
-
-    <td>Kevin Spacey</td>
-    </tr>
-          <tr>
-    <td>Alan Arkin</td>
-    </tr>
-        </table>
-  </body>
-  </html>
-
-Note that you didn't have to specifically tell DTML that you are
-querying a Script (Python) object.  You just tell it the name of
-the object to call (in this case 'actors'), and it does the work
-of figuring out how to call the object and pass it appropriate
-arguments. If you replace the 'actors' Script with some other kind
-of object that does exactly the same thing, like another DTML
-Method, you won't have to change your 'showActors' DTML Method.
-It will "just work".
-
-Processing Input from Forms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can use DTML to perform actions based on the information
-contained in the submission of an HTML form.
-
-Create a DTML Method named "infoForm" with the following body::
-
-  <dtml-var standard_html_header>
-
-  <p>Please send me information on your aardvark adoption
-  program.</p>
-
-  <form action="infoAction">
-  name: <input type="text" name="user_name"><br>
-  email: <input type="text" name="email_addr"><br>
-  <input type="submit" name="submit" value=" Submit ">
-  </form>
-
-  <dtml-var standard_html_footer>
-
-This is a web form that asks the user for information,
-specifically his user name and email address.  Note that you refer
-to the name "infoAction" as the *action* of the HTML form.  This
-really has nothing to do with DTML, it's an attribute of the HTML
-*form* tag.  But the name specified in the form action tag can
-name another Zope object which will receive and process the
-results of the form when it is submitted.
-
-Create a DTML Method named *infoAction* in the same folder as the
-'infoForm' method.  This is the *target* of the 'infoForm' form
-action.  This method will display a bland "thanks" message which
-includes the name and email information that was gathered from the
-web form.  Provide the *infoAction* method with the following body
-and save it::
-
-  <dtml-var standard_html_header>
-
-  <h1>Thanks <dtml-var user_name></h1>
-
-  <p>We received your request for information and will send you
-  email at <dtml-var email_addr> describing our aardvark adoption
-  program as soon as it receives final governmental approval.
-  </p>
-
-  <dtml-var standard_html_footer>
-
-Navigate back to the 'infoForm' method and use the *View* tab to
-execute it.  Fill out the form and click the *Submit* button. If
-all goes well you should see a thank you message that includes
-your name and email address, much like the figure below:
-
-.. figure:: ../Figures/aardvarkview.png
-
-   Result of submitting the infoForm method
-
-The Zope object named *REQUEST* contains information about the
-current web request.  This object is in the DTML name lookup path.
-The 'infoAction' method found the form information from the web
-request that happened when you clicked the submit button on the
-rendering of 'infoForm'.  DTML looks for variables in the current
-web request, so you can just refer to the form variable names in
-the target method by name.  In our case, we were able to display
-the values of the form elements *user_name* and *email_addr* in
-the 'infoAction' method just by referring to them by name in their
-respective *dtml-var* tags.  DTML used its `lookup
-rules <AppendixE.html>`_ to search for the variable names.  It found
-the names in the "REQUEST.form" namespace and displayed them.  If
-it had found an object with either name *email_addr* or
-*user_name* earlier in the lookup (if perhaps there was a Zope
-object in your acquisition path named 'user_name') it would have
-found this object first and rendered its results.  But, mostly by
-chance, it didn't, and found the name in REQUEST instead.
-
-Let's examine the contents of the Zope REQUEST object in order to
-shed more light on the situation.  Create a new DTML Method object
-named 'show_request' in your sandbox folder.  Give it the the
-following body::
-
-  <dtml-var REQUEST>
-
-The 'show_request' method will render a human-readable
-representation of Zope's REQUEST object when you click submit on
-the 'infoForm' rendering.  Visit the 'infoForm' method, and change
-it to the following::
-
-  <dtml-var standard_html_header>
-
-  <p>Please send me information on your aardvark adoption
-  program.</p>
-
-  <form action="show_request">
-  name: <input type="text" name="user_name"><br>
-  email: <input type="text" name="email_addr"><br>
-  <input type="submit" name="submit" value=" Submit ">
-  </form>
-
-  <dtml-var standard_html_footer>
-
-We changed the form action of the 'infoForm' method to
-*show_request*.  Now click the *View* tab of the new 'infoForm'
-method.  Fill in some information in the form elements, and click
-*Submit*.  You will see something like the following::
-
-  form
-   submit ' Submit '
-   email_addr 'chrism at zope.com'
-   user_name 'Chris'
-
-  cookies
-   tree-s 'eJzTiFZ3hANPW/VYHU0ALlYElA'
-
-  lazy items
-   SESSION <bound method SessionDataManager.getSessionData of <SessionDataManager instance at 897d020>
-
-  other
-   AUTHENTICATION_PATH ''
-   user_name 'Chris'
-   PUBLISHED <DTMLMethod instance at 8a62670>
-   submit ' Submit '
-   SERVER_URL 'http://localsaints:8084'
-   email_addr 'chrism at zope.com'
-   tree-s 'eJzTiFZ3hANPW/VYHU0ALlYElA'
-   URL 'http://localsaints:8084/DTML_Example/show_request'
-   AUTHENTICATED_USER admin
-   TraversalRequestNameStack []
-   URL0 http://localsaints:8084/DTML_Example/show_request
-   URL1 http://localsaints:8084/DTML_Example
-   URL2 http://localsaints:8084
-   BASE0 http://localsaints:8084
-   BASE1 http://localsaints:8084
-   BASE2 http://localsaints:8084/DTML_Example
-   BASE3 http://localsaints:8084/DTML_Example/show_request
-
-  environ
-   SCRIPT_NAME ''
-   HTTP_ACCEPT_ENCODING 'gzip, deflate, compress;q=0.9'
-   SERVER_PORT '8084'
-   PATH_TRANSLATED '/DTML_Example/show_request'
-   HTTP_ACCEPT 'text/xml...'
-   GATEWAY_INTERFACE 'CGI/1.1'
-   HTTP_COOKIE 'tree-s="eJzTiFZ3hANPW/VYHU0ALlYElA"'
-   HTTP_ACCEPT_LANGUAGE 'en-us, en;q=0.50'
-   REMOTE_ADDR '192.168.1.3'
-   SERVER_NAME 'saints'
-   HTTP_USER_AGENT 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1a+) Gecko/20020629'
-   HTTP_ACCEPT_CHARSET 'ISO-8859-1, utf-8;q=0.66, *;q=0.66'
-   CONNECTION_TYPE 'keep-alive'
-   channel.creation_time 1027876407
-   QUERY_STRING 'user_name=Chris&email_addr=chrism%40zope.com&submit=+Submit+'
-   SERVER_PROTOCOL 'HTTP/1.1'
-   HTTP_KEEP_ALIVE '300'
-   HTTP_HOST 'localsaints:8084'
-   REQUEST_METHOD 'GET'
-   PATH_INFO '/DTML_Example/show_request'
-   SERVER_SOFTWARE 'Zope/(unreleased version, python 2.1.3, linux2) ZServer/1.1b1'
-   HTTP_REFERER 'http://localsaints:8084/DTML_Example/infoForm'
-
-You have instructed the 'show_request' method to render the
-contents of the web request initiated by the 'infoForm' method.
-Note that each section (form, cookies, lazy items, other, and
-environ) represents a *namespace* inside the REQUEST.  DTML
-searches all of these namespaces for the names you refer to in
-your 'infoForm' form.  Note that *email_addr* and *user_name* are
-in the "form" namespace of the REQUEST.  There is lots of
-information in the rendering of the REQUEST, but for us, this is
-the most pertinent.  For more information on the REQUEST object,
-visit the Zope Help system, and choose Zope Help -> API Reference
--> Request.
-
-Dealing With Errors
-~~~~~~~~~~~~~~~~~~~
-
-Let's perform an experiment. What happens if you try to view the
-'infoAction' method you created in the last section directly, as
-opposed to getting to it by submitting the 'infoForm' method?
-Click on the 'infoAction' method and then click the *View* tab.
-You will see results not unlike those in the figure below.
-
-.. figure:: ../Figures/infokeyerror.png
-
-   DTML error resulting from a failed variable lookup
-
-Zope couldn't find the *user_name* variable since it was not in
-the current object, its containers or the web request. This is an
-error that you're likely to see frequently as you learn
-Zope. Don't fear, it just means that you've tried to insert a
-variable that Zope can't find.  You can examine the error by
-visiting the *error_log* object in your root folder.  In this
-case, we know why the error occurred, so visiting the error in the
-*error_log* isn't really necessary.  In this example, you need to
-either insert a variable that Zope can find, or use the 'missing'
-attribute on the var tag as described above::
-
-  <h1>Thanks <dtml-var user_name missing="Anonymous User"></h1>
-
-Understanding where DTML looks for variables will help you figure
-out how to fix this kind of problem.  In this case, you have
-viewed a method that needs to be called from an HTML form like
-*infoForm* in order to provide variables to be inserted in the
-output.
-
-Dynamically Acquiring Content
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Zope looks for DTML variables in the current object's containers
-(its parent folders) if it can't find the variable first in the
-current object. This behavior allows your objects to find and use
-content and behavior defined in their parents.  Zope uses the term
-*acquisition* to refer to this dynamic use of content and
-behavior.
-
-An example of acquisition that you've already seen is how web
-pages use standard headers and footers. To acquire the standard
-header just ask Zope to insert it with the *var* tag::
-
-  <dtml-var standard_html_header>
-
-It doesn't matter where the 'standard_html_method' object or
-property is located. Zope will search upwards in the object
-database until it finds the 'standard_html_header' that is defined
-in the root folder.
-
-You can take advantage of how Zope looks up variables to customize
-your header in different parts of your site. Just create a new
-'standard_html_header' in a folder and it will override global
-header for all web pages in your folder and below it.
-
-Create a new folder in your "sandbox" folder with an id of
-"Green". Enter the 'Green' folder and create a DTML Method with an
-id of "welcome". Edit the 'welcome' DTML Method to have these
-contents::
-
-  <dtml-var standard_html_header>
-
-  <p>Welcome</p>
-
-  <dtml-var standard_html_footer>
-
-Now view the 'welcome' method. It should look like a simple web
-page with the word *welcome*, as shown in the figure below.
-
-.. figure:: ../Figures/welcomedtml.png
-
-   Welcome method
-
-Now let's customize the header for the *Green* folder. Create a
-DTML Method in the *Green* folder with an id of
-"standard_html_header". Give it the following body::
-
-  <html>
-  <head>
-    <style type="text/css">
-    body {color: #00FF00;}
-    p {font-family: sans-serif;}
-    </style>
-  </head>
-  <body>
-
-Notice that this is not a complete web page. For example, it does
-not have an ending '</html>' tag.  This is just a fragment of HTML
-that will be used as a header, meant to be included into other
-pages. This header uses `CSS <http://www.w3.org/Style/CSS>`_
-(Cascading Style Sheets) to make some changes to the look and feel
-of web pages.
-
-Now revisit the 'welcome' method and click its *View* tab again.
-You will see something like the figure below:
-
-.. figure:: ../Figures/welcomegreen.png
-
-   Welcome method with custom header
-
-The rendering now looks quite different. This is because it is now
-using the new header we introduced in the 'Green' folder. This
-header will be used by all web pages in the 'Green' folder and its
-sub-folders.
-
-You can continue this process of overriding default content by
-creating another folder inside the 'Green' folder and creating a
-'standard_html_header' DTML Method there. Now web pages in the
-sub-folder will use their local header rather than the 'Green'
-folder's header.  You can of course also create a
-'standard_html_footer', providing it with local content as well.
-
-Using this pattern you can quickly change the look and feel of
-different parts of your website. If you later decide that an area
-of the site needs a different header, just create one. You don't
-have to change the DTML in any of the web pages; they'll
-automatically find the closest header and use it.
-
-Using Python Expressions from DTML
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-So far we've looked at simple DTML tags. Here's an example::
-
-  <dtml-var getHippo>
-
-This will insert the value of the variable named *getHippo*,
-whatever that may be.  DTML will automatically take care of the
-details, like finding the object which represents the variable and
-calling it if necessary. We call this basic tag syntax *name*
-syntax to differentiate it from *expression* syntax.
-
-When you use DTML name syntax, DTML tries to do the right thing to
-insert the results of the object looked up by the variable name,
-no matter what that object may be. In general this means that if
-the variable is another DTML Method or DTML Document, it will be
-called with appropriate arguments.  However, if the variable is
-*not* another DTML Method or DTML Document, and it requires
-parameters, you need to explicitly pass the arguments along using
-an expression.
-
-*Expressions* used in DTML allow you to be more explicit about how
-to find and call variables. Expressions are tag attributes that
-contain small snippets of code in the Python programming language.
-These are typically referred to as *Python expressions*.
-
-A Python expression is essentially any bit of code that *is not* a
-Python *statement*.  For example, the Python statement 'a = 1'
-assigns "1" to the "a" variable. You cannot use this statement in
-DTML expressions.  Likewise, you cannot use the statement 'print
-"x"' in DTML.  It is not an expression.  Essentially, an
-expression must be a combination of values, variables, and Python
-*operators*.  To find out more about Python's expression syntax,
-see the `Python Tutorial <http://www.python.org/doc/current/tut>`_
-at the Python.org website.  For more information specifically about
-the differences between Python expressions and statements, see the
-`Variables, expressions, and statements
-<http://www.ibiblio.org/obp/thinkCSpy/chap02.htm>`_
-chapter of *How To Think Like a Computer Scientist Using Python*.
-
-An expression always results in a return value.  For example, the
-Python expression "a == 5" returns the integer 1 if "a" is equal
-to the integer 5 or the integer 0 if "a" is not equal to the
-integer 5.  The return value of an expression is used by DTML as
-the *target* of the DTML command.
-
-The primary difference in DTML between using *expressions* as
-targets and *names* as targets is that DTML does some magic after
-it locates a *named* targets that it does not do after it finds an
-expression targets.  For example, after finding object with the
-name 'standard_html_header' in the root folder via the name-syntax
-DTML command '<dtml-var standard_html_header>', DTML *calls* the
-'standard_html_header' object, inserting the results into the
-page.  However, when you use an expression-syntax DTML command,
-like '<dtml-var expr="standard_html_header">', DTML *will not*
-call the 'standard_html_header' object.  Instead it will return a
-representation of the object as a string.  In order to *call* the
-'standard_html_header' object in an expression-syntax DTML tag,
-you need to do it explicitly by passing along arguments.  When you
-delve into the realm of DTML expression syntax, DTML "magic" goes
-away, and you need to become aware of the arguments accepted by
-the target (if any) and pass them along.
-
-Let's create a Script (Python) object named 'getHippo' that *must*
-be called in DTML with expression syntax, because it takes a
-non-optional argument that *named* DTML syntax cannot provide.
-
-Create a Script (Python) in your sandbox folder named *getHippo*.
-Provide it with the following body::
-
-  ## Script (Python) "getHippo"
-  ##bind container=container
-  ##bind context=context
-  ##bind namespace=
-  ##bind script=script
-  ##bind subpath=traverse_subpath
-  ##parameters=trap
-  ##title=
-  ##
-  return 'The hippo was captured with a %s.' % trap
-
-Note that this Script (Python) object takes a single parameter
-named "trap".  It is not an optional parameter, so we need to pass
-a value in to this script for it to do anything useful.
-
-Now let's make a DTML method to call 'getHippo'.  Instead of
-letting DTML find and call *getHippo*, we can use an expression to
-explicitly pass arguments.  Create a DTML method named *showHippo*
-and give it the following body::
-
-  <dtml-var expr="getHippo('large net')">
-
-Here we've used a Python expression to explicitly call the
-'getHippo' method with the string argument, 'large net'.  View the
-'showHippo' DTML Method.  It will return a result not unlike the
-following::
-
-    The hippo was captured with a large net.
-
-To see why we need to use expression syntax to call this script,
-let's modify the 'showHippo' method to use DTML name syntax::
-
-  <dtml-var getHippo>
-
-View the method.  You will receive an error not unlike the
-following::
-
-  Error Type: TypeError
-  Error Value: getHippo() takes exactly 1 argument (0 given)
-
-The 'getHippo' method requires that you pass in an argument,
-'trap', that cannot be provided using DTML name syntax.  Thus, you
-receive an error when you try to view the 'showHippo' method.
-
-Expressions make DTML pretty powerful. For example, using Python
-expressions, you can easily test conditions::
-
-    <dtml-if expr="foo < bar">
-      Foo is less than bar.
-    </dtml-if>
-
-Without expressions, this very simple task would have to be broken
-out into a separate method and would add a lot of overhead for
-something this trivial.
-
-Before you get carried away with expressions, take
-care. Expressions can make your DTML hard to understand. Code that
-is hard to understand is more likely to contain errors and is
-harder to maintain. Expressions can also lead to mixing logic in
-your presentation. If you find yourself staring blankly at an
-expression for more than five seconds, stop. Rewrite the DTML
-without the expression and use a Script to do your logic. Just
-because you can do complex things with DTML doesn't mean you
-should.
-
-DTML Expression Gotchas
-%%%%%%%%%%%%%%%%%%%%%%%
-
-Using Python expressions can be tricky. One common mistake is
-to confuse expressions with basic tag syntax. For example::
-
-  <dtml-var objectValues>
-
-and::
-
-  <dtml-var expr="objectValues">
-
-These two examples if you are to put them in a DTML Method will
-end up giving you two completely different results. The first
-example of the DTML *var* tag will automatically *call* the
-object which is represented by *objectValues*. 
-
-In an expression, you have complete control over the variable
-rendering.  In the case of our example, *objectValues* is a
-method implemented in Python which returns the values of the
-objects in the current folder.  It has no required arguments.
-So::
-
-  <dtml-var objectValues>
-
-will call the method.
-However:
-
-  <dtml-var expr="objectValues">
-
-... will *not* call the method, it will just try to insert
-it. The result will be not a list of objects but a string such
-as '<Python Method object at 8681298>'. If you ever see results
-like this, there is a good chance that you're returning a
-method, rather than calling it.
-
-To call a Python method which requires no arguments from an
-expression, you must use standard Python calling syntax by using
-parenthesis::
-
-  <dtml-var expr="objectValues()">
-
-The lesson is that if you use Python expressions you must know
-what kind of variable you are inserting and must use the proper
-Python syntax to appropriately render the variable.
-
-Before we leave the subject of variable expressions we should
-mention that there is a deprecated form of the expression
-syntax. You can leave out the "expr=" part on a variable
-expression tag.  But *please* don't do this.  It is far too easy
-to confuse::
-
-  <dtml-var aName>
-
-with::
-
-  <dtml-var "aName">
-
-and get two completely different results.  These "shortcuts" were
-built into DTML long ago, but we do not encourage you to use them now
-unless you are prepared to accept the confusion and debugging
-problems that come from this subtle difference in syntax.
-
-Common DTML Tags
-----------------
-
-Below, we discuss the most common DTML tags: the *var* tag, the
-*if* tag, the *else* tag, the *elif* tag, and the *in* tag,
-providing examples for the usage of each.
-
-The *Var* Tag
-~~~~~~~~~~~~~
-
-The *var* tag inserts variables into DTML Methods and Documents.  We've
-already seen many examples of how the *var* tag can be used to insert
-strings into web pages.
-
-As you've seen, the *var* tag looks up variables first in the
-current object, then in its containers and finally in the web
-request.
-
-The *var* tag can also use Python expressions to provide more
-control in locating and calling variables.
-
-*Var* Tag Attributes
-%%%%%%%%%%%%%%%%%%%%
-
-You can control the behavior of the *var* tag using its
-attributes. The *var* tag has many attributes that help you in
-common formatting situations. The attributes are summarized in
-Appendix A. Here's a sampling of *var* tag attributes.
-
-html_quote
-  This attribute causes the inserted values to be HTML quoted.  This means
-  that '<', '>' and '&' are escaped.  Note that as of Zope 2.6, all string
-  values which are retrieved from the REQUEST namespace are HTML-quoted by
-  default.  This helps to prevent "cross-site scripting" security holes
-  present in earlier Zope versions, where a user could insert some clever
-  JavaScript into a page in order to possibly make you divulge information
-  to him which could be private.  For more information, see the `CERT
-  advisory <http://www.cert.org/advisories/CA-2000-02.html>`_ on the topic.
-
-missing
-  The missing attribute allows you to specify a default value to use in
-  case Zope can't find the variable. For example::
-
-    <dtml-var bananas missing="We have no bananas">
-
-fmt
-  The fmt attribute allows you to control the format of the *var* tags
-  output. There are many possible formats which are detailed in `Appendix
-  A <AppendixA.html>`_.
-
-  One use of the *fmt* attribute is to format monetary
-  values. For example, create a *float* property in your root
-  folder called *adult_rate*.  This property will represent
-  the cost for one adult to visit the Zoo.  Give this property
-  the value '2.2'.
-
-    % Anonymous User - Oct. 31, 2003 11:02 am:
-     I think this is the first mention of Properties.... Would be
-     helpful to explain that the properties are found with the
-     properties tag....since up until nos almost all additions have
-     been done by the pulldown menu.:)
-
-  You can display this cost in a DTML Document or Method like so::
-
-    One Adult pass: <dtml-var adult_rate fmt=dollars-and-cents>
-
-  This will correctly print "$2.20". It will round more
-  precise decimal numbers to the nearest penny.
-
-
-*Var* Tag Entity Syntax
-%%%%%%%%%%%%%%%%%%%%%%%
-
-Zope provides a shortcut DTML syntax just for the simple *var*
-tag.  Because the *var* tag is a singleton, it can be represented
-with an *HTML entity* like syntax::
-
-  &dtml-cockatiel;
-
-This is equivalent to::
-
-  <dtml-var name="cockatiel" html_quote>
-
-Entity-syntax-based DTML tags always "html quote" their
-renderings.  The main reason to use the entity syntax is to
-avoid putting DTML tags inside HTML tags. For example, instead
-of writing::
-
-  <input type="text" value="<dtml-var name="defaultValue" html_quote>">
-
-You can use the entity syntax to make things more readable for
-you and your text editor::
-
-  <input type="text" value="&dtml-defaultValue;">
-
-The *var* tag entity syntax is very limited. You can't use
-Python expressions within entity-based DTML syntax and many DTML
-attributes won't work with it. See `Appendix A`_
-for more information on *var* tag entity syntax.
-
-The *If* Tag
-~~~~~~~~~~~~
-
-One of DTML's important benefits is to let you customize your web
-pages. Often customization means testing conditions and responding
-appropriately.  This *if* tag lets you evaluate a condition and
-carry out different actions based on the result.
-
-What is a condition?  A condition is either a true or false
-value. In general all objects are considered true unless they are
-0, None, an empty sequence or an empty string.
-
-Here's an example condition:
-
-objectValues
-  True if the variable *objectValues* exists and
-  is true. That is to say, when found and rendered *objectValues*
-  is not 0, None, an empty sequence, or an empty string.
-
-As with the *var* tag, you can use both name syntax and expression
-syntax. Here are some conditions expressed as DTML expressions.
-
-expr="1"
-  Always true.
-
-expr="rhino"
-  True if the rhino variable is true.
-
-expr="x < 5"
-  True if x is less than 5.
-
-expr="objectValues('File')"
-  True if calling the *objectValues* method with an argument of *File*
-  returns a true value.  This method is explained in more detail in this
-  chapter.
-
-The *if* tag is a block tag. The block inside the *if* tag is executed
-if the condition is true.
-
-Here's how you might use a variable expression with the *if* tag to
-test a condition::
-
-  <p>How many monkeys are there?</p>
-
-  <dtml-if expr="monkeys > monkey_limit">
-    <p>There are too many monkeys!</p>
-  </dtml-if>
-
-In the above example, if the Python expression 'monkeys > monkey_limit'
-is true then you will see the first and the second paragraphs of
-HTML. If the condition is false, you will only see the first.
-
-*If* tags can be nested to any depth, for example, you
-could have::
-
-  <p>Are there too many blue monkeys?</p>
-
-  <dtml-if "monkeys.color == 'blue'">
-    <dtml-if expr="monkeys > monkey_limit">
-      <p>There are too many blue monkeys!</p>
-    </dtml-if>
-  </dtml-if>
-
-Nested *if* tags work by evaluating the first condition, and if that
-condition is true, then they evaluate the second
-condition.  In general, DTML *if* tags work very much like
-Python *if* statements...
-
-Name and Expression Syntax Differences
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-The name syntax checks for the *existence* of a name, as well as
-its value. For example::
-
-  <dtml-if monkey_house>
-    <p>There <em>is</em> a monkey house, Mom!</p>
-  </dtml-if>  
-
-If the *monkey_house* variable does not exist, then this condition
-is false. If there is a *monkey_house* variable but it is false,
-then this condition is also false. The condition is only true is
-there is a *monkey_house* variable and it is not 0, None, an empty
-sequence or an empty string.
-
-The Python expression syntax does not check for variable
-existence. This is because the expression must be valid
-Python. For example::
-
-  <dtml-if expr="monkey_house">
-    <p>There <em>is</em> a monkey house, Mom!</p>
-  </dtml-if>
-
-This will work as expected as long as *monkey_house* exists.  If
-the *monkey_house* variable does not exist, Zope will raise a
-*KeyError* exception when it tries to find the variable.
-
-*Else* and *Elif* Tags
-%%%%%%%%%%%%%%%%%%%%%%
-
-The *if* tag only lets you take an action if a condition is
-true. You may also want to take a different action if the
-condition is false.  This can be done with the DTML *else* tag.
-The *if* block can also contain an *else* singleton tag. For
-example::
-
-  <dtml-if expr="monkeys > monkey_limit">
-    <p>There are too many monkeys!</p>
-  <dtml-else>
-    <p>The monkeys are happy!</p>
-  </dtml-if>
-
-The *else* tag splits the *if* tag block into two blocks, the first
-is executed if the condition is true, the second is executed if
-the condition is not true.
-
-A *if* tag block can also contain a *elif* singleton tag. The *elif*
-tag specifies another condition just like an addition *if* tag.
-This lets you specify multiple conditions in one block::
-
-  <dtml-if expr="monkeys > monkey_limit">
-    <p>There are too many monkeys!</p>
-  <dtml-elif expr="monkeys < minimum_monkeys">
-    <p>There aren't enough monkeys!</p>
-  <dtml-else>
-    <p>There are just enough monkeys.</p>
-  </dtml-if>
-
-An *if* tag block can contain any number of *elif* tags but only
-one *else* tag. The *else* tag must always come after the *elif*
-tags.  *Elif* tags can test for condition using either the name
-or expression syntax.
-
-Using Cookies with the *If* Tag
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Let's look at a more meaty *if* tag example.  Often when you have
-visitors to your site you want to give them a cookie to identify
-them with some kind of special value.  Cookies are used frequently
-all over the Internet, and when they are used properly they are
-quite useful.
-
-Suppose we want to differentiate new visitors from folks who have
-already been to our site. When a user visits the site we can set a
-cookie. Then we can test for the cookie when displaying pages. If
-the user has already been to the site they will have the
-cookie. If they don't have the cookie yet, it means that they're
-new.
-
-Suppose we're running a special. First time zoo visitors get in
-for half price. Here's a DTML fragment that tests for a cookie
-using the *hasVisitedZoo* variable and displays the price
-according to whether a user is new or a repeat visitor::
-
-  <dtml-if hasVisitedZoo>
-    <p>Zoo admission <dtml-var adult_rate fmt="dollars-and-cents">.</p>
-  <dtml-else>
-    <p>Zoo admission for first time visitors
-         <dtml-var expr="adult_rate/2" fmt="dollars-and-cents"></p>
-  </dtml-if>  
-
-This fragment tests for the *hasVisitedZoo* variable. If the user
-has visited the zoo before it displays the normal price for
-admission. If the visitor is here for the first time they get in
-for half-price.
-
-Just for completeness sake, here's an implementation of the
-*hasVisitedZoo* method as a Python-based Script that has no
-parameters.::
-
-  ## Script(Python) "hasVisitedZoo"
-  ##
-  """
-  Returns true if the user has previously visited
-  the Zoo. Uses cookies to keep track of zoo visits.
-  """
-  request = context.REQUEST
-  response = request.RESPONSE
-  if request.has_key('zooVisitCookie'):
-      return 1
-  else:
-      response.setCookie('zooVisitCookie', '1')
-      return 0
-
-In the chapter entitled `Advanced Zope Scripting <ScriptingZope.html>`_,
-we'll look more closely at how to script business logic with Python.  For
-now it is sufficient to see that the method looks for a cookie and returns
-a true or false value depending on whether the cookie is found or not.
-Notice how Python uses if and else statements just like DTML uses if and
-*else* tags. DTML's *if* and *else* tags are based on Python's. In fact
-Python also has an elif statement, just like DTML.
-
-The *In* Tag
-~~~~~~~~~~~~
-
-The DTML *in* tag iterates over a sequence of objects, carrying out
-one block of execution for each item in the sequence.  In
-programming, this is often called *iteration*, or *looping*.
-
-The *in* tag is a block tag like the *if* tag.  The content of the *in*
-tag block is executed once for every iteration in the *in* tag
-loop. For example::
-
-  <dtml-in todo_list>
-    <p><dtml-var description></p>
-  </dtml-in>
-
-This example loops over a list of objects named *todo_list*. For
-each item, it inserts an HTML paragraph with a description of
-the to do item.
-
-Iteration is very useful in many web tasks.  Consider a site that
-display houses for sale.  Users will search your site for houses
-that match certain criteria.  You will want to format all of those
-results in a consistent way on the page, therefore, you will need
-to iterate over each result one at a time and render a similar
-block of HTML for each result.
-
-In a way, the contents of an *in* tag block is a kind of *template*
-that is applied once for each item in a sequence.
-
-Iterating over Folder Contents
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Here's an example of how to iterate over the contents of a
-folder. This DTML will loop over all the files in a folder and
-display a link to each one.  This example shows you how to
-display all the "File" objects in a folder, so in order to run
-this example you will need to upload some files into Zope as
-explained in the chapter entitled `Basic Zope Objects`_.
-Create a DTML Method with the following body::
-
-  <dtml-var standard_html_header>
-  <ul>
-  <dtml-in expr="objectValues('File')">
-    <li><a href="&dtml-absolute_url;"><dtml-var title_or_id></a></li>
-  </dtml-in>
-  </ul>
-  <dtml-var standard_html_footer>
-
-This code displayed the following file listing, as shown in the
-figure below.
-
-.. figure:: ../Figures/4-4.png
-
-   Iterating over a list of files
-
-Let's look at this DTML example step by step.  First, the *var*
-tag is used to insert your common header into the method.  Next,
-to indicate that you want the browser to draw an HTML bulleted
-list, you have the *ul* HTML tag.
-
-Then there is the *in* tag.  The tag has an expression that is
-calling the Zope API method called *objectValues*.  This method
-returns a sequence of objects in the current folder that match a
-given criteria.  In this case, the objects must be files.  This
-method call will return a list of files in the current folder.
-
-The *in* tag will loop over every item in this sequence.  If there are
-four file objects in the current folder, then the *in* tag will execute
-the code in its block four times; once for each object in the
-sequence.
-
-During each iteration, the *in* tag looks for variables in the
-current object, first. In the chapter entitled `Variables and
-Advanced DTML`_ we'll look more closely at how DTML
-looks up variables.
-
-For example, this *in* tag iterates over a collection of File
-objects and uses the *var* tag to look up variables in each
-file::
-
-  <dtml-in expr="objectValues('File')">
-    <li><a href="&dtml-absolute_url;"><dtml-var title_or_id></a></li>
-  </dtml-in>
-
-The first *var* tag is an entity and the second is a normal DTML
-*var* tag.  When the *in* tag loops over the first object its
-*absolute_url* and *title_or_id* variables will be inserted in
-the first bulleted list item::
-
-  <ul>
-    <li><a href="http://localhost:8080/FirstFile">FirstFile</a></li>
-
-During the second iteration the second object's *absolute_url*
-and *title_or_id* variables are inserted in the output::
-
-  <ul>
-    <li><a href="http://localhost:8080/FirstFile">FirstFile</a></li>
-    <li><a href="http://localhost:8080/SecondFile">SecondFile</a></li>
-
-This process will continue until the *in* tag has iterated over
-every file in the current folder.  After the *in* tag you
-finally close your HTML bulleted list with a closing *ul* HTML
-tag and the *standard_html_footer* is inserted.
-
-*In* Tag Special Variables
-%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-The *in* tag provides you with some useful information that
-lets you customize your HTML while you are iterating over a
-sequence.  For example, you can make your file library easier to
-read by putting it in an HTML table and making every other table
-row an alternating color, like this, as shown in the figure below.
-
-.. figure:: ../Figures/4-5.png
-
-   File listing with alternating row colors
-
-The *in* tag makes this easy.  Change your file library method a
-bit to look like this::
-
-  <dtml-var standard_html_header>
-
-  <table>
-  <dtml-in expr="objectValues('File')">
-    <dtml-if sequence-even>
-      <tr bgcolor="grey">
-    <dtml-else>
-      <tr>
-    </dtml-if>    
-    <td>
-    <a href="&dtml-absolute_url;"><dtml-var title_or_id></a>
-    </td></tr>
-  </dtml-in>
-  </table>
-
-  <dtml-var standard_html_footer>
-
-Here an *if* tag is used to test for a special variable called
-'sequence-even'.  The *in* tag sets this variable to a true or false
-value each time through the loop.  If the current iteration number is
-even, then the value is true, if the iteration number is odd, it is
-false.
-
-The result of this test is that a *tr* tag with either a gray
-background or no background is inserted for every other object in
-the sequence.  As you might expect, there is a 'sequence-odd' that
-always has the opposite value of 'sequence-even'.
-
-There are many special variables that the *in* tag defines for you.  Here
-are the most common and useful:
-
-sequence-item
-  This special variable is the current item in the
-  iteration.
-
-  In the case of the file library example, each time through the loop
-  the current file of the iteration is assigned to sequence-item.  It
-  is often useful to have a reference to the current object in the
-  iteration.
-
-sequence-index
-  the current number, starting from 0, of iterations
-  completed so far.  If this number is even, 'sequence-even' is true and
-  'sequence-odd' is false.
-
-sequence-number
-  The current number, starting from 1, of iterations
-  completed so far.  This can be thought of as the cardinal position
-  (first, second, third, etc.) of the current object in the loop.
-  If this number is even, 'sequence-even' is false and 'sequence-odd'
-  is true.
-
-sequence-start
-  This variable is true for the very first iteration.
-
-sequence-end
-  This variable is true for the very last iteration.
-
-These special variables are detailed more thoroughly in `Appendix A`_.
-
-Summary
--------
-
-DTML is a powerful tool for creating dynamic content. It allows you to
-perform fairly complex calculations. In the chapter entitled `Variables and
-Advanced DTML`_, you'll find out about many more DTML tags, and more
-powerful ways to use the tags you already have seen. Despite its power, you
-should resist the temptation to use DTML for complex scripting. In the
-chapter entitled `Advanced Zope Scripting`_ you'll find out about how to
-use Python for scripting business logic.

Modified: zope2book/trunk/source/InstallingZope.rst
===================================================================
--- zope2book/trunk/source/InstallingZope.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/InstallingZope.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -263,10 +263,9 @@
 
 You will need to provide the following values:
 
-- The directory where your instance should be located, or the
-  *INSTANCE_HOME*. The instance home will hold your database files, log
-  files, the "Extensions" and "Products" directories, configuration files,
-  and scripts to start and stop the instance.  For our example, we assume
+- The directory where your instance should be located, or the *INSTANCE_HOME*.
+  The instance home will hold your database files, log files, configuration
+  files, and scripts to start and stop the instance. For our example, we assume
   the instance home to be located at ``~/myzope/instance``.
 
 - Username and Password for an initial Zope user. You will log in with

Modified: zope2book/trunk/source/IntroducingZope.rst
===================================================================
--- zope2book/trunk/source/IntroducingZope.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/IntroducingZope.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -2,20 +2,23 @@
 ================
 
 Zope is family of related Python packages focussed on web technologies. The
-first version of Zope has originated from a company called `Zope Corporation`_.
+first version of Zope has originated from a company called
+`Zope Corporation <http://www.zope.com/>`_.
 
-Today the `Zope Foundation`_ holds the copyright of the Zope source code and
-supervises a diverse community of open-source contributers working on a
-variety of related projects.
+Today the `Zope Foundation <http://foundation.zope.org/>`_ holds the copyright
+of the Zope source code and supervises a diverse community of open-source
+contributers working on a variety of related projects.
 
 This book is about the original Zope project, today known as Zope2. When we
-refer to Zope in this book with a narrower specification we speak of Zope2.
+refer to Zope in this book without a narrower specification we speak of Zope2.
 
-Other projects include the `Zope3`_ web application framework, many individual
-packages located in the `Zope Subversion Repository`_ and projects being based
-or related to these packages like `Grok`_ and `Repoze`_. One of the more
-widely known applications based on top of Zope2 is a content management
-system called `Plone`_.
+Other projects include the `Zope3 <http://wiki.zope.org/zope3/Zope3Wiki/>`_ web
+application framework, many individual packages located in the
+`Zope Subversion Repository <http://svn.zope.org/>`_ and projects being based
+or related to these packages like `Grok <http://grok.zope.org/>`_ and
+`Repoze <http://repoze.org/>`_. One of the more widely known applications
+based on top of Zope2 is a content management system called
+`Plone <http://plone.org/>`_.
 
 Zope2 itself is a web framework that allows developers of varying skill
 levels to build *web applications*. This chapter explains Zope's purpose,
@@ -26,14 +29,6 @@
 *NOTE*: The moniker "Zope" stands for the *Z Object Publishing
 Environment* (the "Z" doesn't really mean anything in particular).
 
-.. _Zope Corporation: http://www.zope.com/
-.. _Zope Foundation: http://foundation.zope.org/
-.. _Zope3: http://wiki.zope.org/zope3/Zope3Wiki/
-.. _Zope Subversion Repository: http://svn.zope.org/
-.. _Grok: http://grok.zope.org/
-.. _Repoze: http://repoze.org/
-.. _Plone: http://plone.org/
-
 The Static Web Site Dilemma
 ---------------------------
 
@@ -167,16 +162,12 @@
 of HTML that represented an ad, or an index of ads, when a user
 visited a page in his website.
 
-A framework that allows people to construct a web application is
-often called a *web application server*, or sometimes just an
-*application server*.  Zope is a web application server, as are
-competing products like `WebSphere`_, `JBoss`_, and
-(to some extent) `SAP NetWeaver`_.
+A framework that allows people to construct a web application is often called a
+*web application server*, or sometimes just an *application server*. Zope is a
+web application server, as are competing products like `WebSphere
+<http://www.ibm.com/websphere/>`_, `JBoss <http://labs.jboss.com/jbossas/>`_,
+and (to some extent) `SAP NetWeaver <http://www.sap.com/>`_.
 
-.. _WebSphere: http://www.ibm.com/websphere/
-.. _JBoss: http://labs.jboss.com/jbossas/
-.. _SAP NetWeaver: http://www.sap.com/
-
 Zope is a web application server, which is not
 a web application in itself; rather it is *framework that allows
 people to construct web applications*. Sometimes this framework is
@@ -287,12 +278,10 @@
 
 - Zope allows and encourages third-party developers to package and
   distribute ready-made applications.  Due to this, Zope has a
-  wide variety of integrated services and add-on products
+  wide variety of integrated services and add-on packages
   available for immediate use.  Most of these components, like
   Zope itself, are free and open-source.  Zope's popularity has
-  bred a large community of application developers.  Many other
-  application servers do not have a large base of third-party
-  support or a means by which plug-ins are so neatly packaged.
+  bred a large community of application developers.
 
 - Applications created in Zope can scale almost linearly using
   Zope's built-in "Zope Enterprise Objects" (ZEO) clustering
@@ -314,18 +303,15 @@
   other application server platforms require that you run an
   operating system of their licensor's choosing.
 
-- Zope can be extended using the interpreted `Python`_ scripting language.
-  Python is popular and easy to learn, and it promotes rapid development.
-  Many libraries are available for Python that can be used when
-  creating your own application.  Many other application servers
-  must be extended using compiled languages, such as Java, which
-  cuts down on development speed.  Many other application servers
-  use less popular languages for which there are not as many
-  ready-to-use library features.
+- Zope can be extended using the interpreted `Python <http://www.python.org/>`_
+  scripting language. Python is popular and easy to learn, and it promotes
+  rapid development. Many libraries are available for Python that can be used
+  when creating your own application. Many other application servers must be
+  extended using compiled languages, such as Java, which cuts down on
+  development speed. Many other application servers use less popular languages
+  for which there are not as many ready-to-use library features.
 
-.. _Python: http://www.python.org/
 
-
 Zope Audiences and What Zope Isn't
 ----------------------------------
 
@@ -371,15 +357,13 @@
 itself is not a blog, a content management system, or a
 "e-shop-in-a-box" application.
 
-However, freely available *Plugins* built on top of Zope offer
-these kinds of services.  At the time of this writing, the
-`Python Package Index`_ lists roughly 400 `Plugins that you can
-browse`_ and even reuse in your own applications.  These include Plugins
-for blogging, content management, internationalization, and e-commerce.
+However, freely available *Plugins* built on top of Zope offer these kinds of
+services. At the time of this writing, the `Python Package Index
+<http://pypi.python.org/pypi/>`_ lists roughly 400 `Plugins that you can browse
+<http://pypi.python.org/pypi?:action=browse&c=514>`_ and even reuse in your own
+applications. These include Plugins for blogging, content management,
+internationalization, and e-commerce.
 
-.. _Plugins that you can browse: http://pypi.python.org/pypi?:action=browse&c=514
-.. _Python Package Index: http://pypi.python.org/pypi/
-
 Zope is not a visual design tool.  Tools like Macromedia
 Dreamweaver and Adobe GoLive allow designers to create "look and
 feel".  You may use these tools to successfully manage Zope-based
@@ -406,10 +390,8 @@
 The Zope community gets together occasionally at conferences, but it
 commonly discusses all things Zope on the many Zope mailing
 lists and web sites. You can find out more about Zope-related
-mailing lists at `Zope.org's mailing list page`_.
+mailing lists at `Zope.org's mailing list page <http://mail.zope.org/>`_.
 
-.. _Zope.org's mailing list page: http://mail.zope.org/
-
 Zope Corporation makes its revenue by using Zope to create web
 applications for its paying customers, by training prospective
 Zope developers, by selling support contracts to companies who use
@@ -421,39 +403,33 @@
 Zope's Terms of Use and License
 -------------------------------
 
-Zope is free of cost. You are permitted to use Zope to create and
-run your web applications without paying licensing or usage fees.
-You may also include Zope in your own products and applications
-without paying royalty fees to Zope's licensor, *Zope Foundation*.
+Zope is free of cost. You are permitted to use Zope to create and run your web
+applications without paying licensing or usage fees. You may also include Zope
+in your own products and applications without paying royalty fees to Zope's
+licensor, *Zope Foundation*.
 
-Zope is distributed under an open source license, the `Zope Public
-License or 'ZPL'`_.  The terms of the ZPL license stipulate that you will
-be able to obtain and modify the source code for Zope.
+Zope is distributed under an open source license, the `Zope Public License or
+'ZPL' <http://www.zope.org/Resources/License>`_. The terms of the ZPL license
+stipulate that you will be able to obtain and modify the source code for Zope.
 
-.. _Zope Public License or 'ZPL': http://www.zope.org/Resources/License
+The ZPL is different than another popular open source license, the `GNU Public
+License <http://www.gnu.org>`_. The licensing terms of the GPL require that if
+you intend to redistribute a GPL-licensed application, and you modify or extend
+the application in a meaningful way, when you `redistribute
+<http://www.gnu.org/licenses/gpl-faq.html#GPLRequireSourcePostedPublic>`_ a
+GPL-licensed application, you must distribute it under the terms of the GPL,
+including licensing any modifications or extensions you make under the GPL. You
+must also provide the full source code, including source for your
+modifications.
 
-The ZPL is different than another popular open source license, the
-`GNU Public License`_. The licensing terms of
-the GPL require that if you intend to redistribute a GPL-licensed
-application, and you modify or extend the application in a
-meaningful way, when you `redistribute`_
-a GPL-licensed application, you must distribute it under the terms
-of the GPL, including licensing any modifications or extensions
-you make under the GPL.  You must also provide the full source
-code, including source for your modifications.
+However, this is *not* required for ZPL-licensed applications. You may modify
+and redistribute Zope without contributing your modifications back to Zope
+Corporation, as long as you follow the other terms of the license faithfully.
 
-.. _GNU Public License: http://www.gnu.org
-.. _redistribute: http://www.gnu.org/licenses/gpl-faq.html#GPLRequireSourcePostedPublic
+Note that the ZPL has been `certified`_ as `OSD`_ compliant by the
+`Open Source Initiative`_ and is listed as `GPL compliant`_ by the
+`Free Software Foundation`_.
 
-However, this is *not* required for ZPL-licensed applications.
-You may modify and redistribute Zope without contributing your
-modifications back to Zope Corporation, as long as you follow the
-other terms of the license faithfully.
-
-Note that the ZPL has been `certified`_ as `OSD`_ compliant by
-the `Open Source Initiative`_ and is listed as `GPL compliant`_
-by the `Free Software Foundation`_.
-
 .. _certified: http://www.opensource.org/licenses/zpl.php
 .. _OSD: http://www.opensource.org/docs/definition.html
 .. _Open Source Initiative: http://www.opensource.org/
@@ -464,28 +440,24 @@
 Zope History
 ------------
 
-In 1996, Jim Fulton (the current CTO of Zope Corporation, the
-orginators of Zope) was drafted to teach a class on CGI
-programming, despite not knowing very much about the subject.  CGI,
-or *common gateway interface*, programming is a commonly-used web
-development model that allows developers to construct dynamic
-websites.  Jim studied all of the existing documentation on CGI on
-his way to the class.  On the way back from the class, Jim
-considered what he didn't like about traditional, CGI-based
-programming environments.  From these initial musings, the core of
-Zope was written on the plane flight back from the class.
+In 1996, Jim Fulton (the current CTO of Zope Corporation, the orginators of
+Zope) was drafted to teach a class on CGI programming, despite not knowing very
+much about the subject. CGI, or *common gateway interface*, programming is a
+commonly-used web development model that allows developers to construct dynamic
+websites. Jim studied all of the existing documentation on CGI on his way to
+the class. On the way back from the class, Jim considered what he didn't like
+about traditional, CGI-based programming environments. From these initial
+musings, the core of Zope was written on the plane flight back from the class.
 
-Zope Corporation (then known as Digital Creations) went on to
-release three open-source software packages to support web
-publishing: *Bobo*, *Document Template*, and *BoboPOS*.  These
-packages were written in a language called Python, and respectively
-provided a web publishing facility, text templating, and an object
-database.  Digital Creations developed a commercial
-application server based on their three open-source components.
-This product was called *Principia*.  In November of 1998,
-investor Hadar Pedhazur convinced Digital Creations to open source
-Principia.  These packages have evolved into what today are the
-core components of Zope.
+Zope Corporation (then known as Digital Creations) went on to release three
+open-source software packages to support web publishing: *Bobo*, *Document
+Template*, and *BoboPOS*. These packages were written in a language called
+Python, and respectively provided a web publishing facility, text templating,
+and an object database. Digital Creations developed a commercial application
+server based on their three open-source components. This product was called
+*Principia*. In November of 1998, investor Hadar Pedhazur convinced Digital
+Creations to open source Principia. These packages have evolved into what today
+are the core components of Zope.
 
-Most of Zope is written in the `Python`_ scripting language, with
-performance-critical pieces written in C.
+Most of Zope is written in the `Python <http://www.python.org/>`_ scripting
+language, with performance-critical pieces written in C.

Modified: zope2book/trunk/source/ObjectOrientation.rst
===================================================================
--- zope2book/trunk/source/ObjectOrientation.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/ObjectOrientation.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -1,13 +1,12 @@
 Object Orientation
 ==================
 
-To make the best use of Zope, you will need a grasp on the concept of
-*object orientation*, which is a software development pattern used in many
-programming languages (C++, Java, Python, Eiffel, Modula-2, and others) and
-computer systems that simulate "real-world" behavior.  It stipulates that
-you should design an application in terms of *objects*.  This chapter
-provides a broad overview of the fundamentals of object orientation from
-the perspective of a Zope developer.
+To make the best use of Zope, you will need a grasp on the concept of *object
+orientation*, which is a software development pattern used in many programming
+languages (C++, Java, Python and others) and computer systems that simulate
+"real-world" behavior. It stipulates that you should design an application in
+terms of *objects*. This chapter provides a broad overview of the fundamentals
+of object orientation from the perspective of a Zope developer.
 
 Objects
 -------
@@ -20,7 +19,7 @@
 In a typical, non-object-oriented application, you will have two things:
 
 - Code.  For example, a typical CGI-based web application may have a bit of
-  logic in the form of a Perl script, which retrieves employee data from a
+  logic in the form of a PHP script, which retrieves employee data from a
   database and displays tabular data to a user.
 
 - Data.  For example, you may have employee data stored in a database, such
@@ -29,7 +28,8 @@
   that operates upon it; without this code, the data holds little to no
   value.
 
-In a typical object-oriented application, however, you will have one thing, and one thing only:
+In a typical object-oriented application, however, you will have one thing, and
+one thing only:
 
 - Objects.  Simply stated, these objects are collections of code and data
   wrapped up together.  For example, you may have an "Employee" object that
@@ -39,17 +39,16 @@
   or code, that can manipulate and display its data.
 
 In a non-object-oriented application, your data is kept separate from your
-code.  But in an object-oriented application, both your data and your code
-are stored in one or more objects, each of which represents a particular
-"thing".  These objects can represent just about anything.  In Zope, the
-*Control_Panel* is an object, Folders that you create are objects, and even
-the Zope "root folder" is an object.  When you use the Zope "add list" to
-create a new item in the Zope Management Interface, you are creating an
-object.  People who extend Zope by creating *Products* define their own
-types of objects, which are then entered in to the Zope "add list" so that
-you can create objects based on them.  A Product author might define a
-"Form" object or a "Weblog" object.  Basically, anything that can be
-defined  using a noun can be modelled as a Zope object.
+code. But in an object-oriented application, both your data and your code are
+stored in one or more objects, each of which represents a particular "thing".
+These objects can represent just about anything. In Zope, the *Control_Panel*
+is an object, Folders that you create are objects, and even the Zope "root
+folder" is an object. When you use the Zope "add list" to create a new item in
+the Zope Management Interface, you are creating an object. People who extend
+Zope by creating add-ons define their own types of objects, which are then
+entered in to the Zope "add list" so that you can create objects based on them.
+An add-on author might define a "Form" object or a "Weblog" object. Basically,
+anything that can be defined using a noun can be modeled as a Zope object.
 
 As a programming methodology, object orientation allows software developers
 to design and create programs in terms of "real-world" things, such as
@@ -88,9 +87,6 @@
 *state*.  When one or more of an object's attributes are modified, the
 object is said to have *changed its state*.
 
-Special kinds of web-editable object attributes in Zope are sometimes
-referred to as *Properties*.
-
 Methods
 -------
 
@@ -110,14 +106,6 @@
 data that is passed to it via arguments, it may also operate on the
 attributes of the object to which it is bound.
 
-Some objects in Zope are actually called "methods".  For example, there are
-*DTML Methods*, *SQL Methods*, and *External Methods*, because these
-objects are meant to be used in a "method-ish" way.  They are "bound" to
-their containing Folder object by default when called, and the logic that
-they contain typically makes reference to their containing Folder.  *Script
-(Python)* objects in Zope act similarly through their concept of
-"Bindings."
-
 Messages
 --------
 
@@ -175,7 +163,7 @@
 can be constructed using the same class. Objects that share a class
 typically behave identically to one other.  If you visit two houses that
 share the same set of blueprints, you will likely notice striking
-similaries: the layout will be the same, the light switches will be in the
+similarities: the layout will be the same, the light switches will be in the
 same places, and the fireplace will almost certainly be in the same
 location.  The shower curtains might be different in each house, but this
 is an *attribute* of each particular house that doesn't change its
@@ -194,15 +182,14 @@
 *behavior* of that object.
 
 The objects constructed by a class are called *instances of the class*, or
-(more often) just *instances*.  For example, the Zope 'Examples' folder is
-an *instance of* the 'Folder' class. The 'Examples' folder has an 'id'
-attribute of 'Examples', while another folder may have an 'id' attribute of
-'MyFolder'.  However, while they have different attribute values, since
+(more often) just *instances*.  For example, the Zope 'index' page is
+an *instance of* the 'Page Template' class. The 'index' page has an 'id'
+attribute of 'index', while another page may have an 'id' attribute of
+'my_page'.  However, while they have different attribute values, since
 they are both instances of the same class, they both behave identically.
 All the objects that can be administered using the ZMI are instances of a
 class.  Typically, the classes from which these objects are constructed are
-defined in the Zope *Products* created by Zope developers and community
-members.
+defined in the add-ons created by Zope developers and community members.
 
 Inheritance
 -----------
@@ -255,7 +242,7 @@
 by either a programmer or a user of the system in which the objects "live".
 
 Instances of web-manageable objects in Zope, such as Files, Folders, and
-DTML Methods, span from the time the user creates them until they are
+Page Templates, span from the time the user creates them until they are
 deleted. You will often hear these kinds of objects described as
 *persistent* objects.  These objects are stored in Zope's object database
 (the ZODB).
@@ -281,10 +268,6 @@
 including attributes, methods, classes, and inheritance, before setting out
 on a "for-production" Zope development project.
 
-For a more lighthearted description of what object orientation is and how
-it relates to Zope, see Chris McDonough's `Gain Zope Enlightenment by
-Grokking Object Orientation
-<http://www.zope.org/Members/mcdonc/HowTos/gainenlightenment>`_.
 For a more comprehensive treatment on the subject of object orientation,
 buy and read `The Object
 Primer <http://www.ambysoft.com/theObjectPrimer.html>`_ by Scott Ambler.

Modified: zope2book/trunk/source/Preface.rst
===================================================================
--- zope2book/trunk/source/Preface.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/Preface.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -12,7 +12,46 @@
 but you may find the understanding of some programming concepts (particularly
 in object-oriented programming) to be extremely helpful.
 
+Preface to the 2.12 edition
+---------------------------
 
+This book has originally been written for Zope 2.6 back in 2002. It has been
+available in an almost unmodified form for the last seven years. During those
+many years quite a bit has happened in Zope itself and the general web market.
+
+The 2.12 edition of this book does not try to write a new book on how-to do
+Zope development today. Instead it tries to update the original books content
+to be true and helpful again. Many of the underlying principles of Zope2 have
+not changed in the last years. The ZMI, security machinery, page templates and
+how-to use the ZCatalog are still there in an almost unmodified fashion.
+The general ideas behind object orientation, being Python based and the
+general architecture are still the same.
+
+If you want to understand Zope2 you still need to understand how Acquisition
+works, even though it has been discouraged as a way to design your application
+logic.
+
+One of the most notable differences between the original Zope2 approach and
+todays best-practices is in the way you develop applications with Zope2. The
+original Zope2 approach has focussed on a Through-The-Web (TTW) development
+model. You would create your entire application and manage your data through
+the same browser interface and store everything transparently in the same
+database. This model has worked very well in the beginning of "the web" as
+many dynamic websites have been rather simple and specialized projects.
+
+Over the years websites have grown their requirements and often turned into
+development projects of a considerable size. Today websites are understood
+as applications in themselves and need an approach which is no longer
+compatible with the TTW approach of the early Zope2.
+
+In this book you will still read about using the TTW approach for many of
+the examples. Please understand this as a way to quickly and easily learn
+about the underlying technologies. If you want to built an application based
+on top of Zope2, you are almost always better of approaching the project from
+the so called "file-system based approach" or using Python packages to extend
+Zope in a predictable way.
+
+
 How the Book Is Organized
 -------------------------
 
@@ -61,63 +100,44 @@
     This chapter introduces *acquisition*, which is Zope's
     mechanism for sharing site behavior and content.
 
-8. Basic DTML
+8. Using Zope Page Templates
 
-    This chapter introduces *DTML*, Zope's tag-based scripting
-    language.  You'll learn DTML syntax, its basic tags, 
-    and how to use DTML templates and
-    scripting facilities.  After reading this chapter,
-    you'll be able to create dynamic web pages.
-
-9. Using Zope Page Templates
-
     This chapter introduces *Zope Page Templates*, another Zope tool
     used to create dynamic web pages. You will learn about basic
     template statements that let you insert dynamic content, and how
     to create and edit page templates.
 
-10. Creating Basic Zope Applications  
+9. Creating Basic Zope Applications  
 
     This chapter presents several real-world
     examples of building a Zope application.  You'll learn how to
     use basic Zope objects and how they can work together to form
     basic applications.
 
-11. Users and Security
+10. Users and Security
 
     This chapter looks at how Zope handles users, authentication,
     authorization, and other security-related matters.
 
-12. Advanced DTML
+11. Advanced Page Templates
 
-    This chapter takes a closer look at DTML. You'll learn about DTML
-    security, the tricky issue of how variables are looked up
-    in DTML, advanced use of basic tags, 
-    and the myriad of special purpose tags.
+    This chapter goes into more depth with Zope Page Templates. You will learn
+    all about template statements, expression types, and macros, which let you
+    reuse presentation elements.
 
-13. Advanced Page Templates
+12. Advanced Zope Scripting
 
-    This chapter goes into more depth with Zope Page Templates. You will learn 
-    all about template statements, expression
-    types, and macros, which let you reuse presentation
-    elements.
+    This chapter covers scripting Zope with Python. You will learn how to write
+    business logic in Zope using tools more powerful than TAL, about the idea
+    of *scripts* in Zope, and about Scripts (Python).
 
-14. Advanced Zope Scripting
+13. Zope Services
 
-    This chapter covers scripting Zope with Python and Perl.  You will learn
-    how to write business logic in Zope using tools more
-    powerful than DTML, about the idea of *scripts* in
-    Zope, and about Python and Perl-based scripts.  This
-    chapter shows you how to add industrial-strength scripting to
-    your site.
-
-17. Zope Services
-
     This chapter covers Zope objects that are considered "services," which
     don't readily fit into any of the basic "content,"
     "presentation," or "logic" object groups.
 
-15. Searching and Categorizing Content
+14. Searching and Categorizing Content
 
     This chapter shows you how to index and search objects with
     Zope's built-in search engine: the *Catalog*. You'll learn about 
@@ -125,7 +145,7 @@
     indexing and searching, metadata, and
     search results. 
 
-16. Relational Database Connectivity
+15. Relational Database Connectivity
 
     This chapter describes how Zope connects to external
     relational databases.  You'll learn about features that allow you
@@ -133,7 +153,7 @@
     objects, and security and performance
     considerations.
 
-17. Virtual Hosting Services
+16. Virtual Hosting Services
 
     This chapter explains how to set up Zope in a "virtual hosting"
     environment, in which Zope sub-folders can be served as "top-level"
@@ -141,12 +161,12 @@
     be performed either "natively" or using Apache's 'mod_rewrite'
     facility.
 
-18. Sessions
+17. Sessions
 
     This chapter describes Zope's "sessioning" services, which allow
     Zope developers to "keep state" between HTTP requests.
 
-19. Scalability and ZEO
+18. Scalability and ZEO
 
     This chapter covers issues and solutions for building and
     maintaining large web applications, and focuses on issues of
@@ -155,34 +175,31 @@
     tools and techniques needed to turn a small site into a
     large-scale site, servicing many simultaneous visitors.
 
-20. Managing Zope Objects Using External Tools
+19. Managing Zope Objects Using External Tools
 
     This chapter explains how to use tools outside of your web
     browser to manipulate Zope objects.
 
-21. Extending Zope
+20. Extending Zope
 
-    This chapter covers extending Zope by creating your own
-    classes of objects. You'll learn about *ZClasses*, how instances
-    are built from classes, and how to build a ZClass and
-    its attendant security and design issues.  You'll also learn how to create 
-    Python base classes for ZClasses, and about 
-    the base classes that ship with Zope.
+    This chapter covers extending Zope by creating your own classes of objects.
+    You'll learn how to create Python base classes and about the base classes
+    that ship with Zope.
 
-22. Maintaining Zope
+21. Maintaining Zope
 
     This chapter covers Zope maintenance and administration tasks,
-    such as database "packing" and Product installation.
+    such as database "packing" and package installation.
 
-23. Appendix A: DTML Reference
+22. Appendix A: DTML Reference
 
     Reference of DTML syntax and commands.
 
-24. Appendix B:  API Reference
+23. Appendix B:  API Reference
 
     Reference of Zope object APIs.
 
-25. Appendix C:  Page Template Reference
+24. Appendix C:  Page Template Reference
 
     Reference of Zope Page Template syntax and commands.
 
@@ -193,16 +210,3 @@
 
 26. Appendix E: DTML Name Lookup Rules
     Describes DTML's name lookup rules.
-
-
-Conventions Used in This Book
------------------------------
-
-This book uses the following typographical conventions:
-
-*Italic*
-  Italics indicate variables and names and is also used to introduce new terms.
-
-``Fixed width``
-  Fixed width text indicates objects, commands, hyperlinks, and code
-  listings.

Modified: zope2book/trunk/source/RelationalDatabases.rst
===================================================================
--- zope2book/trunk/source/RelationalDatabases.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/RelationalDatabases.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -119,9 +119,8 @@
 
 A database can only be used if a Zope Database Adapter is available,
 though a Database Adapter is fairly easy to write if the database has
-Python support. Database adapters can be downloaded from the `Products
-section of Zope.org <http://www.zope.org/Products/>`_  The exception to
-this is Gadfly, which is included with Zope.
+Python support. Database adapters can be found in the
+`Zope Framework category of the Python Package Index <http://pypi.python.org/pypi?:action=browse&c=514>`_.
 
 At the time of writing the following adapters were available, but this
 list constantly changes as more adapters are added.
@@ -170,9 +169,6 @@
   `informixdb <http://starship.python.net/crew/sturner/informixdb.html>`_
   package.
 
-Gadfly
-  The Gadfly Database Adapter is built into Zope.
-
 If you will need to connect to more than one database or wish to connect
 as to the same database as different users then you may use multiple
 database connection objects.
@@ -479,7 +475,7 @@
 
   <div>
     <ul>
-      <li tal:repeat="row here/list_all_employees">
+      <li tal:repeat="row context/list_all_employees">
         <span tal:content="string:${row/id}: ${row/last} ${row/first} 
               makes ${row/salary} Euro a year.
       </li>
@@ -957,7 +953,7 @@
 and the ZPT version::
 
   <div>
-    <tal:div  tal:repeat="row python: here.employee_by_id(emp_id=42)">
+    <tal:div  tal:repeat="row python: context.employee_by_id(emp_id=42)">
       <h1 tal:content="string: ${row/last}, ${row/first}" />
       <p>
        <span tal:content="string:${row/first}s employee id is ${row/emp_id}. 
@@ -1146,16 +1142,12 @@
 Up to now we have just been iterating through the attributes of
 the Result object in DTML. The result object does however provide
 other methods which can be easier in some situations. These
-methods can be accessed from Python scripts, page templates and
-from DTML. For example in Python we could write::
+methods can be accessed from Scripts (Python) and page templates.
+For example in Python we could write::
 
   result=context.list_all_employees()
   return len(result)
 
-which in DTML would be::
-
-  <dtml-var "_.len(list_all_employees())">
-
 and in ZPT::
 
   <span tal:content="python: len(list_all_employees())" />

Modified: zope2book/trunk/source/ScriptingZope.rst
===================================================================
--- zope2book/trunk/source/ScriptingZope.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/ScriptingZope.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -6,54 +6,43 @@
 we will explore this topic some more.  Subjects discussed
 include additional scripting objects, script security, and
 calling script objects from presentation objects like Page
-Templates or DTML Methods.  As we have mentioned before,
+Templates.  As we have mentioned before,
 separation of logic and presentation is a key factor in
-implementing maintainable web applications. 
+implementing maintainable web applications.
 
 What is *logic* and how does it differ from presentation? Logic
 provides those actions which change objects, send messages, test
 conditions and respond to events, whereas presentation formats and
-displays information and reports. Typically you will use DTML or
+displays information and reports. Typically you will use
 Page Templates to handle presentation, and Zope scripting to
 handle logic.
 
-Zope Scripts
-------------
+Warning
+-------
 
-Zope *Script* objects are objects that encapsulate a small
-chunk of code written in a programming language. Script
-objects first appeared in Zope 2.3, and are now the
-preferred way to write programming logic in Zope. Currently,
-Zope comes with *Python-based Scripts*, which are written in
-the Python language.  We have discussed Python-based Scripts
-in the "Basic Zope Scripting" chapter; below we will present
-*External Methods*, a filesystem-based scripting object
-without the security restrictions of *Python-based Scripts*.
-These are also written in Python, but the code is stored on
-the filesystem. External Methods allow you to do many things
-that are restricted from Python-based Scripts.
+Zope *Script* objects are objects that encapsulate a small chunk of code
+written in a programming language. They first appeared in Zope 2.3, and have
+been the preferred way to write programming logic in Zope for many years. Today
+it is discouraged to use Scripts for any but the most minimal logic. If you
+want to create more than trivial logic, you should approach this by creating a
+Python package and write your logic *on the file system*.
 
+This book does not cover this development approach in its details. This
+chapter is still useful to read, as it allows you to get an understanding on
+some of the more advanced techniques and features of Zope.
 
 Calling Scripts
 ---------------
 
-In the "Basic Zope Scripting" chapter, you learned how to
-call scripts from the web and, conversely, how to call Page
-Templates and DTML from Python-based Scripts.  In addition,
-any type of script may be called by any other type of
-object; you can call a Python-based Script from a DTML
-Method, or a built-in method from an External Method.  In
-fact scripts can call scripts which call other scripts, and
-so on.  For example, if you're using a Python-based Script
-to perform a task, but later decide that it would be better
-done in an External Method, you can usually replace the
-script with an External Method with the same id.
+In the "Basic Zope Scripting" chapter, you learned how to call scripts from the
+web and, conversely, how to call Page Templates from Python-based Scripts. In
+fact scripts can call scripts which call other scripts, and so on.
 
 Calling Scripts from Other Objects
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-You can call scripts from other objects, whether they are DTML
-objects, Page Templates, or Scripts (Python). The
+You can call scripts from other objects, whether they are
+Page Templates or Scripts (Python). The
 semantics of each language differ slightly, but the same rules
 of acquisition apply. You do not necessarily have to know what
 language is used in the script you are calling; you only need to
@@ -67,7 +56,7 @@
 expressions as described in the chapter entitled "Using Zope
 Page Templates.":ZPT.html>`_  For example::
 
-  <div tal:replace="here/hippo/feed">
+  <div tal:replace="context/hippo/feed">
     Output of feed()
   </div>
 
@@ -75,13 +64,12 @@
 quoting by using the *structure* keyword, as described in
 the chapter entitled `Advanced Page Templates <AdvZPT.html>`_
 
-Page Templates do not really provide an equivalent to DTML's
-*call* tag. To call a script without inserting a value in the
+To call a script without inserting a value in the
 page, you can use *define* and ignore the variable assigned::
 
-  <div tal:define="dummy here/hippo/feed" />
+  <div tal:define="dummy context/hippo/feed" />
 
-In a page template, *here* refers to the current context.  It
+In a page template, *context* refers to the current context.  It
 behaves much like the *context* variable in a Python-based
 Script.  In other words, *hippo* and *feed* will both be
 looked up by acquisition.
@@ -89,26 +77,17 @@
 If the script you call requires arguments, you must use a 
 TALES python expression in your template, like so::
 
-  <div tal:replace="python:here.hippo.feed(food='spam')">
+  <div tal:replace="python:context.hippo.feed(food='spam')">
     Output of feed(food='spam')
   </div>
 
-Just as in Path Expressions, the 'here' variable refers to the
+Just as in Path Expressions, the 'context' variable refers to the
 acquisition context the Page Template is called in.  
 
 The python expression above is exactly like a line of
-code you might write in a Script (Python). One
-difference is the name of the variable used to get the
-acquisition context, called 'here' in TALES, 'context' in
-Script (Python).  Don't be misled by the different
-terminology: context is context, whatever you call
-it. Unfortunately, the different names used in ZPT and
-Python Scripts evolved independently.  (Note that as of
-this writing, the ZPT variable *here* is planned to
-become *context* in a future version of Zope, probably
-Zope 3.). 
+code you might write in a Script (Python).
 
-Another difference is the notation used for attribute access --
+One difference is the notation used for attribute access --
 Script (Python) uses the standard Python period notation,
 whereas in a TALES path expression, a forward slash is
 used.
@@ -116,56 +95,11 @@
 For further reading on using Scripts in Page Templates, refer
 to the chapter entitled `Advanced Page Templates`_.
 
-Calling Scripts from DTML 
-%%%%%%%%%%%%%%%%%%%%%%%%%
-
-As you saw in the chapter entitled `Advanced DTML <AdvDTML.html>`_,
-you can call Zope scripts from DTML with the *call* tag. For example::
-
-  <dtml-call updateInfo>
-
-DTML will call the *updateInfo* script, whether it is
-implemented in a Python-based SWcript, Page Template, or
-any other object.
-
-If the *updateInfo* script requires parameters, either your script 
-must have a name for the DTML namespace binding (see *Binding
-Variables* in the section "Using Python-based Scripts" below), 
-so that the parameters will be looked up in the DTML
-namespace, or you must pass the parameters in an expression.
-For example:: 
-
-  <dtml-call expr="updateInfo(color='brown', pattern='spotted')">
-
-You can also pass in any variables that are valid in
-the current DTML namespace. For example, if *newColor*
-and *newPattern* are defined using *dtml-let*, you could pass the
-variables as parameters like this::
-
-  <dtml-call expr="updateInfo(color=newColor, pattern=newPattern)">
-
-You can also pass variables that are defined automatically
-by dtml tags such as *dtml-in*. For example::
-
-  <dtml-in all_animals prefix="seq">
-    <dtml-call expr="feed(animal=seq_item)">
-  </dtml-in>
-
-This assumes that *feed* is a script and has a parameter
-called *animal*.  The standard names used during DTML
-loops ('sequence-item', 'sequence-key', et al.) are a
-bit cumbersome to spell out in a Python *expr*, because
-'sequence-item' would be interpreted as 'sequence' minus
-'item'.  To avoid this problem, we use the *prefix*
-attribute of the dtml-in tag, which then uses the
-specified value ("seq") and an underscore ("_") instead
-of the customary "sequence-" string.
-
 Calling scripts from Python
 %%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-Calling scripts from other Python scripts works the same
-as calling scripts from DTML, except that you must
+Calling scripts from other scripts works similar to calling
+scripts from page templates, except that you must
 *always* use explicit calling (by using
 parentheses). For example, here is how you might call
 the *updateInfo* script from Python::
@@ -205,43 +139,26 @@
 Calling Scripts: Summary and Comparison
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-Let's  recap  the ways  to  call  a hypothetical  *updateInfo*
-script on a *foo* object, with argument passing: from your web
-browser,  from Python, from DTML,  and  from Page
+Let's recap the ways to call a hypothetical *updateInfo* script on a *foo*
+object, with argument passing: from your web browser, from Python and from Page
 Templates.
 
 - by URL::
 
    http://my-zope-server.com:8080/foo/updateInfo?amount=lots
 
-- from a Python script::
+- from a Script (Python)::
 
    context.foo.updateInfo(amount="lots")
 
 - from a Page Template::
 
-   <span tal:content="here/foo/updateInfo" />
+   <span tal:content="context/foo/updateInfo" />
 
 - from a Page Template, with arguments::
 
-   <span tal:content="python:here.foo.updateInfo(amount='lots')" />
+   <span tal:content="python:context.foo.updateInfo(amount='lots')" />
 
-- from DTML::
-
-   <dtml-with foo >
-    <dtml-var updateInfo>
-   </dtml-with>
-
-- from DTML, with arguments::
-
-   <dtml-with foo>
-    <dtml-var expr="updateInfo(amount='lots')">
-   </dtml-with>
-
-- another DTML variant::
-
-   <dtml-var expr="_['foo'].updateInfo()">
-
 Regardless of the language used, this is a very common idiom
 to find an object, be it a script or any other kind of object:
 you ask the context for it, and if it exists in this context
@@ -268,452 +185,25 @@
 the *updateInfo* variable is None, and if not, we know we can
 call it.
 
-Using External Methods
-----------------------
-
-Sometimes the security constraints imposed by Python-based
-Scripts, DTML and ZPT get in your way. For example, you
-might want to read files from disk, or access the network,
-or use some advanced libraries for things like regular
-expressions or image processing.  In these cases you can use
-*External Methods*.   We encountered External Methods briefly
-in the chapter entitled `Using Basic Zope Objects <BasicObjects.html>`_ .
-Now we will explore them in more detail.
-
-To create and edit External Methods you need access
-to the filesystem. This makes editing these scripts more
-cumbersome since you can't edit them right in your web
-browser. However, requiring access to the server's filesystem
-provides an important security control. If a user has access
-to a server's filesystem they already have the ability to harm
-Zope. So by requiring that unrestricted scripts be edited on
-the filesystem, Zope ensures that only people who are already
-trusted have access.
-
-External Method code is created and edited in files on the Zope
-server in the *Extensions* directory. This directory is located in
-the top-level Zope directory. Alternately you can create and edit
-your External Methods in an *Extensions* directory inside an
-installed Zope product directory, or in your INSTANCE_HOME
-directory if you have one. See the chapter entitled "Installing
-and Starting Zope":InstallingZope.html>`_ for more about
-INSTANCE_HOME.
-
-Let's take an example. Create a file named *example.py* in the
-Zope *Extensions* directory on your server. In the file, enter the
-following code::
-
-  def hello(name="World"):
-      return "Hello %s." % name 
-
-You've created a Python function in a Python module. But you have
-not yet created an External Method from it. To do so, we must add
-an External Method object in Zope.
-
-To add an External Method, choose *External Method* from the
-product add list. You will be taken to a form where you must
-provide an id. Type "hello" into the *Id* field, type "hello" in
-the *Function name* field, and type "example" in the *Module name*
-field. Then click the *Add* button.  You should now see a new
-External Method object in your folder. Click on it. You should be
-taken to the *Properties* view of your new External Method as
-shown in the figure below.
-
-.. figure:: ../Figures/8-7.png
-
-   External Method *Properties* view
-
-Note that if you wish to create several related External
-Methods, you do not need to create multiple modules on the
-filesystem.  You can define any number of functions in one
-module, and add an External Method to Zope for each
-function. For each of these External Methods, the *module
-name* would be the same, but *function name* would vary.
-
-Now test your new script by going to the *Test* view. You should
-see a greeting. You can pass different names to the script by
-specifying them in the URL. For example,
-'hello?name=Spanish+Inquisition'.
-
-This example is exactly the same as the "hello world" example that
-you saw for Python-based scripts. In fact, for simple string
-processing tasks like this, scripts offer a better solution since
-they are easier to work with.
-
-The main reasons to use an External Method are to access
-the filesystem or network, or to use Python packages that are
-not available to restricted scripts.
-
-For example, a Script (Python) cannot access environment variables
-on the host system. One could access them using an External
-Method, like so::
-
-  def instance_home():
-     import os
-     return os.environ.get('INSTANCE_HOME')
-
-Regular expressions are another useful tool that are restricted
-from Scripts.  Let's look at an example.  Assume we want to get
-the body of an HTML Page (everything between the 'body' and
-'/body' tags)::
-
-  import re
-  pattern = r"<\s*body.*?>(.*?)</body>"
-  regexp = re.compile(pattern, re.IGNORECASE + re.DOTALL)
-
-  def extract_body(htmlstring):
-      """
-      If htmlstring is a complete HTML page, return the string
-      between (the first) <body> ... </body> tags
-      """
-      matched = regexp.search(htmlpage)
-      if matched is None: return "No match found"
-      body = matched.group(1)
-      return body 
-
-Note that we import the 're' module and define the regular
-expression at the module level, instead of in the function itself;
-the 'extract_body()' function will find it anyway. Thus, the
-regular expression is compiled once, when Zope first loads the
-External Method, rather than every time this External Method is
-called.  This is a common optimization tactic.
-
-Now put this code in a module called 'my_extensions.py'. Add an
-'External Method' with an id of 'body_external_m'; specify
-'my_extensions' for the 'Module Name' to use and, 'extract_body'
-for 'Function Name'.
-
-You could call this for example in a 'Script (Python)' called
-'store_html' like this::
-
-  ## Script (Python) "store_html"
-  ##
-
-  # code to get 'htmlpage' goes here...
-  htmlpage = "some string, perhaps from an uploaded file"
-  # now extract the body
-  body = context.body_external_m(htmlpage)
-  # now do something with 'body' ...
-
-... assuming that body_external_m can be acquired by store_html.
-This is obviously not a complete example; you would want
-to get a real HTML page instead of a hardcoded one, and you would
-do something sensible with the value returned by your External
-Method. 
-
-Creating Thumbnails from Images
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Here is an example External Method that uses the Python Imaging
-Library (PIL) to create a thumbnail version of an existing Image
-object in a Folder.  Enter the following code in a file named
-*Thumbnail.py* in the *Extensions* directory::
-
-  def makeThumbnail(self, original_id, size=200):
-      """
-      Makes a thumbnail image given an image Id when called on a Zope
-      folder.
-
-      The thumbnail is a Zope image object that is a small JPG
-      representation of the original image. The thumbnail has an
-      'original_id' property set to the id of the full size image
-      object.
-      """
-
-      import PIL 
-      from StringIO import StringIO
-      import os.path 
-      # none of the above imports would be allowed in Script (Python)!
-
-      # Note that PIL.Image objects expect to get and save data
-      # from the filesystem; so do Zope Images. We can get around 
-      # this and do everything in memory by using StringIO.
-
-      # Get the original image data in memory.
-      original_image=getattr(self, original_id)
-      original_file=StringIO(str(original_image.data))
-
-      # create the thumbnail data in a new PIL Image. 
-      image=PIL.Image.open(original_file)
-      image=image.convert('RGB')
-      image.thumbnail((size,size))
-
-      # get the thumbnail data in memory.
-      thumbnail_file=StringIO()
-      image.save(thumbnail_file, "JPEG") 
-      thumbnail_file.seek(0)
-
-      # create an id for the thumbnail
-      path, ext=os.path.splitext(original_id)
-      thumbnail_id=path + '.thumb.jpg'
-
-      # if there's an old thumbnail, delete it
-      if thumbnail_id in self.objectIds():
-          self.manage_delObjects([thumbnail_id])
-
-      # create the Zope image object for the new thumbnail
-      self.manage_addProduct['OFSP'].manage_addImage(thumbnail_id,
-                                                     thumbnail_file,
-                                                     'thumbnail image')
-
-      # now find the new zope object so we can modify 
-      # its properties.
-      thumbnail_image=getattr(self, thumbnail_id)
-      thumbnail_image.manage_addProperty('original_id', original_id, 'string')
-
-Notice that the first parameter to the above function is called
-*self*. This parameter is optional. If *self* is the first parameter 
-to an External Method function definition, it will be assigned 
-the value of the calling context (in this case, a folder). 
-It can be used much like the *context* we have seen in 
-Scripts (Python).
-
-You must have PIL installed for this example to work. Installing
-PIL is beyond the scope of this book, but note that it is
-important to choose a version of PIL that is compatible with the
-version of Python that is used by your version of Zope. See the
-"PythonWorks
-website":http://www.pythonware.com/products/pil/index.htm for more
-information on PIL.  
-
-To continue our example, create an External Method named
-*makeThumbnail* that uses the *makeThumbnail* function in the
-*Thumbnail* module.
-
-Now you have a method that will create a thumbnail image. You can
-call it on a Folder with a URL like
-*ImageFolder/makeThumbnail?original_id=Horse.gif* This would
-create a thumbnail image named 'Horse.thumb.jpg'.
-
-You can use a script to loop through all the images in a folder and
-create thumbnail images for them. Create a Script (Python) named
-*makeThumbnails*::
-
-  ## Script (Python) "makeThumbnails"
-  ##
-  for image_id in context.objectIds('Image'):
-      context.makeThumbnail(image_id)
-
-This will loop through all the images in a folder and create a
-thumbnail for each one.
-
-Now call this script on a folder with images in it. It will create a
-thumbnail image for each contained image. Try calling the
-*makeThumbnails* script on the folder again and you'll notice it created
-thumbnails of your thumbnails. This is no good. You need to change the
-*makeThumbnails* script to recognize existing thumbnail images and not
-make thumbnails of them. Since all thumbnail images have an
-*original_id* property you can check for that property as a way of
-distinguishing between thumbnails and normal images::
-
-  ## Script (Python) "makeThumbnails"
-  ##
-  for image in context.objectValues('Image'):
-      if not image.hasProperty('original_id'):
-          context.makeThumbnail(image.getId())
-
-Delete all the thumbnail images in your folder and try calling your
-updated *makeThumbnails* script on the folder. It seems to work
-correctly now.
-
-Now with a little DTML you can glue your script and External Method
-together. Create a DTML Method called *displayThumbnails*::
-
-  <dtml-var standard_html_header>
-
-  <dtml-if updateThumbnails>
-    <dtml-call makeThumbnails>
-  </dtml-if>
-
-  <h2>Thumbnails</h2>
-
-  <table><tr valign="top">
-
-  <dtml-in expr="objectValues('Image')">
-    <dtml-if original_id>
-      <td>
-        <a href="&dtml-original_id;"><dtml-var sequence-item></a>
-        <br />
-        <dtml-var original_id>
-      </td> 
-    </dtml-if>
-  </dtml-in>
-
-  </tr></table>
-
-  <form>
-  <input type="submit" name="updateThumbnails"
-         value="Update Thumbnails" />
-  </form>
-
-  <dtml-var standard_html_footer>
-
-When you call this DTML Method on a folder it will loop through all the
-images in the folder and display all the thumbnail images and link them
-to the originals as shown in the figure below.
-
-.. figure:: ../Figures/8-8.png
-
-   Displaying thumbnail images
-
-This DTML Method also includes a form that allows you to update the
-thumbnail images. If you add, delete or change the images in your
-folder you can use this form to update your thumbnails.
-
-This example shows a good way to use scripts, External Methods and DTML
-together. Python takes care of the logic while the DTML handles
-presentation. Your External Methods handle external packages 
-such as PIL while your scripts do simple processing of Zope objects.
-Note that you could just as easily use a Page Template instead of DTML.
-  
-Processing XML with External Methods
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can use External Methods to do nearly anything. One interesting
-thing that you can do is to communicate using XML. You can generate and
-process XML with External Methods.
-
-Zope already understands some kinds of XML messages such as
-XML-RPC and WebDAV. As you create web applications that communicate
-with other systems you may want to have the ability to receive XML
-messages. You can receive XML a number of ways: you can read XML files
-from the file system or over the network, or you can define scripts
-that take XML arguments which can be called by remote systems.
-
-Once you have received an XML message you must process the XML to find
-out what it means and how to act on it.  Let's take a quick look at how
-you might parse XML manually using Python. Suppose you want to connect
-your web application to a "Jabber":http://www.jabber.com/ chat
-server. You might want to allow users to message you and receive
-dynamic responses based on the status of your web application. For
-example suppose you want to allow users to check the status of animals
-using instant messaging. Your application should respond to XML instant
-messages like this::
-
-  <message to="cage_monitor at zopezoo.org" from="user at host.com">
-    <body>monkey food status</body>
-  </message>
-
-You could scan the body of the message for commands, call a script
-and return responses like this::
-
-  <message to="user at host.com" from="cage_monitor at zopezoo.org">
-    <body>Monkeys were last fed at 3:15</body>
-  </message>
-
-Here is a sketch of how you could implement this XML messaging
-facility in your web application using an External Method::
-
-  # Uses Python 2.x standard xml processing packages.  See
-  # http://www.python.org/doc/current/lib/module-xml.sax.html for
-  # information about Python's SAX (Simple API for XML) support If
-  # you are using Python 1.5.2 you can get the PyXML package. See
-  # http://pyxml.sourceforge.net for more information about PyXML.
-
-  from xml.sax import parseString
-  from xml.sax.handler import ContentHandler
-
-  class MessageHandler(ContentHandler):
-      """
-      SAX message handler class
-
-      Extracts a message's to, from, and body
-      """
-
-      inbody=0
-      body=""
-
-      def startElement(self, name, attrs):
-          if name=="message":
-              self.recipient=attrs['to']
-              self.sender=attrs['from']
-          elif name=="body":
-              self.inbody=1
-
-      def endElement(self, name):
-          if name=="body":
-              self.inbody=0
-
-      def characters(self, content):
-          if self.inbody:
-              self.body=self.body + content
-
-  def receiveMessage(self, message):
-      """
-      Called by a Jabber server
-      """
-      handler=MessageHandler()
-      parseString(message, handler)
-
-      # call a script that returns a response string
-      # given a message body string
-      response_body=self.getResponse(handler.body)
-
-      # create a response XML message
-      response_message="""
-        <message to="%s" from="%s">
-          <body>%s</body>
-        </message>""" % (handler.sender, handler.recipient, response_body)
-
-      # return it to the server
-      return response_message
-
-The *receiveMessage* External Method uses Python's SAX (Simple API
-for XML) package to parse the XML message. The *MessageHandler*
-class receives callbacks as Python parses the message. The handler
-saves information its interested in. The External Method uses the
-handler class by creating an instance of it, and passing it to the
-*parseString* function. It then figures out a response message by
-calling *getResponse* with the message body. The *getResponse*
-script (which is not shown here) presumably scans the body for
-commands, queries the web applications state and returns some
-response. The *receiveMessage* method then creates an XML message
-using response and the sender information and returns it.
-
-The remote server would use this External Method by calling the
-*receiveMessage* method using the standard HTTP POST
-command. Voila, you've implemented a custom XML chat server that
-runs over HTTP.
-
-External Method Gotchas
-~~~~~~~~~~~~~~~~~~~~~~~
-
-While you are essentially unrestricted in what you can do in an
-External Method, there are still some things that
-are hard to do.
-
-While your Python code can do as it pleases if you want to
-work with the Zope framework you need to respect its
-rules. While programming with the Zope framework is too
-advanced a topic to cover here, there are a few things that
-you should be aware of.
-
-Problems can occur if you hand instances of your own
-classes to Zope and expect them to work like Zope
-objects. For example, you cannot define a class in your
-External Method and assign an instance of this class as an
-attribute of a Zope object. This causes problems with
-Zope's persistence machinery.  If you need to create new
-kinds of persistent objects, it's time to learn about
-writing Zope Products. Writing a Product is beyond the
-scope of this book. You can learn more by reading the
-"Zope Developers'
-Guide":http://www.zope.org/Documentation/Books/ZDG/current
-
 Advanced Acquisition 
 --------------------
 
 In the chapter entitled "Acquisition":Acquisition.html>`_ , we
 introduced acquisition by containment, which we have been using
 throughout this chapter. In acquisition by containment, Zope
-looks for an object by going back up the containment heirarchy
+looks for an object by going back up the containment hierarchy
 until it finds an object with the right id. In Chapter 7 we also
 mentioned *context acquisition*, and warned that it is a tricky
 subject capable of causing your brain to explode. If you are
 ready for exploding brains, read on.
 
-Recall our Zoo example introduced earlier in this chapter. 
+The most important thing for you to understand in this chapter is
+that context acquisition exists and can interfere with whatever
+you are doing. Today it is seen as a fragile and complex topic and
+rarely ever used in practice.
 
+Recall our Zoo example introduced earlier in this chapter.
+
 .. figure:: ../Figures/zoo.png 
 
    Zope Zoo Example hierarchy
@@ -824,7 +314,7 @@
 
 Context acquisition can make code more difficult to
 understand. A person reading your script can no longer simply
-look backwards up one containment heirarchy to see where an
+look backwards up one containment hierarchy to see where an
 acquired object might be; many more places might be searched,
 all over the zope tree folder. And the order in which objects
 are searched, though it is consistent, can be confusing.
@@ -844,7 +334,7 @@
 For example, if you write a script that calls another script by
 a long and torturous path, you are assuming that the folder tree
 is not going to change. A maintenance decision to reorganize the
-folder heirarchy could require an audit of scripts in *every*
+folder hierarchy could require an audit of scripts in *every*
 part of the site to determine whether the reorganization will
 break anything. 
 
@@ -917,7 +407,7 @@
 in your list of parameters. Request variables are detailed more
 fully in `Appendix B: API Reference <AppendixB.html>`_ .
 
-In the Python script given above, there is a subtle problem. You
+In the Script (Python) given above, there is a subtle problem. You
 are probably expecting an integer rather than a string for age,
 but all form variables are passed as strings.  You could
 manually convert the string to an integer using the Python *int*
@@ -1005,7 +495,7 @@
 These converters all work in more or less the same way to coerce
 a form variable, which is a string, into another specific
 type. You may recognize these converters from the chapter
-entitled `Using Basic Zope Objects`_ , in which we
+entitled Using Basic Zope Objects , in which we
 discussed properties. These converters are used by Zope's
 property facility to convert properties to the right type.
 
@@ -1171,8 +661,7 @@
 All scripts that can be edited through the web are subject to
 Zope's standard security policies. The only scripts that are not
 subject to these security restrictions are scripts that must be
-edited through the filesystem. These unrestricted scripts
-include *External Methods*.
+edited through the filesystem.
 
 The chapter entitled `Users and Security <Security.html>`_ covers
 security in more detail. You should consult the *Roles of
@@ -1202,14 +691,12 @@
   Scripts cannot import arbitrary
   packages and modules. You are limited to importing the
   *Products.PythonScripts.standard* utility module, the
-  *AccessControl* module, those modules available via DTML
+  *AccessControl* module, some helper modules
   (*string*, *random*, *math*, *sequence*), and modules
   which have been specifically made available to scripts
   by product authors.  See `Appendix B: API Reference`_
   for more information on these
-  modules.  If you want to be able to import any Python
-  module, use an External Method, as described in this
-  chapter.
+  modules.
 
 Access limits
   You are restricted by standard Zope
@@ -1228,10 +715,7 @@
   do so, the restriction against using objects whose names
   begin with an underscore would prevent you from using
   your class's __init__ method.  If you need to define
-  classes, use *External Methods* or *Zope Products* (see
-  the "Zope Developers
-  Guide":http://www.zope.org/Documentation/Books/ZDG for
-  more information about creating Products).  You may,
+  classes, use *packages* You may,
   however, define functions in scripts, although it is
   rarely useful or necessary to do so.  In practice, a
   Script in Zope is treated as if it were a single method
@@ -1245,37 +729,28 @@
 Despite these limits, a determined user could use large amounts
 of CPU time and memory using Python-based Scripts. So malicious
 scripts could constitute a kind of denial of service attack by
-using lots of resources. These are difficult problems to solve
-and DTML suffers from the same potential for abuse. As with
-DTML, you probably should not grant access to scripts to
+using lots of resources. These are difficult problems to solve.
+You probably should not grant access to scripts to
 untrusted people.
 
 
-DTML versus Python versus Page Templates 
-----------------------------------------
+Python versus Page Templates
+----------------------------
 
-Zope gives you many ways to script. For small scripting
-tasks the choice of Python-based Scripts, Page Templates or
-DTML probably doesn't make a big difference.  For larger,
+Zope gives you multiple ways to script. For small scripting
+tasks the choice of Python-based Scripts or Page Templates
+probably doesn't make a big difference.  For larger,
 logic-oriented tasks you should use Python-based Scripts or
-External Methods. 
+write packages on the file-system.
 
-For presentation, Python should *not* be used; the choice
-then becomes whether to use DTML or ZPT.
+For presentation, Python should *not* be used; instead you use ZPT.
 
 Just for the sake of comparison, here is a simple presentational script 
-suggested by Gisle Aas in four different languages.
+suggested by Gisle Aas in ZPT and Python.
 
-In DTML::
-
-  <dtml-in objectValues>
-    <dtml-var getId>: <dtml-var sequence-item>
-  </dtml-in>
-  done
-
 In ZPT::
 
-  <div tal:repeat="item here/objectValues" 
+  <div tal:repeat="item context/objectValues" 
        tal:replace="python:'%s: %s\n' % (item.getId(), str(item))" />
 
 In Python::
@@ -1285,10 +760,6 @@
   print "done"
   return printed
 
-Despite the fact that Zope is implemented in Python, it sometimes
-(for better or worse) follows the Perl philosophy that "there's
-more than one way to do it".
-
 Remote Scripting and Network Services
 -------------------------------------
 
@@ -1306,7 +777,7 @@
 *XML-RPC*.  XML-RPC is used to execute a procedure on a remote
 machine and get a result on the local machine.  XML-RPC is designed
 to be language neutral, and in this chapter you'll see examples in
-Python, Perl and Java.
+Python and Java.
 
 The second common way to remotely script Zope is with any HTTP
 client that can be automated with a script.  Many language
@@ -1318,8 +789,8 @@
 
 XML-RPC is a simple remote procedure call mechanism that works
 over HTTP and uses XML to encode information. XML-RPC clients
-have been implemented for many languages including Python, Perl,
-Java, JavaScript, and TCL.
+have been implemented for many languages including Python,
+Java and JavaScript.
 
 In-depth information on XML-RPC can be found at the "XML-RPC
 website":http://www.xmlrpc.org/. 
@@ -1345,19 +816,6 @@
   for employee in server.JanitorialDepartment.personnel():
       server.fireEmployee(employee)
 
-In Perl::
-
-  use Frontier::Client;
-
-  $server = Frontier::Client->new(url => "http://www.zopezoo.org/");
-
-  $employees = $server->call("JanitorialDepartment.personnel");
-  foreach $employee ( @$employees ) {
-
-    $server->call("fireEmployee",$server->string($employee));
-
-  }
-
 In Java::
 
   try {
@@ -1384,8 +842,7 @@
 XML-RPC request exactly like a normal HTTP request with respect to
 security controls. This means that you must provide authentication in
 your XML-RPC request for Zope to grant you access to protected
-scripts, eg. by using the user:password URL notation, as
-in 'http://user:password@server.domain/'
+scripts.
 
 Remote Scripting with HTTP
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1466,5 +923,4 @@
 With scripts you can control Zope objects and glue together your
 application's logic, data, and presentation. You can
 programmatically manage objects in your Zope folder hierarchy by
-using the Zope API.  You can also perform serious programming
-tasks such as image processing and XML parsing.
+using the Zope API.

Modified: zope2book/trunk/source/SearchingZCatalog.rst
===================================================================
--- zope2book/trunk/source/SearchingZCatalog.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/SearchingZCatalog.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -438,7 +438,7 @@
 Here is a report form that works with the search form::
 
   <html>
-  <body tal:define="searchResults here/NewsCatalog;">
+  <body tal:define="searchResults context/NewsCatalog;">
   <table border>
     <tr>
       <th>Item no.</th>
@@ -466,7 +466,7 @@
 examination.  The heart of the whole thing is in the definition
 of the 'searchResults' variable::
 
-  <body tal:define="searchResults here/NewsCatalog;">
+  <body tal:define="searchResults context/NewsCatalog;">
 
 This calls the 'NewsCatalog' ZCatalog.  Notice how the form
 parameters from the search form ( 'contentTextIdx' ,
@@ -528,7 +528,7 @@
 
   ...
   <ul>
-    <li tal:repeat="item here/relevantSectionNews">
+    <li tal:repeat="item context/relevantSectionNews">
       <a href="news link" tal:attributes="href item/absolute_url">
         <span tal:replace="item/title">news title</span>
       </a>
@@ -792,7 +792,7 @@
   <td>
     <select name="author:list" size="6" multiple>             
       <option 
-        tal:repeat="item python:here.NewsCatalog.uniqueValuesFor('author')" 
+        tal:repeat="item python:context.NewsCatalog.uniqueValuesFor('author')" 
         tal:content="item"
         value="opt value">
       </option>
@@ -814,7 +814,7 @@
 
     <select name="author:list" size="6" multiple>             
       <option 
-        tal:repeat="item python:here.NewsCatalog.uniqueValuesFor('author')" 
+        tal:repeat="item python:context.NewsCatalog.uniqueValuesFor('author')" 
         tal:content="item"
         value="opt value">
       </option>
@@ -883,7 +883,7 @@
 
   <select name="keywords:list" multiple>
     <option 
-      tal:repeat="item python:here.uniqueValuesFor('keywords')"
+      tal:repeat="item python:context.uniqueValuesFor('keywords')"
       tal:content="item">
         opt value goes here
     </option>
@@ -911,7 +911,7 @@
 
   <h2>Lizard Pictures</h2>
   <p tal:repeat="item
-      python:here.AnimalCatalog(pathindex='/Zoo/Lizards', 
+      python:context.AnimalCatalog(pathindex='/Zoo/Lizards', 
       meta_type='Image')">
     <a href="url" tal:attributes="href item/getURL" tal:content="item/title">
       document title
@@ -1496,13 +1496,13 @@
 it with::
 
   <html><head>
-  <title tal:content="here/title_or_id">title</title>
+  <title tal:content="context/title_or_id">title</title>
   <link rel="stylesheet" type="text/css" href="/manage_page_style.css">
   </head>
   <body bgcolor="#FFFFFF" link="#000099" vlink="#555555">
   <span 
     tal:define="manage_tabs_message options/manage_tabs_message | nothing"
-    tal:replace="structure here/manage_tabs"> 
+    tal:replace="structure context/manage_tabs"> 
     prefab management tabs 
   </span>
   <form action="manage_editNewsProps" method="get">
@@ -1512,7 +1512,7 @@
     <td>
       <textarea 
         name="content:text" rows="6" cols="35"
-        tal:content="here/content">content text</textarea>
+        tal:content="context/content">content text</textarea>
     </td>
   </tr>
   <tr>
@@ -1520,7 +1520,7 @@
     <td>
       <input name="author:string" 
              value="author string"
-             tal:attributes="value here/author">
+             tal:attributes="value context/author">
     </td>
   </tr>
   <tr>
@@ -1528,7 +1528,7 @@
     <td>
       <input name="date:date"
              value="the date"
-             tal:attributes="value here/date">
+             tal:attributes="value context/date">
     </td>
   </tr>
   <tr><td></td><td>
@@ -1591,13 +1591,13 @@
   <title tal:content="template/title">The title</title>
   </head><body>
   <h1>News Flash</h1>
-  <p tal:content="here/date">
+  <p tal:content="context/date">
     date goes here
   </p>
-  <p tal:content="here/author">
+  <p tal:content="context/author">
     author goes here
   </p>
-  <p tal:content="here/content">
+  <p tal:content="context/content">
     content goes here
   </p>
   </body></html>

Modified: zope2book/trunk/source/Security.rst
===================================================================
--- zope2book/trunk/source/Security.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/Security.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -87,17 +87,13 @@
 Identification and Authentication
 ---------------------------------
 
-When a user accesses a protected resource (for example, by
-attempting to view a "protected" DTML Method) Zope will ask the
-user to log in by presenting an authentication dialog. Once the 
-dialog has been "filled out" and submitted, Zope will look for 
-the user account represented by this set of credentials. By default 
-Zope uses HTTP basic authentication.
+When a user accesses a protected resource (for example, by attempting to view a
+"protected" Page Template) Zope will ask the user to log in by presenting an
+authentication dialog. Once the dialog has been "filled out" and submitted,
+Zope will look for the user account represented by this set of credentials. By
+default Zope uses HTTP basic authentication. A cookie-based authentication can
+be implemented by adding a CookieCrumbler to the site's base folder.
 
-A cookie-based authentication can be implemented by adding a 
-CookieCrumbler to the site's base folder. This is also useful in a 
-setup with Zope-Addons like CMF and Plone.
-
 Zope *identifies* a user by examining the username and password
 provided during the entry into the authentication dialog.  If Zope
 finds a user within one of its user databases with the username
@@ -143,8 +139,6 @@
 information as necessary until the user either "gets it right" or
 gives up.
 
-  % xx Possibility to set a maximum no. of challenges in the conf.?
-
 In general, there is no need for a user to log in to Zope if he
 only wishes to use public resources.  For example, to view the
 parts of your Zope website that are publically available, a user
@@ -178,10 +172,8 @@
 A *context* in Zope is a "place" within the Zope object hierarchy.
 In relation to security, a context is an object that has a
 location within the Zope Object Database.  For example, a
-description of a context could be expressed as "the 'Examples'
-Folder object within the Zope root object".  Another example of a
-context might be "a DTML Method object named 'show_css' within the
-Zope root folder".  In essence, a context can be thought of as an
+description of a context could be expressed as "a folder object named zoo'
+within the Zope root object". In essence, a context can be thought of as an
 object's "location" within the Zope Object Database, described by
 its "path".  Each object that exists in the Zope Object Database
 which has a web-manageable interface can be associated with its
@@ -201,7 +193,7 @@
 policy allows managers to delete objects in this folder.  If
 objects created within this folder do not override their parents'
 security policy, they acquire this policy.  So, for example, if a
-DTML Method is created within this folder, it may also be deleted
+Page Template is created within this folder, it may also be deleted
 by users with the Manager role.  Subobjects within subfolders of
 the original folder have the same policy unless they override it
 themselves, ad infinitum.
@@ -290,8 +282,7 @@
 implementation do not support additional properties like
 email addresses and phone numbers.  For support of properties
 like these, you will have to use external User products like the
-CMF Membership Component (in the `CMF <http://cmf.zope.org>`_) or
-`exUserFolder <http://exuserfolder.sourceforge.net>`_.
+CMF Membership Component (in the `CMF <http://cmf.zope.org>`_).
 
 Users can not be copied and pasted between User Folders.  The
 facility does not exist to perform this.
@@ -327,10 +318,7 @@
 
 To grant the capability for users to change their own passwords
 without being able to influence other users' information, set up
-a script with *Proxy Roles* to do the work for you.  See `msx's
-mini-how-to
-<http://www.zope.org/Members/msx/ChangeOwnPassword-mini-howto>`_
-for more information, or create a script to do so after reading
+a script with *Proxy Roles* to do the work for you after reading
 the section within this chapter entitled "Proxy Roles".
 
 In general, user folders work like normal Zope folders; you can
@@ -420,44 +408,16 @@
 Working with Alternative User Folders  
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-It may be that you don't want to manage your user account
-through the web using Zope's "stock" user folder
-implementation. Perhaps you already have a user database, or
-perhaps you want to use other tools to maintain your account
-information. Zope allows you to use alternate sources of data as
-user information repositories. You can find an ever-growing list
-of alternate user folders at the `Zope website Products
-area <http://www.zope.org/Products/user_management>`_. Some of the 
-more popular alternative user folders are available here.
+It may be that you don't want to manage your user account through the web using
+Zope's "stock" user folder implementation. Perhaps you already have a user
+database, or perhaps you want to use other tools to maintain your account
+information. Zope allows you to use alternate sources of data as user
+information repositories. The most popular user folder implementation is called
+`PluggableAuthService`_ which allows you to mix-in and combine a vast number of
+different authentication schemes and backends, like LDAP or MySQL.
 
-`PluggableAuthService <http://zope.org/Members/urbanape/PluggableAuthService>`_ 
-  This product defines a fully-pluggable user folder, intended for use in
-  all Zope sites. It defines a framework for a set of plugins which it
-  orchestrates to generate user objects from requests. 
+.. _PluggableAuthService: http://pypi.python.org/pypi/Products.PluggableAuthService
 
-`Extensible User Folder <http://exuserfolder.sourceforge.net>`_ 
-  exUserFolder allows for authentication from a choice of
-  sources and separate storage of user properties.  It has been
-  designed to be usable out of the box, and requires very little
-  work to set up.  There are authentication sources for
-  Postgresql, RADIUS and SMB and others as well as normal ZODB
-  storage.
-
-`etcUserFolder <http://www.zope.org/Products/etcUserFolder>`_ 
-  This user folder authenticates using standard Unix
-  */etc/password* style files.
-
-`LDAP User Folder <http://www.dataflake.org/software/ldapuserfolder>`_
-  This user folder allows you to authenticate from an LDAP server.
-
-`NTUserFolder <http://www.zope.org/Members/htrd/NTUserFolder>`_
-  This user folder authenticates from NT user accounts. It
-  only works if you are running Zope under Windows NT or Windows
-  2000.
-
-`MySQLUserFolder <http://www.zope.org/Members/vladap/mysqlUserFolder>`_
-  This user folder authenticates from data within a MySQL database.
-
 Some user folders provide alternate login and logout controls in
 the form of web pages, rather than relying on Basic HTTP
 Authentication controls. Despite this variety, all user folders
@@ -480,22 +440,22 @@
 Zope Anonymous User
 %%%%%%%%%%%%%%%%%%%
 
-    Zope has a built-in user account for "guests" who possess no
-    credentials.  This is the 'Anonymous' user. If you don't have
-    a user account on Zope, you'll be considered to be the
-    'Anonymous' user.
+Zope has a built-in user account for "guests" who possess no
+credentials.  This is the 'Anonymous' user. If you don't have
+a user account on Zope, you'll be considered to be the
+'Anonymous' user.
 
-    The 'Anonymous' *user* additionally possesses the 'Anonymous'
-    *role*. The "stock" Zope security policy restricts users which
-    possess the 'Anonymous' role from accessing nonpublic
-    resources. You can tailor this policy, but most of the time
-    you'll find the default anonymous security settings adequate.
+The 'Anonymous' *user* additionally possesses the 'Anonymous'
+*role*. The "stock" Zope security policy restricts users which
+possess the 'Anonymous' role from accessing nonpublic
+resources. You can tailor this policy, but most of the time
+you'll find the default anonymous security settings adequate.
 
-    As we mentioned earlier in the chapter, you must try to access
-    a protected resource in order for Zope to attempt
-    authentication.  Even if you've got a user account on the
-    system, Zope will consider you the 'Anonymous' user until you
-    been prompted for login and you've successfully logged in.
+As we mentioned earlier in the chapter, you must try to access
+a protected resource in order for Zope to attempt
+authentication.  Even if you've got a user account on the
+system, Zope will consider you the 'Anonymous' user until you
+been prompted for login and you've successfully logged in.
 
 Zope Emergency User
 %%%%%%%%%%%%%%%%%%%
@@ -668,13 +628,9 @@
 you should manage your Zope site via an SSL (Secured Sockets
 Layer) connection.  The easiest way to do this is to use Apache or
 another webserver which comes with SSL support and put it "in
-front" of Zope.  Some (minimalistic) information about setting up
-Zope behind an SSL server is available at `Unfo's member page on
-Zope.org <http://www.zope.org/Members/unfo/apache_zserver_ssl>`_, on
-`Zopelabs.com <http://www.zopelabs.com/cookbook/1028143332>`_.  The
-chapter of this book entitled `Virtual Hosting <VirtualHosting.html>`_
-also provides some background that may be helpful to set up an SSL
-server in front of Zope.
+front" of Zope. The chapter of this book entitled
+`Virtual Hosting <VirtualHosting.html>`_ provides some background that may be
+helpful to set up an SSL server in front of Zope.
 
 Managing Custom Security Policies
 ---------------------------------
@@ -765,9 +721,9 @@
 
 You should notice that roles can be used at the level at which
 they are defined and "below" in the object hierarchy.  For
-example, if you create a role in the 'Examples' folder that
+example, if you create a role in a 'myfolder' folder that
 exists in the Zope root folder, that role cannot be used outside
-of the 'Examples' folder and any of its subfolders and
+of the 'myfolder' folder and any of its subfolders and
 subobjects.  If you want to create a role that is appropriate
 for your entire site, create it in the root folder.
 
@@ -792,9 +748,9 @@
 For example, if a user creates an object using the Zope
 Management Interface, they are always given the additional local
 role of *Owner* in the context of that object. A user might not
-have the ability to edit DTML Methods in general if he does not
+have the ability to edit Page Templates in general if he does not
 possess a set of global roles which allow him to do so, but for
-DTML Methods he owns, the user may edit the DTML Method by
+Page Templates he owns, the user may edit the Page Template by
 virtue of possessing the *Owner* local role.
 
 Local roles are a fairly advanced security control. Zope's
@@ -812,17 +768,16 @@
 
 A permission defines a single action which can be taken upon a
 Zope object. Just as roles abstract users, permissions abstract
-objects. For example, many Zope objects, including DTML Methods
-and DTML Documents, can be viewed. This action is protected by
+objects. For example, many Zope objects, including Page Templates
+and Folders, can be viewed. This action is protected by
 the *View* permission.  Permissions are defined by Zope
-*Product* developers and the Zope "core" itself.  *Products* are
+developers in Python packages and the Zope "core" itself. Packages are
 responsible for creating a set of permissions which are relevant
 to the types of objects they expose.
 
-Some permissions are only relevant for one type of object, for
-example, the *Change DTML Methods* permission only protects DTML
-Methods. Other permissions protect many types of objects, such
-as the *FTP access* and *WebDAV access*  permissions which
+Some permissions are only relevant for one type of object.
+Other permissions protect many types of objects, such
+as the *FTP access* and *WebDAV access* permissions which
 control whether objects are available via FTP and WebDAV.
 
 You can find out what permissions are available on a given object
@@ -1181,28 +1136,12 @@
 For example, suppose your application allows some users to upload
 files. This action may be protected by the "Add Documents, Images,
 and Files" standard Zope permission. You can test to see if the
-current user has this permission in DTML::
+current user has this permission in a Page Template::
 
-  <dtml-if expr="_.SecurityCheckPermission(
-                'Add Documents, Images, and Files', this())">
-
-    <form action="upload">
-     ...
-    </form>
-
-  </dtml-if>
-
-The *SecurityCheckPermission* function takes two arguments, a
-permission name, and an object. In DTML we pass 'this()' as the
-object which is a reference to the "current" object.
-
-For Page Templates the syntax is a bit different, but the behavior
-is the same::
-
   <form action="upload" 
     tal:condition="python:
       modules['AccessControl'].getSecurityManager().checkPermission(
-         'Add / Documents, Images, and Files', here)">
+         'Add / Documents, Images, and Files', context)">
   ...
   </form>
 
@@ -1213,7 +1152,7 @@
 the Page template::
 
   <form action="upload"
-        tal:condition="python: here.check_security(
+        tal:condition="python: context.check_security(
            'Add Documents, Images and Files', here)">
 
 Here is the 'check_security' Python Script which is referenced
@@ -1247,28 +1186,14 @@
 documentation.
 
 Suppose you wish to display the current user name on a web page to
-personalize the page. You can do this easily in DTML::
+personalize the page. You can do this easily in Page Template::
 
-  <dtml-var expr="_.SecurityGetUser().getUserName()">
-
-You can retrieve the currently logged in user with the
-*SecurityGetUser* DTML function or the shortcut *user* in Page
-Templates.  This DTML fragment tests the current user by calling
-the *getUserName* method on the current user object. If the user
-is not logged in, you will get the name of the anonymous user,
-which is *Anonymous User*.
-
-You can do the same thing in a Page Template like this::
-
   <p tal:content="user/getUserName">username</p>
 
-The Zope security API for Scripts is explained in `Appendix B:
-API Reference <AppendixB.html>`_.  The Zope security API for DTML is
-explained in `Appendix A: DTML Reference <AppendixA.html>`_.  The Zope
-security API for Page Templates is explained in `Appendix C: Zope
-Page Templates Reference <AppendixC.html>`_.  An even better reference
-to these functions exists in the Zope help system, available by
-clicking on 'Help' from any Zope Management Interface page.
+The Zope security API for Scripts is explained in
+`Appendix B: API Reference <AppendixB.html>`_. The Zope security API for Page
+Templates is explained in
+`Appendix C: Zope Page Templates Reference <AppendixC.html>`_.
 
 Advanced Security Issues: Ownership and Executable Content
 ----------------------------------------------------------
@@ -1277,7 +1202,7 @@
 are the advanced concepts of *ownership* and *executable
 content*. Zope uses ownership to associate objects with users who
 create them, and executable content refers to objects such as
-Scripts, DTML Methods and Documents, which execute user code.
+Scripts, which execute user code.
 
 For small sites with trusted users you can safely ignore these
 advanced issues. However for large sites where you allow untrusted
@@ -1310,8 +1235,8 @@
 limiting the power of web resources based on who authored them.
 If an untrusted user authors a web page, then the power of the
 web pages to do harm to unsuspecting visitors will be
-limited. For example, suppose an untrusted user creates a DTML
-document or Python script that deletes all the pages in your
+limited. For example, suppose an untrusted user creates a
+Script (Python) that deletes all the pages in your
 site. If anyone attempt to view the page, it will fail since the
 owner of the object does not have adequate permissions. If a
 manager views the page, it will also fail, even though the
@@ -1361,13 +1286,11 @@
 Roles of Executable Content
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-DTML Documents, DTML Methods, SQL Methods, Python-based Scripts,
-and Perl-based Scripts are said to be *executable* since their
-content is generated dynamically.  Their content is also
-editable through the web.
+Python-based Scripts are said to be *executable* since their content is
+generated dynamically. Their content is also editable through the web.
 
 When you view an executable object by visiting its URL or
-calling it from DTML or a script, Zope runs the object's
+calling it from a script, Zope runs the object's
 executable content. The objects actions are restricted by the
 roles of its owner and your roles. In other words an executable
 object can only perform actions that *both* the owner and the
@@ -1401,12 +1324,12 @@
 and for good reason. You don't want just anyone to be able to
 anonymously send email with your Zope server.
 
-The problem with this arrangement is that your DTML Method that
+The problem with this arrangement is that your Script (Python) that
 sends email will fail for anonymous users. How can you get
 around this problem? The answer is to set the proxy roles on the
-DTML Method that sends email so that when it executes it has the
-"Manager" role. Visit the Proxy management tab on your DTML
-Method, as shown in the figure below.
+Script (Python) that sends email so that when it executes it has the
+"Manager" role. Visit the Proxy management tab on your Python
+script, as shown in the figure below.
 
 .. figure:: ../Figures/6-7.png
 

Modified: zope2book/trunk/source/SimpleExamples.rst
===================================================================
--- zope2book/trunk/source/SimpleExamples.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/SimpleExamples.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -4,7 +4,6 @@
 .. todo:
    
    - add new screen shots
-   - convert guest book to zpt
 
 This chapter will take you, step by step, through building a basic web
 application in Zope.  As we go through the chapter, we will examine some of
@@ -42,9 +41,6 @@
 - Provide a simple file library of various documents that describe the
   animals.
 
-- A guest book must be created so that zoo visitors can give you feedback
-  and comments about your site.
-
 Beginning with a Folder
 -----------------------
 
@@ -106,10 +102,6 @@
 Step 2: Create Site Organization
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. note:
-   
-   Do not create public interfaces for the folders in this step.
-
 1. Enter the *ZopeZoo* folder and create three subfolders with *Ids*:
    'Reptiles', 'Mammals' and 'Fish'.
 
@@ -692,239 +684,6 @@
 *modified* then the files are sorted by modification time.  Otherwise the
 files are sorted by *title*.
 
-Building a Guest Book
----------------------
-
-A guest book is a common and useful web application that allows visitors to
-your site to leave messages.  Figure [5-6] shows what the guest book you're
-going to write looks like.
-
-.. figure:: ../Figures/5-6.png
-
-   Zoo guest book
-
-Start by creating a folder called *GuestBook* in the root folder.  Give
-this folder the title 'The Zope Zoo Guest Book'.  The *GuestBook* folder
-will hold the guest book entries and methods to view and add entries. The
-folder will hold everything the guest book needs. After the guest book is
-done you will be able to copy and paste it elsewhere in your site to create
-new guest books.
-
-You can use Zope to create a guest book several ways, but for this example,
-you'll use one of the simplest.  The *GuestBook* folder will hold a bunch
-of Files, one file for each guest book entry.  When a new entry is added to
-the guest book, a new file is created in the *GuestBook* folder.  To delete
-an unwanted entry, just go into the *GuestBook* folder and delete the
-unwanted file using the management interface.
-
-Let's create a method that displays all of the entries.  Call this method
-*index_html* so that it is the default view of the *GuestBook* folder::
-
-  <dtml-var standard_html_header>
-
-  <h2><dtml-var title_or_id></h2>
-
-  <!-- Provide a link to add a new entry, this link goes to the
-  addEntryForm method -->
-
-  <p>
-    <a href="addEntryForm">Sign the guest book</a>
-  </p>
-
-  <!-- Iterate over each File in the folder starting with
-  the newest documents first. -->
-
-  <dtml-in expr="objectValues('File')"
-           sort="bobobase_modification_time" reverse>
-
-  <!-- Display the date, author and contents of each file -->
-
-    <p>
-    <b>On <dtml-var bobobase_modification_time fmt="aCommon">, 
-       <dtml-var guest_name html_quote null="Anonymous"> said:</b><br>
-
-    <dtml-var sequence-item html_quote newline_to_br>
-
-    <!-- Make sure we use html_quote so the users can't sneak any
-    HTML onto our page -->
-
-  </p>
-
-  </dtml-in>
-
-  <dtml-var standard_html_footer>
-
-This method loops over all the files in the folder and displays each one.
-Notice that this method assumes that each file will have a *guest_name*
-property. If that property doesn't exist or is empty, then Zope will use
-*Anonymous* as the guest name. When you create a entry file you'll have to
-make sure to set this property.
-
-Next, let's create a form that your site visitors will use to add new guest
-book entries. In the *index_html* method above we already created a link to
-this form. In your *GuestBook* folder create a new DTML Method named
-*addEntryForm*::
-
-  <dtml-var standard_html_header>
-
-  <p>Type in your name and your comments and we'll add it to the
-  guest book.</p>
-
-  <form action="addEntryAction" method="POST">
-  <p> Your name: 
-    <input type="text" name="guest_name" value="Anonymous">
-  </p>
-  <p> Your comments: <br>
-    <textarea name="comments" rows="10" cols="60"></textarea>
-  </p>
-
-  <p>
-    <input type="submit" value="Send Comments">
-  </p>  
-  </form>
-
-  <dtml-var standard_html_footer>
-
-Now when you click on the *Sign Guest Book* link on the guest book page
-you'll see a form allowing you to type in your comments.  This form
-collects the user's name and comments and submits this information to a
-method named *addEntryAction*.
-
-Now create an *addEntryAction* DTML Method in the *GuestBook* folder to
-handle the form. This form will create a new entry document and return a
-confirmation message::
-
-  <dtml-var standard_html_header>
-
-  <dtml-call expr="addEntry(guest_name, comments)">
-
-  <h1>Thanks for signing our guest book!</h1>
-
-  <p><a href="<dtml-var URL1>">Return</a>
-  to the guest book.</p>
-
-  <dtml-var standard_html_footer>
-
-.. TODO:
-   
-   show how to send the form data straight to the form and then return
-   to the guestbook page with the validated entry
-
-This method creates a new entry by calling the *addEntry* method and
-returns a message letting the user know that their entry has been added.
-
-The last remaining piece of the puzzle is to write the script that will
-create a file and sets its contents and properties. We'll do this in Python
-since it is much clearer than doing it in DTML. Create a Python-based
-Script in the *GuestBook* folder called *addEntry* with parameters
-*guest_name* and *comments*::
-
-  ## Script (Python) "addEntry"
-  ##parameters=guest_name, comments
-  ##
-  """
-  Create a guest book entry.
-  """
-  # create a unique file id
-  id='entry_%d' % len(context.objectIds())
-
-  # create the file
-  context.manage_addProduct['OFSP'].manage_addFile(id,
-                                           title="", file=comments)
-
-  # add a guest_name string property
-  doc=getattr(context, id)
-  doc.manage_addProperty('guest_name', guest_name, 'string')
-
-This script uses Zope API calls to create a File and to create a property
-on it. This script performs the same sort of actions in a script that you
-could do manually; it creates a file, edits it and sets a property.
-
-.. TODO:
-   
-   also explain objectIds, OFSP
-
-The guest book is now almost finished. To use the simple guest book, just
-visit 'http://localhost:8080/ZopeZoo/GuestBook/'.
-
-One final thing is needed to make the guest book complete. More than likely
-your security policy will not allow anonymous site visitors to create
-files. However the guest book application should be able to be used by
-anonymous visitors. In Chapter 7, User and Security, we'll explore this
-scenario more fully. The solution is to grant special permission to the
-*addEntry* method to allow it to do its work of creating a file. You can do
-this by setting the *Proxy role* of the script to *Manager*. This means
-that when the script runs it will work as though it was run by a manager
-regardless of who is actually running the method. To change the proxy roles
-go to the *Proxy* view of the *addEntry* script, as shown in [5-7].
-
-.. figure:: ../Figures/5-7.png
-
-   Setting proxy roles for the *addEntry* script
-
-Now select *Manager* from the list of proxy roles and click *Change*.
-
-Congratulations, you've just completed a functional web application. The
-guest book is complete and can be copied to different sites if you want.
-
-Extending the Guest Book to Generate XML
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-All Zope objects can create XML. It's fairly easy to create XML with DTML.
-XML is just a way of describing information. The power of XML is that it
-lets you easily exchange information across the network. Here's a simple
-way that you could represent your guest book in XML::
-
-  <?xml version="1.0"?>
-  <guestbook>
-    <entry>
-      <author>Tom</author>
-      <comments>My comments</comments>
-    </entry>
-    <entry>
-      <author>Anonymous</author>
-      <comments>I like your web page</comments>
-    </entry>
-    <entry>
-      <author>Laura</author>
-      <comments>Please no blink tags</comments>
-    </entry>
-  </guestbook>
-
-This XML document may not be that complex but it's easy to generate. Create
-a DTML Method named "entries.xml" in your guest book folder with the
-following contents::
-
-  <?xml version="1.0"?>
-  <guestbook>
-    <dtml-in expr="objectValues('File')">
-    <entry>
-      <author><dtml-var guest_name null="Anonymous"></author>
-      <comments><dtml-var sequence-item html_quote></comments>
-    </entry>
-    </dtml-in>
-  </guestbook>
-
-As you can see, DTML is equally adept at creating XML as it is at creating
-HTML. Simply embed DTML tags among XML tags and you're set. The only tricky
-thing that you may wish to do is to set the content-type of the response to
-*text/xml*, which can be done with this DTML code::
-
-  <dtml-call expr="RESPONSE.setHeader('content-type', 'text/xml')">
-
-The whole point of generating XML is producing data in a format that can be
-understood by other systems. Therefore you will probably want to create XML
-in an existing format understood by the systems you want to communicate
-with.  In the case of the guest book a reasonable format may be the RSS
-(Rich Site Summary) XML format. RSS is a format developed by Netscape for
-its *my.netscape.com* site, which has since gained popularity among other
-web logs and news sites.  The Zope.org website uses DTML to build a dynamic
-RSS document.
-
-Congratulations! You've XML-enabled your guest book in just a couple
-minutes. Pat yourself on the back. If you want extra credit, research RSS
-enough to figure out how to change *entries.xml* to generate RSS.
-
 Building "Instance-Space" Applications
 --------------------------------------
 
@@ -956,28 +715,28 @@
 they are executed.
 
 Instance-space applications are typically created from common Zope objects.
-Script (Python) objects, Folders, DTML Methods, Page Templates, and other
-Zope services can be glued together to build simple applications.
+Script (Python) objects, Folders, Page Templates, and other Zope services can
+be glued together to build simple applications.
 
-Instance-Space Applications vs. Products
-----------------------------------------
+Instance-Space Applications vs. Python packages
+-----------------------------------------------
 
 In contrast to building applications in instance space, you may also build
-applications in Zope by building them as *Products*.  Building an
-application as a Product differs from creating applications in instance
-space inasmuch as the act of creating a Product typically allows you to
-*extend* Zope with new "addable" objects that appear in Zope's "Add" list.
-Building a Product also typically allows you to more easily distribute an
+applications in Zope by building them as Python packages.  Building an
+application as a package differs from creating applications in instance
+space inasmuch as the act of creating a package typically is more familiar to
+developers and does not constrain them in any way.
+
+Building a package also typically allows you to more easily distribute an
 application to other people, and allows you to build objects that may more
 closely resemble your "problem space".  We explore one way to create
-Products in the chapter entitled <Extending Zope
-<CustomZopeObjects.html>`_.
+packages in the chapter entitled <Extending Zope <CustomZopeObjects.html>`_.
 
-Building a Product is typically more complicated than building an
+Building a package is typically more complicated than building an
 "instance-space" application, so we get started here by describing how to
 build instance-space applications.  When you find that it becomes difficult
 to maintain, extend, or distribute an instance-space application you've
-written, it's probably time to reconsider rewriting it as a Product.
+written, it's probably time to reconsider rewriting it as a package.
 
 The Next Step
 -------------

Modified: zope2book/trunk/source/UsingZope.rst
===================================================================
--- zope2book/trunk/source/UsingZope.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/UsingZope.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -5,14 +5,14 @@
 ------------
 
 When you log in to Zope, you are presented with the Zope Management
-Interface (ZMI).  The ZMI is a management and development environment that
-allows you to control Zope, manipulate Zope objects, and develop web
+Interface (ZMI).  The ZMI is a management and configuration environment that
+allows you to control Zope, manipulate Zope objects, and configure web
 applications.
 
 The Zope Management Interface represents a view into the Zope *object
 hierarchy*.  Almost every link or button in the ZMI represents an action
 that is taken against an *object*.  When you build web applications with
-Zope, you typically spend most of your time creating and managing objects.
+Zope, you typically spend some of your time creating and managing objects.
 
 Don't be frightened if you don't understand the word "object" just yet.
 For the purposes of this chapter, the definition of an "object" is *any
@@ -140,10 +140,6 @@
   logging out using this method, try closing and reopening your browser to
   log out.
 
-- *Quick Start Links*: Selecting this menu item presents the
-  "QuickStart" page, which contains links to Zope documentation and
-  community resources.
-
 .. figure:: ../Figures/statusframe.jpg
  
    The Status Frame
@@ -267,10 +263,8 @@
 the root folder. These objects include *Control_Panel*,
 *browser_id_manager*, and *temp_folder*.  These objects are necessary for
 Zope's operation.  It is possible to delete other root objects, such as
-*index_html*, *session_data_manager*, *standard_html_header*,
-*standard_html_footer*, *standard_error_message*, and
-*standard_template.pt*, but it is not recommended to do so unless you have
-a very good reason.
+*index_html*, *session_data_manager* and *standard_error_message*,
+but it is not recommended to do so unless you have a very good reason.
 
 Transactions and Undoing Mistakes
 ---------------------------------
@@ -291,7 +285,7 @@
 transaction describes all of the changes that happen in the course of
 performing a web request.
 
-Any action in Zope that causes a transaction can be undone via the *Undo*
+Most actions in Zope that causes a transaction can be undone via the *Undo*
 tab.  You can recover from mistakes by undoing the transaction that
 represents the mistake.  This includes undo actions themselves, which can
 also be undone to restore an object to its state before the undo action.
@@ -349,165 +343,7 @@
 The Undo tab will provide you with enough information to know that a change
 has occurred.  However, it will not tell you much about the effect of the
 transaction on the objects that were changed during the transaction.
-"Presentation" and "logic" objects, like DTML Methods, DTML Documents, Zope
-Page Templates, and Script (Python) objects, support *History* for this
-purpose.  If you know a transaction has affected one of these objects, you
-can go to that object's *History* view and look at the previous states of
-the object, as shown in the figure below.
 
-.. figure:: ../Figures/history.png
-
-   The History View
-
-The *History* view of an object supports the comparison of revisions,
-allowing you to track their changes over time.  You may select two
-revisions from an object's History and compare them to one another.  To
-perform a comparison between two object revisions, select two revisions
-using the checkboxes next to the transaction identifiers, and click the
-*Compare* button.
-
-The resulting comparison format is often called a *diff*, as it emphasizes
-the differences in content between the versions.  The diff format shows you
-the lines that have been added to the new document (via a plus), which
-lines have been subtracted from the old document (via a minus), and which
-lines have been replaced or changed (via an exclamation point).
-
-.. figure:: ../Figures/histcompare.png
-
-   Comparing Revisions Via The History View
-
-To revert to an older object revision, click the checkbox next to the
-transaction identifier, then click the *Copy to present* button.
-
-Importing and Exporting Objects
--------------------------------
-
-You can move objects from one Zope system to another using *export* and
-*import*.  You can export all types of Zope objects, with the possible
-exception of External Method objects, to an *export file*.  This file can
-then be imported into any other Zope system.
-
-You can think of exporting an object as cloning a piece of your Zope system
-into a separate file, which you can then move between machines.  You can
-take this file and graft the clone onto any other Zope server.
-
-Suppose you have a folder for home work that you want to export from your
-school's Zope server, and take it home with you to work on in your home
-Zope server.  You'd create a folder in your root folder called "homeWork".
-After creating the folder, you'd click the checkbox next to the *homeWork*
-folder you'd just created, and then click the *Import/Export* button. You
-would then be working in the Import/Export folder view, as shown in the
-figure below.
-
-.. figure:: ../Figures/export.jpg
-
-   Exporting homeWork.zexp
-
-There are two sections to this screen: the upper half is the *export*
-section, and the lower half is the *import* section.  To export an object
-from this screen, type the id of the object into the first form element,
-*Export object id*. In our case, Zope has already filled this field in for
-us, since we had selected the *homeWork* folder on the last screen.
-
-The next form option lets you choose between downloading the export file to
-your computer or leaving it on the server. If you select *Download to local
-machine*, and click the *Export* button, your web browser will prompt you
-to download the export file.  If you select *Save to file on server*, then
-Zope will save the file on the same machine on which Zope is running, and
-you must fetch the file from that location yourself. The export file will
-be written to Zope's *var* directory on its server's file system. By
-default, export files use the file extension *.zexp*.
-
-In general, it's easier to download the export file to your local machine.
-It may be more convenient to save the file to the server instead if you are
-on a slow connection and the export file is very large, or if you are just
-trying to move the exported object to another Zope instance on the same
-server.
-
-The final export form element is the *XML format?* checkbox.  This option
-exports the object in the *eXtensible Markup Language* (XML) format, as
-opposed to exporting the file in Zope's default binary format.  XML format
-exports are much larger but are (mostly) human-readable.  Currently, the
-only tool that understands this XML format is Zope itself, but the future
-may bring along other tools that can understand Zope's XML format.  In
-general, you should leave this box unchecked, unless you're curious about
-what the XML export format looks like and want to examine it by hand.
-
-While you're viewing the export form for *homeWork*, ensure that "download
-to local machine" is selected, "XML format?" is *not* selected, and then
-click the *Export* button.  Your browser will present a file save dialog.
-Save the file, which will be named named *homeWork.zexp*, to a temporary
-location on your local computer.
-
-Suppose that you've later gone home and wanted to import the file into your
-home Zope server.  First, you would copy the exported file into Zope's
-*import* directory on your Zope server's file system, and then import the
-file via the ZMI into your home Zope instance.  Here is an example of a
-Zope import: we are copying the *homeWork.zexp* file, which is in a
-directory named '/tmp' on the local computer, to a remote ("home") computer
-running Zope using the *scp* facility in Linux.  We copy the *.zexp* file
-into our Zope directory's 'import' directory.  In this example, the Zope
-installation directory on the remote computer is named
-'/home/chrism/sandboxes/ZBExample'::
-
-  chrism at saints:/tmp$ ls -al homeWork.zexp 
-  -rw-r--r--    1 chrism   chrism        182 Jul 13 15:44 homeWork.zexp
-  chrism at saints:/tmp$ scp homeWork.zexp saints.homeunix.com:/home/chrism/sandboxes/ZBExample/import
-  chrism at saints.homeunix.com's password: 
-  homeWork.zexp        100% |*****************************|   182       00:00    
-  chrism at saints:/tmp$ 
-
-In the above example, the export file 'homeWork.zexp' was copied from the
-local computer's '/tmp' directory to the remote computer's
-'/home/chrism/sandboxes/ZBExample/import/' directory.  Your local directory
-and your Zope's installation directory will be different.  For the purpose
-of this example, you'd copy the export file you downloaded to your Zope
-installation's "import" directory using whatever facility you're most
-comfortable with (you needn't use scp).
-
-Now, go back to your Zope's ZMI.  Create a Folder named 'import_example'.
-Visit the newly-created 'import_example' folder by clicking on it in the
-ZMI.  Then click the *Import/Export* button from within the
-'import_example' folder, and scroll to the bottom of the Workspace frame.
-Note that Zope gives you the option to either *Take ownership of imported
-objects* or *Retain existing ownership information*.  Ownership will be
-discussed more in the chapter entitled "Users and Security". For now, just
-leave the *Take ownership of imported objects* option selected, enter the
-name of the export file ('homeWork.zexp') in the *Import file name* field,
-and click *Import*.
-
-.. figure:: ../Figures/import.jpg
-
-   Importing homeWork.zexp
-
-You now have a new object in the 'import_example' folder named 'homeWork'.
-Note that Zope informs you of the success of the import operation with a
-status message.
-
-.. figure:: ../Figures/importsuccess.jpg
-
-   Success Importing homeWork.zexp
-
-There are a few caveats to importing and exporting: in order to perform a
-successful import of a Zope export file, you need to ensure that both the
-importing and exporting Zope instances have the same *Products* installed.
-If an import fails, it's likely that you don't have the same Products
-installed in your importing Zope as the Products installed in the Zope from
-whence the export file came.  Our example above works because we are
-exporting a Folder object, which is a common, core object type for all
-Zopes. If you have trouble importing any given exported Zope file, check
-with the distributor of the exported file to see what Products are
-necessary for proper import.
-
-Note that you cannot import an object into a folder that has an existing
-object with the same 'id' as an exported file.  Therefore, when you import
-an export file, you need to ensure that it does not want to install an
-object that has the same name as an existing object in the folder in which
-you wish to import it.  In our example above, in order to bring your
-homework back to school, you'd either need to import it into a folder that
-doesn't already have an existing *homeWork* folder in it, or you'd need to
-delete the existing *homeWork* folder before importing the new one.
-
 Using Object Properties
 -----------------------
 
@@ -577,58 +413,8 @@
 
 Properties are very useful tools for tagging your Zope objects with bits of
 metadata.  Properties are supported by most Zope objects and are often
-referenced by "dynamic" Zope objects, such as "scripts" and "methods"
-(which we have not yet discussed) for purposes of data display.
+referenced by your application logic for purposes of data display.
 
-Using the Help System
----------------------
-
-Zope has a built-in help system: every management screen has a help button
-in its upper right-hand corner.  This button launches another browser
-window that exposes the Zope Help System.
-
-To see the help system, go to the root folder and click the *Help* link in
-upper right-hand corner of the Workspace frame.
-
-.. figure:: ../Figures/2-7.png
-
-   The Help System
-
-The help system has an organization similar to the two primary panes of the
-Zope management interface: it has one frame for navigation, and one frame
-for displaying the contents of the help system related to the current
-management screen.
-
-Browsing and Searching Help 
----------------------------
-
-Normally you would use the help system to get help on a specific topic.
-However, if you are curious, you can browse through its content.
-
-The help system lets you browse all of the help topics in the *Contents*
-tab of the left-hand help frame, in which you can expand and collapse help
-topics. To view a help topic in the right frame, click on its name in the
-left frame.  By default, no topics are expanded.
-
-Most help pertaining to Zope itself is located in the *Zope Help* folder.
-Click on the "plus" symbol next to the words *Zope Help* in the *Contents*
-tab of the left frame.  The frame will expand to show help topics
-(currently, in an apparently random and somewhat unhelpful order) and
-additional, related help categories, including *API Reference*, *DTML
-Reference*, and *ZPT Reference*. These subcategories contain help on
-scripting Zope, which is explained further in the chapters named "Dynamic
-Content With DTML":DTML.stx, "Using Zope Page Templates":ZPT.stx, and
-"Advanced Zope Scripting":ScriptingZope.stx.
-
-When you install third-party Zope components, they may also include their
-own help content. Each installed component has its own help folder.
-
-You may search for content in the help system by clicking on the Search tab
-in the left frame, and entering one or more search terms. For example, to
-find all of the help topics that mention folder objects, type "folder" into
-the search field and click "Search".  This will return a number of help
-topic links, most of which should pertain to the word "folder".
-
 Logging Out
 -----------
 

Modified: zope2book/trunk/source/ZPT.rst
===================================================================
--- zope2book/trunk/source/ZPT.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/ZPT.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -33,35 +33,6 @@
 A Page Template is like a model of the pages that it will generate.  In
 particular, it is parseable by most HTML tools.
 
-Zope Page Templates versus DTML
--------------------------------
-
-*Page Templates* use the *Template Attribute Language* (*TAL*), while
-*DTML Methods*, *DTML Documents* and *SQL Methods* use the *Document
-Template Markup Language* (*DTML*).  You may wonder why Zope needs two
-different template languages.
-
-First of all, there are historical reasons.  *Page Templates* are a
-relative new technology.  Zope 2.5 was the first release that shipped with
-*Page Templates*.  There are still many products and howtos that use
-*DTML* for tasks *Page Templates* are designed for.  And some people still
-prefer working with *DTML*.
-
-Secondly, *DTML* and *Page Templates* have different strengths and
-weaknesses.  *Page Templates* are aimed at HTML designers.  Once an HTML
-page has been "dynamicized" by inserting *DTML* into it, the resulting
-page typically becomes un-parseable for HTML tools, making it difficult to
-work with outside Zope.  *Page Templates* also enforce separation of
-presentation, logic and content (data).  This increases the scalability of
-content management and website development efforts that use these systems.
-And *Page Templates* give you better control over name lookups, while
-*DTML*'s namespace model adds too much "magic".
-
-But *DTML* has its strengths if we are dealing with something else than
-HTML/XML presentation, such as dynamically generated email messages and
-SQL queries.  So *DTML* is not a "dead end" and for some advanced tasks
-you might want to learn *DTML*, too.
-
 HTML Page Templates
 -------------------
 
@@ -149,19 +120,12 @@
 Creating a Page Template
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
-If you design pages, you will probably use FTP or WebDAV instead of the
-Zope Management Interface (ZMI) to edit *Page Templates*.  See "Remote
-Editing With FTP and WebDAV" in the `Advanced Page Templates`_ chapter for
-information on editing *Page Templates* remotely.  For the small
-examples in this chapter, it is easier to use the ZMI.
+Use your web browser to log into the Zope Management Interface as a manager.
+Create a *Folder* to work in named 'template_test' in the root of your Zope.
+Visit this folder and choose *Page Template* from Zope's add list. Type
+'simple_page' in the add form's *Id* field, then push the *Add and Edit*
+button.
 
-Use your web browser to log into the Zope Management Interface as a
-manager.  Create a *Folder* to work in named 'template_test' in the root
-of your Zope.  Visit this folder and choose *Page Template* from Zope's
-add list (do *NOT* choose DTML Method or DTML Document, the following
-examples only work inside a Page Template).  Type 'simple_page' in the
-add form's *Id* field, then push the *Add and Edit* button.
-
 You should now see the main editing page for the new *Page Template*.
 The title is blank and the default template text is in the editing area.
 
@@ -180,10 +144,7 @@
 confirming that your changes have been saved.
 
 If you get an error message, check to make sure you typed the example
-correctly and save it again.  Using an external editor, an HTML comment
-starting with *Page Template Diagnostics* is added to the template text
-to show you something went wrong.  You don't need to erase the error
-comment; once the error is corrected it will go away.
+correctly and save it again.
 
 Click on the *Test* tab.  You should see a page with "This is **a Simple
 Page**." at the top.  Notice that the title is bold.  This is because
@@ -268,15 +229,13 @@
 
 Let's try to rewrite it using a *Python expression*::
 
-  <h1 tal:content="python: context.getProperty('title')">Sample Page
-   Title</h1>
+  <h1 tal:content="python: context.title">Sample Page Title</h1>
 
-While *path expressions* are the default, we need a prefix to indicate
-other expression types.  This expression with the prefix 'python:'
-does (at least here) the same as the *path expression* above, but we
-have to know that 'title' is a property of the context object and how
-to access properties.  *Path expressions* try different ways to access
-'title', so in general they are more flexible, but less explicit.
+While *path expressions* are the default, we need a prefix to indicate other
+expression types. This expression with the prefix 'python:' does (at least
+here) the same as the *path expression* above. *Path expressions* try different
+ways to access 'title', so in general they are more flexible, but less
+explicit.
 
 There are some simple things you can't do with *path expressions*.
 The most common are comparing values like in::
@@ -504,13 +463,13 @@
 Edit the table cell in the meta-type column of the above example to
 look like this::
 
-  <td><img src="/misc_/OFSP/File_icon.gif"
+  <td><img src="file_icon.gif"
            tal:attributes="src item/icon" />
     <span tal:replace="item/meta_type">Meta-Type</span></td>
 
 The 'tal:attributes' statement replaces the 'src' attribute of the
 'img' tag with the value of 'item/icon'.  The 'src` attribute in the
-template (whose value is "/misc\_/OFSP/File_icon.gif") acts as a placeholder.
+template (whose value is "file_icon.gif") acts as a placeholder.
 
 Notice that we've replaced the 'tal:content' attribute on the table
 cell with a 'tal:replace' statement on a 'span' tag.  This change
@@ -562,12 +521,7 @@
 When you're using the Zope management interface to edit *Page Templates*
 it's easy to spot these diagnostic messages, because they are shown in the
 "Errors" header of the management interface page when you save the *Page
-Template*.  However, if you're using WebDAV or FTP it's easy to miss these
-messages.  For example, if you save a template to Zope with FTP, you won't
-get an FTP error telling you about the problem.  In fact, you'll have to
-reload the template from Zope to see the diagnostic message.  When using
-FTP and WebDAV it's a good idea to reload templates after you edit them to
-make sure that they don't contain diagnostic messages.
+Template*.
 
 If you don't notice the diagnostic message and try to render a template
 with problems you'll see a message like this::
@@ -697,7 +651,7 @@
 In this case the path expression returns a macro defined dynamically by
 the 'getMacro' script.  Using *Python expressions* to locate macros lets
 you dynamically vary which macro your template uses.  An example
-of the body of a "getMacro" Python script is as follows::
+of the body of a "getMacro" Script (Python) is as follows::
 
   return container.ptMacros.macros['amacroname']
 
@@ -734,12 +688,7 @@
 
 If you check the *Expand macros when editing* option on the *Page
 Template* *Edit* view, then any macros that you use will be expanded in
-your template's source.  When you're editing in the ZMI, rather than
-using a WYSIWYG editing tool, it's more convenient not to expand macros
-when editing.  This is the default for newly created templates.  When
-using WYSIWYG tools, however, it is often desirable to have the macros
-expanded so you are editing a complete page.  In this case, check the
-*Expand macros...* checkbox before editing the page.
+your template's source.
 
 Using Slots
 ~~~~~~~~~~~
@@ -945,35 +894,6 @@
 add a sidebar on the left and the press release template would
 automatically use these new presentation elements.
 
-This is a much more flexible solution to control page look and feel then
-the DTML 'standard_html_header' and 'standard_html_footer' solution.  In
-fact, Zope comes with a stock page template in the root folder named
-'standard_template.pt' that includes a whole page macro with a 'head'
-and 'body' slot.  Here's how you might use this macro in a template::
-
-  <html metal:use-macro="context/standard_template.pt/macros/page">
-    <div metal:fill-slot="body">
-      <h1 tal:content="context/title">Title</h1>
-      <p tal:content="context/getBody">Body text goes here</p>
-    </div>
-  </html>
-
-Using the 'standard_template.pt' macro is very similar to using other
-whole page macros.  The only subtlety worth pointing out is the path
-used to locate the macro.  In this example the path begins with
-'context'.  This means that Zope will search for the
-'standard_template.pt' object using acquisition starting at the object
-that the template is applied to.  This allows you to customize the look
-and feel of templates by creating custom 'standard_template.pt' objects
-in various locations.  You can choose to start the path to the macro
-with *root* or with *container*, as well as with *context*.  If the path
-begins with *root* then you will always get the standard template which
-is located in the root folder.  If the path begins with *container* then
-Zope will search for a standard template using acquisition starting in
-the folder where the template is defined.  This allows you to customize
-look and feel of templates, but does not allow you to customize the look
-and feel of different objects based on their location in the site.
-
 Using Templates with Content
 ----------------------------
 
@@ -981,18 +901,13 @@
 *Page Templates* are presentation components and they can be used to
 display content components.
 
-Zope ships with several content components: ZSQL Methods, Files, and
-Images.  DTML Documents and methods are not really pure content components
-since they can hold content and execute DTML code.  You can use Files for
-textual content since you can edit the contents of Files if the file is
-less than 64K and contains text.  However, the File object is fairly basic
-and may not provide all of the features or metadata that you need.
+Zope ships with several content components: ZSQL Methods, Files, and Images.
+You can use Files for textual content since you can edit the contents of Files
+if the file is less than 64K and contains text. However, the File object is
+fairly basic and may not provide all of the features or metadata that you need.
 
 Zope's `Content Management Framework <http://cmf.zope.org>`_ (CMF) solves
 this problem by providing an assortment of rich content components.  The
 CMF is Zope's content management add on.  It introduces all kinds of
 enhancements including workflow, skins and content objects.  The CMF makes
-a lot of use of *Page Templates*.  A later release of Zope will probably
-include technologies `from and inspired by
-<http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/FrontPage>`_
-the CMF.
+a lot of use of *Page Templates*.

Modified: zope2book/trunk/source/ZopeArchitecture.rst
===================================================================
--- zope2book/trunk/source/ZopeArchitecture.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/ZopeArchitecture.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -19,9 +19,8 @@
 provides to build web applications more quickly than other
 languages or frameworks, and to write web
 application logic in the `Python <http://www.python.org/>`_
-language.  Zope also comes with two solutions that allow you 
-to "template" text, XML, and HTML: the *Document Template Markup 
-Language* (DTML), and *Zope Page Templates* (ZPT).
+language.  Zope also comes with one solution that allow you 
+to "template" text, XML, and HTML: *Zope Page Templates* (ZPT).
 
 Object Orientation
 ------------------
@@ -165,7 +164,7 @@
 managers can use "SQL Method" objects without being able to change them or
 even view their source. You can also set restrictions so that a
 user can only create certain kinds of objects, for instance,
-"Folders" and "DTML Documents," but not "SQL Methods" or other
+"Folders" and "Page Templates," but not "SQL Methods" or other
 objects.
 
 Zope provides the capability to manage users through the web via

Modified: zope2book/trunk/source/ZopeServices.rst
===================================================================
--- zope2book/trunk/source/ZopeServices.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/ZopeServices.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -56,14 +56,16 @@
 has changed, denoting that it is now the access rule for this
 Folder.
 
-Create a DTML Method named 'test' in the accessrule_test folder
-with the following body::
+Create a page template named 'test' in the accessrule_test folder
+with the following text::
 
-  <dtml-var standard_html_header>
-  <dtml-var REQUEST>
-  <dtml-var standard_html_footer>
+  <html>
+  <body>
+    <pre tal:content="context/REQUEST">request details</pre>
+  </body>
+  </html>
 
-Save the 'test' DTML Method and click its "View" tab.  You will
+Save the 'test' page template and click its "View" tab.  You will
 see a representation of all the variables that exist in the
 REQUEST.  Note that in the **other** category, there is now a
 variable named "OS" with (depending on your browser platform)
@@ -79,25 +81,6 @@
 listed in the request because we've turned off the Access Rule
 capability for 'access_rule'.
 
-Access Rules have many potential creative uses.  For example:
-
-- A ZopeLabs recipe submitted by `xzc
-  <http://www.zopelabs.com/cookbook/997210090>`_ shows how to
-  restrict a specific user agent from accessing a particular Zope
-  object.
-  
-- Another tip from `runyaga
-  <http://www.zopelabs.com/cookbook/1017462630>`_ shows how to
-  use an access rule to restrict management access in a
-  `CMF <http://cmf.zope.org>`_ site for non-manager users.
-  
-- Another recipe by `ivo <http://www.zopelabs.com/cookbook/1003844578>`_
-  tells us how to transparently delegate requests for an object to another
-  object using an Access Rule.
-
-Access Rules don't need to be Script (Python) objects, they may
-also be DTML Methods or External Methods.
-
 Temporary Storage Services
 --------------------------
 
@@ -126,168 +109,19 @@
 objects because your computer can potentially run out of RAM as
 a result.
 
-Version Services
-----------------
-
-Version objects help coordinate the work of many people on the
-same set of objects.  While you are editing a document, someone
-else can be editing another document at the same time. In a large
-Zope site hundreds or even thousands of people can be using Zope
-simultaneously. For the most part this works well, but problems
-can occur. For example, two people might edit the same document at
-the same time. When the first person finishes their changes they
-are saved in Zope. When the second person finishes their changes
-they over write the first person's changes. You can always work
-around this problem using *Undo* and *History*, but it can still
-be a problem.  To solve this problem, Zope has *Version* objects.
-
-.. warning::
-
-   Aside from the ZCatalog incompatibility noted in the
-   caveat below, Versions have had some serious bugs through their
-   history, including some bugs that lead to ZODB corruption and data
-   loss.  Some of these may be fixed now, but many zope users 
-   have long avoided Versions like the plague. There are other
-   solutions to the same issues, from the simple and kludgey (copy stuff
-   to a private folder and work on it there) to the sophisticated
-   (ZopeVersionControl, available from cvs.zope.org).
-
-Another problem that you may encounter is that you may wish to make
-some changes, but you may not want to make them public until you are
-done. For example, suppose you want to change the menu structure of
-your site. You don't want to work on these changes while folks are
-using your site because it may break the navigation system temporarily
-while you're working.
-
-Versions are a way of making private changes in Zope. You can make
-changes to many different documents without other people seeing
-them. When you decide that you are done you can choose to make
-your changes public, or discard them. You can work in a Version
-for as long as you wish. For example it may take you a week to put
-the finishing touches on your new menu system. Once you're done
-you can make all your changes live at once by committing the
-version.
-
-.. note::
-   Using versions via the Zope Management Interface requires
-   that your browser supports and accepts cookies from the Zope
-   server.
-
-Create a Version by choosing Version from the product add
-list. You should be taken to an add form.  Give your Version an id
-of *MyChanges* and click the *Add* button. Now you have created a
-version, but you are not yet using it. To use your version click
-on it. You should be taken to the *Join/Leave* view of your
-version as shown in the figure below.
-
-.. figure:: ../Figures/3-8.png
-
-   Joining a Version
-
-The Version is telling you that you are not currently using it. Click
-on the *Start Working in MyChanges* button. Now Zope should tell you
-that you are working in a version. Now return to the root
-folder. Notice that everywhere you go you see a small message at the
-top of the screen that says *You are currently working in version
-/MyChanges*. This message lets you know that any changes you make at
-this point will not be public, but will be stored in your version. For
-example, create a new DTML Document named *new*. Notice how it has a
-small red diamond after its id. Now edit your *standard_html_header*
-method. Add a line to it like so::
-
-  <HTML>
-    <HEAD>
-      <TITLE><dtml-var title_or_id></TITLE>
-    </HEAD>
-    <BODY BGCOLOR="#FFFFFF">
-    <H1>Changed in a Version</H1>
-
-Any object that you create or edit while working in a version will
-be marked with a red diamond. Now return to your version and click
-the *Quit working in MyChanges* button. Now try to return to the
-*new* document. Notice that the document you created while in your
-version has now disappeared. Any other changes that you made in
-the version are also gone. Notice how your *standard_html_header*
-method now has a small red diamond and a lock symbol after
-it. This indicates that this object has been changed in a
-version. Changing an object in a version locks it, so no one else
-can change it until you commit or discard the changes you made in
-your version. Locking ensures that your version changes don't
-overwrite changes that other people make while you're working in a
-version. So for example if you want to make sure that only you are
-working on an object at a given time you can change it in a
-version. In addition to protecting you from unexpected changes,
-locking also makes things inconvenient if you want to edit
-something that is locked by someone else. It's a good idea to
-limit your use of versions to avoid locking other people out of
-making changes to objects.
-
-Now return to your version by clicking on it and then clicking the
-*Start working in MyChanges* button. Notice how everything returns
-to the way it was when you left the Version. At this point let's
-make your changes permanent. Go to the *Save/Discard* view as
-shown in the figure below.
-
-.. figure:: ../Figures/3-9.png
-
-   Committing Version changes
-
-Enter a comment like *This is a test* into the comment field and
-click the *Save* button. Your changes are now public, and all
-objects that you changed in your Version are now unlocked. Notice
-that you are still working in your Version. Go to the *Join/Leave*
-view and click the *Quit Working in MyChanges* button. Now verify
-that the document you created in your version is visible. Your
-change to the *standard_html_header* should also be visible. Like
-anything else in Zope you can choose to undo these changes if you
-want. Go to the *Undo* view. Notice that instead of many
-transactions one for each change, you only have one transaction
-for all the changes you made in your version. If you undo the
-transaction, all the changes you made in the version will be
-undone.
-
-Versions are a powerful tool for group collaboration. You don't
-have to run a live server and a test server since versions let you
-make experiments, evaluate them and then make them public when you
-decide that all is well. You are not limited to working in a
-version alone. Many people can work in the same version. This way
-you can collaborate on version's changes together, while keeping
-the changes hidden from the general public.
-
-Caveat: Versions and ZCatalog
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-ZCatalog is Zope's indexing and searching engine, covered in
-depth in the chapter entitled `Searching and Categorizing
-Content <SearchingZCatalog.html>`_.
-
-Unfortunately, Versions don't work well with ZCatalog. This is
-because versions lock objects when they are modified in a
-version, preventing changes outside the version. 
-
-ZCatalog has a way of connecting changes made to disparate
-objects. This is because cataloging an object must, by necessity
-change the catalog. Objects that automatically catalog
-themselves when they are changed propagate their changes to the
-catalog. If such an object is changed in a version, then the
-catalog is changed in the version too, thus locking the catalog
-itself. This makes the catalog and versions get along poorly.
-As a rule, versions should not be used in applications that use
-the catalog.
-
 Caching Services
 ----------------
 
 A *cache* is a temporary place to store information that you
 access frequently.  The reason for using a cache is speed.  Any
-kind of dynamic content, like a DTML page or a Script (Python),
+kind of dynamic content, like a a Script (Python),
 must be evaluated each time it is called.  For simple pages or
 quick scripts, this is usually not a problem.  For very complex
-DTML pages or scripts that do a lot of computation or call remote
+scripts that do a lot of computation or call remote
 servers, accessing that page or script could take more than a
-trivial amount of time.  Both DTML and Python can get this
-complex, especially if you use lots of looping (such as the 'in'
-tag or the Python 'for' loop) or if you call lots of scripts, that
+trivial amount of time.  Scripts can get this
+complex, especially if you use lots of looping (such as the
+Python 'for' loop) or if you call lots of scripts, that
 in turn call lots of scripts, and so on.  Computations that take a
 lot of time are said to be *expensive*.
 
@@ -403,7 +237,7 @@
 There is also an *Associate* view that allows you to associate a
 specific type or types of Zope objects with a particular cache
 manager.  For example, you may only want your cache manager to
-cache DTML Documents.  You can change these settings on the
+cache Scripts.  You can change these settings on the
 *Associate* view.
 
 At this point, nothing is cached yet, you have just created a
@@ -417,36 +251,47 @@
 First, before you can cache an object you must have a cache
 manager like the one you created in the previous section.
 
-To cache a document, create a new DTML Document object in the
+To cache a page, create a new page template object in the
 root folder called *Weather*.  This object will contain some
 weather information.  For example, let's say it contains::
 
-  <dtml-var standard_html_header>
+  <html>
+  <body>
 
     <p>Yesterday it rained.</p>
 
-  <dtml-var standard_html_footer>
+  </body>
+  </html>
 
-Now, click on the *Weather* DTML Document and click on its *Cache*
-view.  This view lets you associate this document with a cache
+Now, click on the *Weather* page template and click on its *Cache*
+view.  This view lets you associate this page with a cache
 manager.  If you pull down the select box at the top of the view,
 you'll see the cache manager you created in the previous section,
 *CacheManager*.  Select this as the cache manager for *Weather*.
 
-Now, whenever anyone visits the *Weather* document, they will get
-the cached copy instead.  For a document as trivial as our
+Now, whenever anyone visits the *Weather* page, they will get
+the cached copy instead.  For a page as trivial as our
 *Weather* example, this is not much of a benefit.  But imagine for
 a moment that *Weather* contained some database queries.  For
 example::
 
-  <dtml-var standard_html_header>
+  <html>
+  <body>
 
-    <p>Yesterday's weather was <dtml-var yesterdayQuery> </p>
+    <p>
+      Yesterday's weather was
+      <tal:yesterday tal:replace="context/yesterdayQuery" />
+    </p>
 
-    <p>The current temperature is <dtml-var currentTempQuery></p>
+    <p>
+      The current temperature is
+      <tal:current tal:replace="context/currentTempQuery" />
+    </p>
 
-  <dtml-var standard_html_footer>
+  </body>
+  </html>
 
+
 Let's suppose that *yesterdayQuery* and *currentTempQuery* are
 SQL Methods that query a database for yesterdays forecast and
 the current temperature, respectively (for more information on
@@ -459,10 +304,10 @@
 viewed hundreds of times in an hour, then all of those hundreds of
 queries would always contain the same information.
 
-If you specify that the document should be cached, however, then
-the document will only make the query when the cache expires.  The
+If you specify that the page should be cached, however, then
+the page will only make the query when the cache expires.  The
 default cache time is 300 seconds (5 minutes), so setting this
-document up to be cached will save you 91% of your database
+page up to be cached will save you 91% of your database
 queries by doing them only one twelfth as often.  There is a
 trade-off with this method, there is a chance that the data may be
 five minutes out of date, but this is usually an acceptable
@@ -472,11 +317,9 @@
 ----------------------
 
 Zope comes with an object that is used to send outbound e-mail,
-usually in conjunction with the DTML 'sendmail' tag, described
-more in the chapter entitled `Variables and Advanced
-DTML <AdvDTML.html>`_.
+usually in conjunction with a Script (Python).
 
-Mailhosts can be used from either Python or DTML to send an email
+Mailhosts can be used Python to send an email
 message over the Internet.  They are useful as 'gateways' out to
 the world.  Each mailhost object is associated with one mail
 server, for example, you can associate a mailhost object with
@@ -490,37 +333,8 @@
 your localhost machine is running a mail server, or change
 "localhost" to be the name of your outgoing SMTP server.
 
-Now you can use the new MailHost object from a DTML 'sendmail'
-tag.  This is explained in more detail in the chapter entitled
-`Variables and Advanced DTML`_, but we provide a simple
-example below.  In your root folder, create a DTML Method named
-'send_mail' with a body that looks like the following::
+Now you can use the new MailHost object from a Script.
 
-  <dtml-sendmail>
-  From: me at nowhere.com
-  To: you at nowhere.com
-  Subject: Stop the madness!
-
-  Take a day off, you need it.
-
-  </dtml-sendmail>
-
-  % Anonymous User - Feb. 9, 2004 9:55 pm:
-   The sendmail tag should be:
-   <dtml-sendmail smtphost="mymailhost.com">
-
-Ensure that all the lines are flush against the left side of the
-textarea for proper function.  When you invoke this DTML Method
-(perhaps by visiting its *View* tab), it will use your
-newly-created MailHost to send an admonishing mail to
-"you at nowhere.com".  Substitute your own email address to try it
-out.
-
-The API for MailHost objects also allows you to send mail from
-Script (Python) objects and External Methods.  See the Zope
-MailHost API in the Zope help system at Zope Help -> API Reference
--> MailHost for more information about the interface it provides.
-
 Error Logging Services
 ----------------------
 
@@ -554,9 +368,9 @@
 Searching and Indexing Services
 -------------------------------
 
-For detailed information about using searching and indexing
-services in Zope to index and search a collection of documents, see
-the chapter entitled `Searching and Categorizing Content`_.
+For detailed information about using searching and indexing services in Zope to
+index and search a collection of documents, see the chapter entitled
+`Searching and Categorizing Content <SearchingZCatalog.html>`_.
 
 Sessioning Services
 -------------------
@@ -564,13 +378,3 @@
 For detailed information about using Zope's "sessioning" services
 to "keep state" between HTTP requests for anonymous users, see the
 chapter entitled `Sessions <Sessions.html>`_.
-
-Internationalization Services
-------------------------------
-
-This section of the document needs to be expanded.  For now, please see
-documentation for Zope 2.6+ wrt Unicode and object publishing at:
-
-- http://www.zope.org/Members/htrd/howto/unicode-zdg-changes and
-
-- http://www.zope.org/Members/htrd/howto/unicode .

Modified: zope2book/trunk/source/index.rst
===================================================================
--- zope2book/trunk/source/index.rst	2009-02-15 12:22:46 UTC (rev 96568)
+++ zope2book/trunk/source/index.rst	2009-02-15 13:08:15 UTC (rev 96569)
@@ -19,11 +19,9 @@
    UsingZope.rst
    BasicObject.rst
    Acquisition.rst
-   DTML.rst
    ZPT.rst
    SimpleExamples.rst
    Security.rst
-   AdvDTML.rst
    AdvZPT.rst
    ScriptingZope.rst
    ZopeServices.rst



More information about the Checkins mailing list