[Zpt] ZPT Guide for DTML users is up

Evan Simpson evan@digicool.com
Fri, 2 Mar 2001 14:17:38 -0500


It's at
http://dev.zope.org/Wikis/DevSite/Projects/ZPT/IntroductionForDTMLers

Here's the text:

A DTML user's Introduction to Presentation Templates

  DTML is good

    DTML solves a lot of problems, and solves them well.  You can use it to
    generate XML, HTML, RDF, SQL, or any other sort of text your heart
    desires.  You have access to the full power of Zope, through the
    namespace, and to Python, through expressions.

  DTML has problems

    For all that you may be familiar with DTML now, and love it to death,
you
    can probably remember a time when it made you tear your hair out.  Its
    syntax is quirky and unpredictable.  Some tag attributes use
    names, some use literal strings, and some can use Python expressions,
but
    there's not much rhyme or reason to it.  Access to names in the
namespace
    that contain punctuation, or names which must be reached via a path, are
    painful to use.

    If you do all of your page design in vi, emacs, or some other text-based
    editor, you're probably content to replace large, arbitrary chunks of
your
    page with '<dtml-var foo>'.  On the other hand, if you use a
    visual editor or work with someone who does, you've exerienced the pain
of
    having to reconcile DTML's dynamicism with the visual representation of
a
    page (or page fragment).

  DTML will go on

    Nobody who uses DTML wants to see it disappear.  We will continue to
    maintain and improve it, and may well incorporate the more successful
    ideas from Presentation Templates.  It will continue to be the
    language of choice for generating unstructured text (like SQL or CSV).

  Presentation Templates are better (where they apply)

    TALES, TAL, and METAL are our simplest, most straighforward attempt to
    design templates for SGML that still have enough expressiveness to get
the
    job done.  Each of them covers a single layer of template functionality
in
    a cleanly extensible fashion.  Forget the cutesy acronyms for a moment,
    and follow the reasoning:

    Expressions

      Just as in DTML, most of the grunt work of Presentation Templates
takes
      place inside of tag attribute values.  This means that you've aready
got
      a set of quote marks around the expression that you can't easily use
      inside it.  You want to be able to easily refer to Zope objects by Id
      and by paths of Ids, including Ids with odd characters in them.  You
      want to be able to use simple Python expressions. You want to be able
to
      write literal strings, and interpolate variables into a string.
Perhaps
      at some point you'll discover that there's a whole new notation that
you
      would like to be able to use (eg. Perl).  These requirements produced
      TALES.

      Referring to Zope objects by name is one of the clunkier bits of DTML,
      and it is made worse by the "everything in one pile" namespace DTML
      uses.  In TALES, the namespace is replaced by paths. There are a small
      number of "contexts" that you use as starting points for referring to
      objects. They are similar to Script bindings, and include "root",
      "here", "container", and "template", among others.  You pick a
context,
      then write a slash-separated path from the context to the object.
      For example, you refer to object "big-wig" in the same Folder as the
      Template by the path "container/big-wig".  You can acquire "dead
parrot"
      from "shop", and "shop" from the object on which the Template was
called
      with "here/shop/dead parrot".  Any character that is valid in a Zope
Id
      is allowed in a path.  Contexts are just builtin variables, and a path
      can start with any variable, so if you have defined variable "ick" as
the
      path "here/shop/dead parrot", you can use "ick/name" to get the
      parrot's "name" property.

      In DTML, sometimes you can use a Python expression in an attribute,
      sometimes you must, and sometimes you can't.  Every place that you can
      use a TALES expression, you can use Python.  You simply prefix the
      Python expression with "python:", as in "python:2 + 2" or
      "python:string.split(x, '','')".

      Similarly, you can always provide a literal string by using the
      expression type prefix "string:". Thus, "string:This isn't bad" is a
      valid TALES expression.  You can insert variables values into string
      expressions using "$varname"  (or "${varname}") syntax.  If
      variable "name" refers to "Evan" and "thing" refers to "cat",
      then "string:$name likes ${thing}s" produces "Evan likes cats".

      TALES is designed to be extended by simply defining new expression
      types.  If you wanted to use XPath notation, you could write an XPath
      expression engine, register it with TALES, and start writing
      expressions like "xpath:...".

    Statements

      DTML Tags are the statements of the DTML language.  They are
completely
      independent of the text in which they are embedded, and they don't pay
      any attention to any structure or grammar that the text may possess.
      If you mark up HTML with DTML carefully, you can produce a composite
      document that an HTML editing tool can tolerate, or can be made to
      tolerate.  On the other hand, it's easy to write DTML that an editing
      tool considers complete gibberish, but that renders into perfectly
good
      HTML. For this reason (among others) it is highly unlikely that many
      HTML tools will be adapted to deal well with DTML.

      Presentation Templates' TAL statements are attributes of ordinary HTML
      (or XML) tags.  This means that you can only use TAL with HTML or XML
      text, but Zope generates a lot of HTML.  Most of the popular HTML
tools
      ignore and preserve tag attributes that they don't recognize.  Since
TAL
      attributes have their own XML namespace (a prefix like 'z:' or 'tal:'
      that you choose), they don't interfere with the validity of XML
      documents. Thus, HTML or XML that you have marked up with TAL
      is likely to be perfectly compatible with tools that know nothing
about
      Zope.

      Write an HTML document as XHTML, or at least very tidily, and it has a
      nice easy-to-parse tree structure.  This allows us to frame template
      operations in terms of repeating, replacing, removing, or changing
      attributes of tags.  You can handle almost all cases where this model
      doesn't fit the dynamicism of your document by adding the odd
      '<span>' or '<div>', just as you might when applying CSS
      classes.

    Variables and Scoping

      Much of the difficulty of DTML lies in using the DTML namespace.  This
      is a powerful, difficult to control tool, especially when combined
with
      acquisition.  It is all too easy to accidentally obscure a name, and
      often hard to access names deep in the stack.  There are also security
      issues posed by the fact that DTML code cannot be sure that any name
in
      the namespace is bound to what it expected to find.

      Presentation Templates solve this, by providing your TALES expressions
      with a set of builtin variables.  If there is an object named 'helper'
      in the same container as your template, you can reliably access it
      as 'container/helper'.

      You can define your own global or local variables with the
      'define="var expr"' statement.  Local variables are like the names
bound
      by a '<dtml-let>'; Their scope is the statement tag and its
      content.  Global variables are more like 'REQUEST.set' names, since
      they are in scope from the start of the statement tag to the end of
the
      template.

    Template Operations

      Just as '<dtml-var foo>' is the most fundamental statement of
DTML,
      'replace="expr"' is the basic workhorse of TAL.  It replaces the tag
on
      which you place it with the value of the expression "expr". As you saw
      above, the TALES expression "expr" can evaluate to any Zope object,
      string, or Python-computed value.

      Rather than replacing an entire tag, you can set tag attributes with
      'attributes="attrname expr"', or replace the tag's contents by
      using 'insert="expr"'.

      Instead of '<dtml-in>', TAL uses 'repeat="var expr"'.  This
repeats
      the tag on which you place it once for each element of the
      sequence "expr". In each repetition, the local variable "var" is bound
      to the current element of the sequence, and loop variable "var" gives
      you access to the TAL equivalent of 'sequence-number'.

      The 'condition="expr"' statement is similar to '<dtml-if>', but
      more basic.  If the expression is true, the statement does nothing.
      If the expression is false, the tag and its contents is skipped.
      There is no equivalent to '<dtml-else>' or '<dtml-elif>'.

    The Macros Saga

      There are times when the power of '<dtml-var>' can be a problem.
      You can't tell, just by inspecting DTML source, whether
      '<dtml-var x>' inserts a string, performs a catalog search,
sends
      mail, or even restarts Zope!  Templates often include other templates,
      or parts of them, and it can be useful to know when that is only thing
      happening.

      If you have some way to tell that '<dtml-var sidebar>' inserts a
sidebar
      template, then you can solve the problem faced by designers who use
      WYSIWYG tools.  When they load a template page into their editor,
insert
      the sidebar template so that it appears normally in the page, instead
of
      as a little placeholder symbol.  When they save it back to Zope,
convert
      the sidebar back into a reference.

      METAL is the language that allows this sort of behavior.  It is
similar
      to TAL, in that it consists of tag attributes in an XML namespace.
You
      can use it to define **macros**, by placing a 'define-macro="name"'
      attribute on a tag that you want to re-use. While METAL affects
template
      rendering, inserting any macros that the template uses just before TAL
      executes, it *also* inserts macros whenever you get the source code
for
      the template.  You can create libraries of macros, with all of the
      advantages of code reuse, yet still see *everything* in a page when
you
      edit it.

      Macros can only be changed by editing the definition.  If you load a
      template into an editor, and change a tag that has a
'use-macro="expr"'
      attribute, these changes will have no effect.

      Only whole tags can be macros, so you can't make a
'standard_html_header'
      and 'standard_html_footer' macro.  Instead, you would create a
      'standard_page' template, make the entire 'html' tag a macro,
      and place a 'define-slot="main"' METAL attribute on the 'body' tag.
      Slots are tags within a macro that can be replaced when the macro is
      inserted.  They are replaced if the 'use-macro' statement tag contains
      a 'fill-slot="name"' statement tag, where 'name' matches the name of a
      slot in the macro.  To use your 'standard_page' template, you place
      'use-macro="here/standard_page/macros/page"' on your page's 'html'
tag,
      and 'fill-slot="main"' on its 'body' tag.  Now the 'html' tag and all
      of its contents *other than* the body tag will be replaced with the
      macro body.