Tag Libraries
for XSLT and XQuery
Erik Hennum, MarkLogic Inc.
Vyacheslav Zholudev, Jacobs University Bremen
August 2, 2011

Erik Hennum, MarkLogic Inc.
Vyacheslav Zholudev, Jacobs University Bremen
August 2, 2011
A Java technology for dynamic web pages:
Lots of adoption, lots of tag libraries
or
Tag libraries don't change what you can do with XML
but who can tap into XML technology
<html:table> <tag:attendees> <html:tr> <html:td>${last-name}</html:td> <html:td>${first-name}</html:td> </html:tr> </tag:attendees> </html:table>
<tag:attendees>
tag
gets the list of attendees<html:tr>
fragment for each attendee
${last-name}
and
${first-name}
<html:table> ... <html:tr> <html:td>Fitzgerald</html:td> <html:td>Elena</html:td> </html:tr> <html:tr> <html:td>Green</html:td> <html:td>Alfonso</html:td> </html:tr> <html:tr> <html:td>Hutz</html:td> <html:td>Egberto</html:td> </html:tr> ... </html:table>
<c:set var="feed-uri" value="http://news.ycombinator.com/rss"/> <feed:summary feed="${feed-uri}" ...> <p> <a href="${feed-uri}">${title}</a> ${description} </p> </feed:summary>
pull -
<feed:summary>
tag is a call
from the tagdoc to the taglib
push -
the tag content is a callback from taglib to tagdoc
with
${title}
and
${description}
parameters
closure -
the tag content refers to
${feed-uri}
variable
defined before the tag call
General-purpose language with programming syntax
- do anything
ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String lastName = rs.getString("LAST_NAME"); }
Domain-specific language with custom statements
- do one thing clearly (semantic transparency)
SELECT LAST_NAME, FIRST_NAME FROM ATTENDEES
<xsl:apply-templates>
vs <feed:summary>
Java | XSTag | |
---|---|---|
Expressions | Unified Expression Language | XPath |
Tag bindings | Configuration files | QName of function or template |
Callbacks | One unnamed tag body |
Many named handlers |
Fragment reuse | Document inclusion | Basic tag libraries |
<-- A basic taglib that defines page components --> <xst:taglib version="0.2" ... xmlns:pg=".../pagecomp"> ... <xst:tag name="pg:footer" as="element()*"> <p>Copyright 2011, Some Legal Entity</p> </xst:tag> </xst:taglib>
<-- A tagdoc that uses the taglib to generate a page --> <html xst:version="0.2" ... xmlns:pg=".../pagecomp"> <xst:import href="PageComponents.xstag"/> ... <body> ... <pg:footer/> </body> </html>
<xst:taglib version="0.2" ... xmlns:feed=".../feed/">
... other tags get feed and properties ...
<xst:tag name="feed:list" as="node()*">
<xst:param name="feed" as="document-node()*"/>
<xst:param name="onItem" implicit="true" as="handler(
$title as xs:string?,
...
) as node()*"/>
<xst:for-each name="item" at="number" select="...">
...
<xst:call handler="$onItem">
<xst:with-param name="title" select="..."/>
...
</xst:call>
</xst:for-each>
</xst:tag>
</xst:taglib>
<html xst:version="0.2" ... xmlns:feed=".../feed/"> <xst:import href="feed-lib/feeds.xstag"/> <xst:variable name="feed"> <feed:get>http://news.ycombinator.com/rss</feed:get> </xst:variable> ... <body> <h1><feed:title feed="{$feed}"/></h1> <ul> <feed:list feed="{$feed}" xst:handles="$uri, $title"> <li><a href="{$uri}">{$title}</a></li> </feed:list> </ul> </body> </html>
<html xst:version="0.2" ... xmlns:widget=".../widget/"> <xst:import href="feed-lib/feeds.xstag"/> <xst:import href="widget-lib/widgets.xstag"/> ... <body> ... <widget:accordion-list> <feed:list feed="{$feed}" xst:handles="$uri, $title, ..."> <widget:accordion-summary> {$title} </widget:accordion-summary> <widget:accordion-detail> <p>Source: <a href="{$uri}">{$uri}</a> ... </p> </widget:accordion-detail> </feed:list> </widget:accordion-list>
<html xst:version="0.2" ... xmlns:rfsh=".../refresh/"> <xst:import href="refresh-lib/refresh.xstag"/> ... <rfsh:refresh> <rfsh:trigger>feed-view</rfsh:trigger> <rfsh:provider>feed-ajax-server.html</rfsh:provider> <rfsh:params>feed-uri=feed-select</rfsh:params> <rfsh:targets>feed-title, feed-list</rfsh:targets> </rfsh:refresh> ... <form action="#">... <select id="feed-select">...</select> <button id="feed-view" type="button">View</button> </form> <h1 id="feed-title"/> <ul id="feed-list"/> ...
<div xst:version="0.2" ... xmlns:feed=".../feed/"> <xst:import href="feed-lib/feeds.xstag"/> <xst:param name="feed-uri">...</xst:param> <xst:variable name="feed"> <feed:get>{$feed-uri}</feed:get> </xst:variable> <h1 id="feed-title"><feed:title feed="{$feed}"/></h1> <ul id="feed-list"> <feed:list feed="{$feed}" xst:handles="$uri, $title"> <li><a href="{$uri}">{$title}</a></li> </feed:list> </ul> </div>
<root xst:version="0.2" ... xmlns:feed=".../feed/"> <xst:import href="feed-lib/feeds.xstag"/> ... <block ...>Table of Contents</block> <feed:list feed="{$feed}" xst:handles="$number, ..."> <block ...> <basic-link ...>{$title}</basic-link> ... <page-number-citation ref-id="f{$number}"/> </block> </feed:list> ... <feed:list feed="{$feed}" xst:handles="$number, ..."> <block id="f{$number}" ...>{$title}</block> ... </feed:list> ...
xst:taglib/@for
attributexst:tag
and xst:param
declaration
xst:call
to handler
Glue for component configuration and assembly -
not for:
Preprocessor implementation for experiments at
http://code.google.com/p/xstag