Sitellite Design Templates
Chapter 8: XT Template Reference
XT tags
<xt:box>
This tag loads a Sitellite box. In a box tag, the name, which is the only required attribute (the rest are all dependent on the parameters the box in question requires), refers to the name of the box, starting with the name of the app (see the inc/app folder for the list of available apps), and then with the path to the box itself. The additional attributes of the box call are passed to the box in an array called $parameters. So for example, in the above box call, the variable $parameters['position'] would contain the value "left".
<xt:box name="sitellite/sidebar" position="left" />
<xt:block>
Defines a reusable template block. A block can be defined in an included template and still be used within the current template. Block parameters can be used using the block/param path.
<xt:block name="sidebar"> <h2 class="sidebar" xt:content="block/title" >Block title</h2> <p class="sidebar" xt:content="block/body" >Block body...</p> <p class="sidebar" align="right" > <a href="blocklink.html" xt:attrs="href block/link"> <xt:intl>Learn more</xt:intl> </a> </p> </xt:block>
<xt:cache>
Sitellite features partial-page caching with the <xt:cache> commands in your XT templates. The <xt:cache> tags offer unfortunately little performance improvement in most cases however, since XT still has to parse and loop through the tags between the <xt:cache and </xt:cache> either way. Essentially, this will only see performance improvements when you wrap these tags around content that requires that boost in performance. Another feature of <xt:cache> is the ability to cache a separate copy for each specific visitor, so that performance is boosted on subsequent page requests from the same visitor. This has the advantage of allowing content to be cacheable that still contains personalized data. In this case, if we didn't include the scope="session", the next visitor to that screen would see the previous visitor's name and profile information -- a big privacy faux pas!
<xt:cache> <xt:box name="sitellite/sidebar" position="left" /> </xt:cache> <xt cache scope="session"> <h2>Your profile, <xt:var name="session/firstname" />:</h2> <xt:box name="myapp/user/profile" /> </xt:cache>
<xt:code>
The <xt:code> tag tells XT to wrap the enclosed content in the language identifiers of your choice (the default is PHP). The CDATA tags are in case you have any "illegal entities" in your source code (namely, < and &), as does the above example since it prints a <br /> tag.
<xt:code><![CDATA[ echo 'hello<br />'; ]]></xt:code>
The nice thing about this feature is that, coupled with my article on publishing a static web site from Sitellite, you can use this to publish semi-dynamic web sites that are completely devorced from Sitellite itself (leaving the Sitellite-powered site as a staging area), as well. Couple this with some simple rsync-based mirroring and perhaps a little cron, and you've got a full-fledged language-agnostic content publishing solution.
Of course, you'll want to make sure your staging area is blocked off from public access, or people will be able to see your source code by viewing the source of your templates. You could do this either by firewalling it off entirely, or using SSL and HTTP basic authentication to access the staging site.
Here's a quick overview of the different languages supported:
| <xt:code language="php"></xt:code> | <?php ?> |
| <xt:code language="asp"></xt:code> | <% %> |
| <xt:code language="jsp"></xt:code> | <% %> |
| <xt:code language="eruby"></xt:code> | <% %> |
| <xt:code language="python"></xt:code> | <% %> |
| <xt:code language="eperl"></xt:code> | <: :> |
| <xt:code language="asp_include"></xt:code> | <%@ %> |
| <xt:code language="jsp_include"></xt:code> | <%@ %> |
| <xt:code language="runat_server"></xt:code> | <script runat="server"></script> |
| <xt:code language="javascript"></xt:code> | <script language="javascript type="text/javascript"></script> |
Most other languages I've seen use the asp/jsp tag style as well, so I'm sure there are more that are supported than just the ones mentioned here.
<xt:comment>, <xt:note>
Comment tags in XT are stripped out. It allows you to have comments in your templates that are hidden from the final user output. However, this is a pretty moot point, since unless you turn it off via htaccess or your Apache configuration, users can access the source of your templates directly in the browser, and read these comments anyway. So don't put any passwords in there. Comments that you want remain in the final output of the template can be made using the following syntax. <xt:note> is an alias for <xt:comment>
<xt:comment>This is a comment.</xt:comment> <xt:note>This is an other comment.</xt:note>
However, there's a problem with this approach: It's in clear violation of the preview capabilities of XT templates, since the comment text would be rendered as if it were web page content in the preview. To solve this, you can either insert a style="display: none" attribute into the comment tag itself, or if the browser you're using to preview the templates supports the following CSS trickery, you can include this rule in your CSS file:
xt\:comment, xt\:note {
display: none;
}
<xt:condition>
Evaluates a complex conditional statement and returns the first expression to return true (or any value other than 0 and false), or the <xt:else> condition if all others do not succeed. This is a compount command, using the <xt:condition>, <xt:if>, <xt:elseif>, and <xt:else> tags. A shorthand for evaluating a single condition is to use the xt:condition attribute command, which evaluates only a single condition, and has no "else" clause either.
<xt:condition> <xt:if expr="php: foo == 'bar'"> <p>foo is 'bar'</p> </xt:if> <xt:elseif expr="php: foo == 'asdf'"> <p>foo is 'asdf'</p> </xt:elseif> <xt:else> <p>foo is unknown</p> </xt:else> </xt:condition>
<xt:doctype>
In addition to the comment tags, doctype declarations are stripped away during the XT template rendering. To compensate for this, we've added a special doctype tag, which can be used as follows. Make sure however that the <xt:doctype> tag begins on the first line of the document.
<xt:doctype root="html" access="public" name="-//W3C//DTD XHTML 1.0 Transitional//EN" uri="DTD/xhtml1-transitional.dtd" />
<xt:exec>
Executes an expression without returning the output it creates. Useful for setting complex values or multiple values at once.
<xt:exec value="php: a.val = b.val" />
<xt:form>
This tag loads a Sitellite MailForm. In a form tag, the name, which is the only required attribute (the rest are all dependent on the parameters the form in question requires), refers to the name of the form, starting with the name of the app (see the inc/app folder for the list of available apps), and then with the path to the form itself.
<xt:form name="sitemember/register" />
<xt:import>
Imports the specified package using the global $loader object, making that class available to the <xt:set-obj> command.
<xt:import pkg="saf.Date" ></xt>
<xt:inc>
Includes the specified file, which is processed depending on the type specified. The default type is 'xt', which processes the included file as a template. Additional types can be 'messy', which processes the file as a messy template, 'csv' which treats the file like a comma-separated values file. and uses the specified delimiter to split lines into table cells. Known delimiters are "comma", "tab", "colon", "semicolon", and "pipe", and other delimiters may be used by entering them in the delimiter attribute. Additionally, with the 'csv' type, a header attribute can be specified (set it to 'yes') to use the first line of the CSV file as a list of table column headers. If an include is of the type 'plain', it will not be evaluated at all. The last type is 'xml', which causes XT to treat the file as an XML document, parse it, and allow you to access a list of "item" values using XTE expressions. An item is a node in the XML document whose child nodes become its properties. The 'xml' type is unique in that it causes the markup contained within the inc tags to become the "sub" template used to display each item. Where in the XML document the items are to be found is determined either by the item attribute of the inc tag, which should contain an saf.XML.Doc.Query-compatible XPath expression. If this attribute is not present, XT assumes the items are all of the nodes below the root node of the XML document. New: 'simple' type has been added, which uses saf.Template.Simple to parse the included file. Name attribute value is also an expression now, with a default type of 'string'.
<xt:inc name="filename" ></xt> <xt:inc name="filename"> <p> Mockup text for previewing that will be replaced by the contents of the included file. </p> </xt:inc> <ul> <xt:inc name="sites.rss" type="xml" item="/rss/item"> <li> <a href="#" xt:attributes="href xml/link" xt:content="xml/title"> Title </a> <span xt:replace="xml/description"> Description </span> </li> </xt:inc> </ul>
<xt:intl>
Translates the enclosed text using the saf.I18n package and the global $intl object.
<xt:intl>Hello</xt:intl>
<xt:loop>
Loops through the specified list. Assigns each item to loop/i.
<xt:loop through="i php: range(1,25)"> <p xt:content="loop/i/value">1</p> </xt:loop>
<xt:register>
Imports a global object into the XTE register, allowing it to be used in PHP expressions. The name attribute may also be a comma-separated list.
<xt:register name="page" />
<xt:set>
Sets the value of object/foo to be the string "bar". The value attribute is an XTE expression with the default type string.
<xt:set name="foo" value="bar" />
<xt:set-obj>
Creates a new object in the XTE register. The new attribute is evaluated as a literal PHP string calling the class constructor and passing it the appropriate values.
<xt:set-obj
name="c"
new="Alt ('even', 'odd')"
/>
<xt:show>
Calls a block and passes it a set of parameters. The mockup inside the tag is used for previewing when no Sitellite installation is available, allowing the template to still look as if the call to the block occurred. This same mockup inclusion can be done with the <xt:inc> tag as well, as shown in the example above.
<xt:show block="sidebar" title="Volunteers Wanted!" body="Come volunteer with us to help improve our project." link="/index/volunteer"> <h3 class="sidebar"> Block test</h3> <p class="sidebar"> Block body...</p> <p align="right" class="sidebar"> <a href="blocklink.html"> Learn more </a> </p> </xt:show>
<xt:sql>
The <xt:sql> command is a compound command using the <xt:sql>, <xt:bind>, <xt:sub>, and <xt:else> tags, which queries the database connection (the global $db object) with the specified query and returns the results formatted using the contents of the <xt:sub> tag like a block. The <xt:else> tag provides an alternate template block to display in case there are no results for the specified query. The <xt:bind> tags allow you to "bind" values to the query, which substitutes question marks in the query for the bound values. The query results are accessible in the through the "result" object path, and it's properties correspond to the list of columns returned by the query. Another powerful feature of this command is that you can automatically add paging capabilities to your query results (via the saf.Database.Pager package) just by adding the pager="yes" attribute to the <xt:sql> tag. Other pager-related attributes are limit, offsetvar, and totalquery. Limit defaults to 20, and offsetvar defaults to "offset" (accessible via cgi/offset) and the totalquery is used very seldom, only when a separate query can be used to find out the total number of results. Also note that the limit clause should be left out of the SQL query. In case of error, the message and information is accessible in the xt:else clause via result/error, result/err_sql, and result/err_bind/valuenumber.
<table <tr> <th>Last Name</th> <th>First Name</th> <th>Department</th> </tr> <xt:sql query=" select * from employees where title = ?" pager="yes"> <xt:bind value="cgi/title" ></xt> <xt:sub> <tr> <td xt:content="result/lastname"> Smith </td> <td xt:content="result/firstname"> Joe </td> <td xt:content="result/dept"> Accounting </td> </tr> </xt:sub> <xt:else> <tr> <td colspan="3"> No matches </td> </tr> </xt:else> </xt:sql> </table>
<xt:tpl>
These tags surround every XT template, helping to ensure that even if the contents of your template are not necessarily intended to be in XML format, it can still be valid XML.
<xt:tpl version="1.0"></xt:tpl>
<xt:transform>
Sets transformation directives which are used to transform the values of XTE paths who end in the specified name. The format of a transformation directive is the name of the tag, the type of transformation (as defined by the saf.Template.Transformation package), and the transformation call (if it's a func or function transformation). Multiple transformations are separated by a semicolon, and blank space for legibility is encouraged.
<xt:transform directives=" foo, func, ucfirst (object.foo); bgcolor, alternate, even, odd " />
<xt:var>
Substitutes itself with the value of the XTE expression it names. The XTE expression has a default type of "path".
<xt:var name="xte path" ></xt>
<xt:xmldecl>
This tag is used to insert the xml declaration at the beginning of the document. The attributes of this tag are the same as for the standard XML declaration itself, so there's nothing new to remember.
<xt:xmldecl version="1.0" encoding="utf-8" />
<xt:xmlstyle>
This creates an XML stylesheet declaration.
<xt:xmlstyle type="text/css" href="mystylesheet.css" />
XT Attributes
xt:content attribute
Replaces the value of the current tag with the result of the given expression.
<p xt:content="cgi/foo"> Temp value of foo </p>
xt:replace attribute
Replaces the entire tag with the result of the given expression.
<span xt:replace="cgi/foo"> Temp value of foo </span>
xt:attributes attribute
Replaces the specified attributes with the result of that expression. Multiple attributes may be separated by semicolons in the expression. An abbreviated command alias, xt:attrs, also exists.
<p align="left" xt:attributes="align intl/align"> Some text here </p>
xt:loop attribute
Loop using the current tag as the wrapper for the loop. The expression syntax is the same as the full loop command. An alias xt:repeat also exists, so ZPT users will find XT even more familiar.
<table> <tr xt:loop="i php: range (1, 5)"> <td xt:content="loop/i/number">1</td> </tr> </table>
Inline attribute expressions
The ${expression} shorthand also allows you to include tags in other non-XT attributes. This is a shorthand for the xt:attributes example seen above, but comes at the sacrifice of previewability in some cases (ie. in this example, the path to the image will not resolve when previewing the template directly in a browser).
<img src="${site/prefix}/pix/foo.gif" />
XT Expressions
The real power behind the XT template language is not in the tags or in the XML at all, but in what's inside the tags. That is, the XT Expression language, or XTE for short.
XTE expressions are made up of three basic components and only two operators. These components are the string: path: and php: evaluation methods, which can be combined in a single expression to create more complex output, and the two operators are the semicolon and the pipe characters.
A semicolon terminates an expression and begins a new one, but does so under the same output buffer, causing them to typically act like concatenators more so than separators. But semicolons are not necessary when going from one evaluation method to the next, making them rarely needed (and in fact, only supported by a few select tags, including , , , and the xt:condition attribute).
Pipes are used as an "or" command, which says "if the value of the first part of the expression results in no output or a false value (ie. a path that pointed to a nonexistant object), then try the next.
Here is an example of the pipe operator:
path: site/url | string: http://www.simian.ca/
This says to the XTE engine "use the value of the object path site/url, but if that's not found then use the string http://www.simian.ca/". There is one other syntax feature that can make it easier to concatenate paths into strings, which is the ${path} inclusion syntax. For example:
string: one ${numbers/2} three ${numbers/4} This is almost the equivalent of saying:
string: one path: numbers/2 string: three path: numbers/4
The only difference is that the first is split into four separate expressions that are concatenated at the end, and the first is done as if the ${path} components were an inline sub-expression. The first is also shorter and makes it easier to distinguish its different components.
Paths
Paths are the really interesting part of XTE, and they are where it gets its real power from. Paths are the way you refer to objects, arrays, object properties and methods, and array values in XTE. So translating the path in the first example into PHP code, we were actually saying:
$site->url
Where $site is a global object, and url is a property of that object. It must be understood by XT developers that the global-ness of the object only means that it's origin was as a global object, because any object used by XTE that was global is first copied to the XTE register and used from there, so as not to affect in any way the values and settings of global objects, and also so as to provide a level of isolation between invocations of the XT engine. So basically, $site was a global object when site/url was called, but before it is acted on it is first moved to the register.
There are also a few predefined path starting points defined by XTE globally as well as during the execution of certain tags, such as the <xt:loop> tag, which allow you to refer to objects defined at that time for that specific purpose. These are as follows:
| object | Refers to the object or associative array passed to the current invocation of the XT engine. |
| nothing | Returns a false value. |
| attrs | Contains a list of all of the attributes of the current XML tag. |
| paths | Contains a list of all of the possible XPath paths that point to the current XML tag. These paths are used for tag and tag attribute binding with the bind() and bindAttr() methods. Only available for ordinary tags, not XT tags. |
| cgi | Refers to the global $cgi object, which contains all of the HTTP request values. |
| session | Refers to the global $session object, which contains all of the user info, such as username and email, if the user is logged in. User status can be determined with the paths session/valid and session/admin. |
| site | Refers to the global $site object, which contains all of the directory and url info. To reference a relative URL, for example, so that your template can be called from the document root or within a subfolder of a site, you could use the site/prefix path. |
| loop | Contains an array of loop objects, the names of which are defined in each loop's expression. Each loop object has the following properties: index (loop iteration number, counting from 0), number (loop iteration number, counting from 1), even and odd (boolean values depending on whether the loop iteration index is an even or odd number), value if the iteration value was a string or integer, start (true for the starting repetition -- index 0), end (true for the final repetition), and length (the total number of repetitions). |
| result | Contains the current result object from a database query made by an <xt:sql> command. The properties of this object correspond to the column names returned from the query. |
| block | Contains a list of parameters passed to the current call to <xt:show> for that <xt:block>. Used inside the <xt:block> command to allow parameter passing, making blocks similar to PHP functions or macros. |
| xml | Contains the current item in an XML include call. Nodes below the item are accessible via xml/nodename, and attributes are accessible via xml/attrs/attrname. |
Strings
PHP
PHP code in expressions has a different syntax and a few caveats compared to straight-up PHP code in a script. For one, in Sitellite objects are the way we manipulate data and also often contain the logic needed to manipulate themselves, so the PHP code in XTE expressions can't shy away from objects. The problem is, PHP's object syntax is not very conducive to working within an XML tag attribute. You see, the > character in $site->url or any other property or method reference would have to be written as >, which is the XML entity used for displaying > characters, since the > character has special meaning in XML (the closing of a tag). So what XTE allows you to do is to refer to objects like this:
site.url
This will be translated into $site->url just before being evaluated. You can also get away with doing this with arrays, for example:
people[joe]
XTE simplifies this in two ways: First it adds the missing dollar sign before people so you have $people[joe], and second it quotes joe so you have $people['joe'], which is correct PHP-speak. But don't worry, XTE can be told not to quote values you mean to be variable, for example:
people[ cgi.person ]
This will be turned into $people[$cgi->person] like you'd expect. Just make sure you include the space between the square braces and the object inside of them.
Actually, XTE goes a step further with objects and arrays in inline PHP expressions. You see, so that calls to XTE do not modify values outside of itself (ie. if a variable is set in XTE it does not exist outside of XTE, and if a variable taken from outside XTE is modified, the modification only affects the copy that XTE took of it and not the real thing). This is because XTE keeps its own register of objects and arrays. This is where the main caveat with using PHP in XTE expressions comes in.
site.url doesn't actually call $site->url or even $GLOBALS['site']->url. It calls $this->register['site']->url. This means that objects called in PHP expressions must first be registered by XTE. Paths do this for you automatically, but PHP expressions do not due to the way they are evaluated. This is why there is an <xt:register> XT tag, which registers a global object with XTE without using it yet.
Assignments
In some XT tags, a value is being set that needs to be named. These include the <xt:loop> tag and the xt:attrs and xt:loop attributes. In these cases, the named value is prepended to the entire expression and separated from it by a space. As you can see, the value of each element of the expression "php: range ('a', 'z')" is assigned to the path loop/letter, since letter was specified in the initial assignment expression.
<xt:loop through="letter php: range ('a', 'z')">
<p xt:content="loop/letter/value">a</p>
</xt:loop>
Conditions
Conditions are evaluated like any other expression with a couple small differences. Instead of returning the value of the expression, a condition evaluates that value to be either true or false, and the body of that condition is either shown or not shown depending on that true or false value. A condition may also be negated using a "not" key word, which has the same syntax as an assignment name. For example:
<p xt:condition="php: true"> This text will show because true always evaluates to true. </p> <p xt:condition="not php: true"> This text will not show because it was negated with the "not" key word. </p>
Default Types
Each XTE expression has a default type associated with it that can be ommitted and XTE will automatically interpret the expression as beginning with that type. For example, the <xt:var name="xte path" ></xt> command has a default type of "path". Paths can also be abbreviated if they start with "object/", so the following are evaluated as equivalents:
<xt:var name="path: object/varname" ></xt> <xt:var name="object/varname" ></xt> <xt:var name="varname" ></xt>
PHP Shorthand Reference
PHP Shorthand is used in SimpleTemplate and XT templates in various tags to simplify the PHP syntax used. In XT this was originally intended to avoid PHP's XML-invalid characters, but it also has the benefit of increasing the readability of template tags by keeping them as alphanumeric as possible.
Keyword Substitutions
Case-insensitive keywords are replaced by their respective operators. These include:
- AND Becomes "&&"
- EQ Becomes "=="
- EQQ Becomes "==="
- GE Becomes ">="
- GT Becomes ">"
- LE Becomes "<="
- LT Becomes "<"
- MOD Becomes "%"
- NE Becomes "!="
- NEQ Becomes "!=="
- NOT Becomes "!"
- OR Becomes "||"
Additional Transformations
- HTML entities for "<" and ">" are converted to their proper symbols.
- "." is converted to "->" and to mimick a JavaScript-style object syntax.
- "_" is converted to "." as an optional additional concatenator.
- "->" with a space on either side of it is converted back into a ".".
- Object references are then converted into global references (ie. $GLOBALS['object']->property). This can be changed in specific instances via the PHPShorthand::replaceGlobals() method.
- Single- and double-quoted strings are handled as special cases and are not transformed.
- [key] array indexes are expanded to their quoted form (ie. ['key']).
Examples
foo.bar ('foo.bar') becomes:
$GLOBALS['foo']->bar ('foo.bar')
not isset (someArray[keyname])
becomes:
! isset ($GLOBALS['someArray']['keyname'])
foo.bar ge bar.foo and not empty (foo.asdf)
becomes:
$GLOBALS['foo']->bar >= $GLOBALS['bar']->foo && ! empty ($GLOBALS['foo']->asdf)
Variable Scope
Currently, the scope of objects and variables is not like one would expect in a standard programming language. When an object is modified inside of a command construct, such as a loop or a condition, the modification is only set inside that construct, and not retained beyond it.




Charles Brunet