xsl-list
[Top] [All Lists]

[xsl] 3D XSLT - Experience and Feedback Welcome

2013-03-19 06:42:07
   Hi,

This is an attempt to formalize my experience with a design pattern
that I call 3D XSLT, which consists in feeding an extra document to
the transformation with elements that carry no information but their
name, for the sole purpose of rule-based matching. I'd be glad to
gather feedback and alternatives to this approach.

While baking [1] a web site, generating in advance all the HTML pages
from a database of manga titles and authors in XML format, I felt the
need to introduce an extra dimension to the transformation.

What I mean by dimension is a vector that directs the flow of the data
transformation in a direction. There are typically two in rule-based
transformations:

* the select attribute of xsl:for-each and xsl:apply-templates,
associated with the match attribute of xsl:template
* the mode attribute of xsl:apply-templates, associated with the mode
attribute of xsl:template

I am used to the combination of match and mode, or 2D XSLT, to make
the input data bounce left and right multiple times until reaching the
expected output. For complex transformations, I further divide the
transformation into several steps, each step adding an extra layer of
decoration on top of the same data:

* Open Document Format Spreadsheet XML -> XML -> XML -> XML -> XHTML

For the final transformation from XML to XHTML, I chose to use
xsl:result-document to generate all the HTML pages from a single
transformation, rather than running a separate transformation to
generate each page.

I then started the development of the transformation with template rules:

- matching different parts of the input data for different types of pages

  * / for the home page,
  * mangaxml:manga for the page with the details of the manga

- using different modes to generate different parts of each page:

  * mode="uri" for the relative URL of the page
  * mode="title" for the title of the page
  * mode="navigation" for the navigation tabs
  * mode="contents" for the main contents
  * mode="preview" for a short preview linking to a page with details

This approach fell short when developing the transformation further to
generate additional types of pages ; several pages would correspond to
the same input data, and thus, the type of elements was no longer
sufficient to cover all cases; an extra dimension of variability was
needed:

  * / for both home page and faq page as well as other pages with
static contents
  * mangaxml:mangas for the different pages with lists of mangas by
country, by date...

My first idea was to use modes for two dimensions, both for the types
of pages and the parts of pages, but I encountered two issues which
made it too complex to be suitable:

  * although a template can match multiple modes, xsl:apply-templates
can only select a single mode at once
  * the mode parameter does not accept an expression to change the
mode using the value of a parameter

Although impracticable, this idea lead me to the solution that I
actually implemented: I introduced an extra input document with
elements that play the role of modes for the transformation:

  * <site:page name="glossary" /> instead of mode="glossary"
  * <site:page name="faq" /> instead of mode="faq"
  * <site:page name="creation-country" /> instead of mode="creation-country"
  * <site:page name="creation-date" /> instead of mode="creation-date"
  * <site:page name="manga" /> instead of mode="manga"

and while writing these lines, it occurred to me that the following
form may have made the concept more explicit:

  * <mode:glossary /> instead of mode="glossary"
  * <mode:faq /> instead of mode="faq"
  * <mode:creation-country /> instead of mode="creation-country"
  * <mode:creation-date /> instead of mode="creation-date"
  * <mode:manga /> instead of mode="manga"

The templates still have only two dimensions for rule-based matching,
mode and match, but they are applied either to a mode and a "mode
element" or to a mode and an input element, which is carried
throughout the transformations using a tunnel parameter:

<!-- context: / -->
<xsl:template match="/">
  <xsl:apply-templates mode="page"
select="$metaDoc/site:site/site:page[@name='glossary']">
    <xsl:with-param name="context" select="/" tunnel="yes" />
  </xsl:apply-templates>
  <xsl:apply-templates mode="page"
select="$metaDoc/site:site/site:page[@name='faq']">
    <xsl:with-param name="context" select="/" tunnel="yes" />
  </xsl:apply-templates>
  ...
  <xsl:apply-templates />
</xsl:template>

<!-- context: mangaxml:author -->
<xsl:template match="mangaxml:author">
  <xsl:apply-templates mode="page"
select="$metaDoc/site:site/site:page[@name='author']">
    <xsl:with-param name="context" select="." tunnel="yes" />
  </xsl:apply-templates>
</xsl:template>

...

<!--
  mode: "page" + *
  context: $context (tunnel)
-->
<xsl:template mode="page" match="site:page">
  <xsl:variable name="uri" as="xs:string">
    <xsl:apply-templates mode="uri" select="." />
  </xsl:variable>
  <!-- instructions to generate result document for each HTML page -->
</xsl:template>

<!--
  mode: "uri" + "glossary"
  context: /
-->
<xsl:template mode="uri" match="site:page[@name='glossary']">
  <!-- glossary is the home page -->
  <xsl:text>/</xsl:text>
</xsl:template>

<!--
  mode = "uri" + "faq"
  context: /
-->
<xsl:template mode="uri" match="site:page[@name='faq']">
  <xsl:text>faq/</xsl:text>
</xsl:template>

<!--
  mode = "uri" + "author"
  context: mangaxml:author
-->
<xsl:template mode="uri" match="site:page[@name='author']">
  <xsl:param name="context" as="element(mangaxml:author)" tunnel="yes" />

  <xsl:text>mangas/by/author/</xsl:text>
  <xsl:value-of select="$context/@name" />
  <xsl:text>/</xsl:text>
</xsl:template>

...

Do you have other examples of use of this pattern? Can you suggest
simpler alternatives?

Your feedback will be appreciated.

Cheers,

Eric Bréchemier

--

[1] Bake, Don’t Fry -  2002-07-09 by Aaron Swartz
http://www.aaronsw.com/weblog/000404

P.S. per Tommie's recommendation, please quote only the minimum amount
of my message, or reply without quoting my message, which for an
unknown reason triggers a false positive on the spam filter of the
list.

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--


<Prev in Thread] Current Thread [Next in Thread>