The ResultXSLT(TM) Environment

$Date: 2004/05/21 17:20:28 $(UTC)


Table of Contents

1. Abstract
1.1. Evolution
2. Overview
2.1. The process
2.2. Layout
2.3. The ResultXSLT environment
2.4. Document Type
2.5. Production
3. Out/in branch pairs
4. Vocabulary
4.1. Action annotation attributes
4.2. Annotation namespace declarations
4.3. Attribute annotation namespaces
4.4. Housekeeping annotation attributes
4.5. Action element
5. Illustrative complete test

1. Abstract

"ResultXSLT"(TM) is a methodology, an XSLT 1.0 stylesheet and a supplemental validation expression for the synthesis of importable XSLT 1.0 stylesheet fragments out of pro-forma transformation results that are seeded with the necessary information to build the desired transformation.

1.1.  Evolution

Based on lessons learned from the "LiterateXSLT"(TM) environment developed in December 2002, this environment is the second generation of stylesheet synthesis tools created by Crane Softwrights Ltd.

Whereas the LiterateXSLT set of annotations provided for the synthesis of a complete stylesheet tied to a single vocabulary, the ResultXSLT is more modest and, in the end, turns out to be more flexible.

One of the earliest observations regarding the first Universal Business Language (UBL) 0p70 stylesheets created by LiterateXSLT was that synthesizing a stylesheet tied to a single vocabulary did not exploit the investment in developing prototype transformation results. Users of other vocabularies asked about the use of the UBL stylesheets and it was obvious the stylesheets were so hardwired to the one vocabulary as to have no utility in other contexts.

A lot of thought has gone into this ResultXSLT environment to ensure that a single investment in a prototypical transformation result could be exploited by many vocabularies. The result ended up being very simple, and sometimes the simplest ideas are the most powerful. The entire vocabulary has only two required action annotation attributes, and two required annotation namespace declarations. Optionally one may wish to use two attribute annotation namespaces, four housekeeping annotation attributes and one action element that has two attributes.

Crane's UBL 1.0 stylesheet library is constructed using ResultXSLT and provides an illustrative example of the use of all of the features of this vocabulary.

2.  Overview

It is often difficult for a stylesheet writer to conceptualize the result tree order when writing an XSLT stylesheet.

Yet, when writing an XSLT stylesheet, the author is obliged to ensure the transformation result is produced in result parse order. The author must orient their primary thinking around the result tree and treat the source tree with a secondary attitude. Having determined "what belongs next" in the result tree, the author goes to the source tree to find the information that is necessary to produce the result.

A common "good practice" when approaching writing an XSLT stylesheet is to mock up the result as a result instance. This helps the author of the stylesheet precisely determine the correct result structure needed in order to produce the result rendering. For example, XSL-FO processors accept hand-authored XML instances of the XSL-FO vocabulary as the input to the rendering process. This allows the stylesheet author to create a complete mockup of the result as a result instance, using an XSL-FO processor to render the mockup and the author to visually confirm the desired result.

At this stage of stylesheet development, the stylesheet author must "deconstruct" the result instance into separate template rules, divine the XPath patterns to match each of these template rules, divine the XPath select expressions to apply the template rules to the source nodes of the input data, establish components of the stylesheet to be localized for maintenance purposes, and organize the stylesheet into an order that promotes successful long-term maintenance.

ResultXSLT does the deconstruction step of this process for the stylesheet writer based on seeded signals of required "branches" in the result tree. Once deconstructed into a set of fragments of the result tree, all that remains is to write stylesheet logic to engage and be engaged at various points of the building of the result. Through XSLT importation, an importing stylesheet can provide the vocabulary-specific logic and import a generic vocabulary-independent collection of result tree fragments.

2.1.  The process

The ResultXSLT process can be overviewed as follows:

The process begins in the bottom left of the diagram with the prototypical result instance.

2.2.  Layout

The prototypical result instance is created as a sample visualization of the results of transforming the production source documents.

Typically this is hand authored or could be the export from a tool in which the visualization is created. Placebo values for source constructs are included in the visualization.

Using the ResultXSLT annotation vocabulary described in this environment, signals are added to the prototypical result to indicate where out/in branch pairs are to be created in the result tree. Other annotations indicate portions of the result that are not to exist in the synthesized stylesheet and yet other annotations perform housekeeping duties regarding the order and documentation of constructs in the output stylesheet.

At any time the prototypical result instance can be forwarded to the production process for visualization using the production tools, rather than any creation tools. Visualizing the result instance in the production environment will give assurances that the choice of markup in the prototypical result instance is acceptable.

Using the ResultXSLT synthesis stylesheet the prototypical result instance is transformed into a synthesized importable stylesheet.

2.3. The ResultXSLT environment

There are three files in this environment:

2.3.1.  stripres.xsl stylesheet

When the presence of the ResultXSLT vocabulary in the prototypical result instance disturbs the production process, the stripres.xsl XSLT 1.0 stylesheet can remove the presence of any attribute or element from any of the ResultXSLT namespaces. The output instance can then be passed to the production process for visualization.

2.3.2.  result.rnc grammar expression

The grammar of ResultXSLT annotations is normatively described by the ISO/IEC 19757-2 RELAX-NG Compact Syntax expression in result.rnc.

Using this expression one can validate the use of the annotations in the prototypical result instance.

2.3.3.  result.xsl synthesis stylesheet

An importable stylesheet is synthesized by applying the result.xsl XSLT 1.0 stylesheet transformation against a prototypical result instance.

2.4.  Document Type

The production source instances are all of a given vocabulary described by a document type of some kind. These are the source files that will be transformed to the production results by the authored stylesheet.

The authored stylesheet imports the synthesized importable stylesheet and typically (but not necessarily) overrides the "out" template rule of each of the synthesized out/in branch pairs, making calls where needed to each corresponding "in" template rule.

2.5.  Production

The production process can take the prototypical result instance and the transformed results of the source files to produce the final results.

3.  Out/in branch pairs

The crux of ResultXSLT annotation is the identification of important branches in the input prototypical-result tree, thus creating out/in branch pairs in the output importable stylesheet fragment.

Consider this simple example where a prototypical HTML result has been created in order to ascertain all of the markup needed for the end result of a transformation.

<html>
  <head>
    <title>A test of ResultXSLT(TM)</title>
  </head>
  <body>
    <p>Here is a list of the inputs:</p>
    <ul>
      <li>
  ...

This prototypical result is annotated to indicate that a branch named "list" of the result tree generation begins at the <body> element:

<html xmlns:x="http://www.CraneSoftwrights.com/ns/result"
      x:out-prefix="out"
      x:in-prefix="in"
      xmlns:out="urn:ss-URI:out"
      xmlns:in="urn:ss-URI:in">
  <head>
    <title>A test of ResultXSLT(TM)</title>
  </head>
  <body x:branch="list">
    <p>Here is a list of the inputs:</p>
    <ul>
      <li x:branch="item">
  ...

The ResultXSLT environment synthesizes the following stylesheet fragment in a file called, say, test-frag.xsl:

<!--Root: default processing for the root node-->
   <xsl:template match="/">
      <html>
         <head>
            <title>A test of ResultXSLT(TM)</title>
         </head>
         <xsl:call-template name="out:list"/>
      </html>
   </xsl:template>

<!--Branch: list-->
   <xsl:template name="out:list">
      <xsl:call-template name="in:list"/>
   </xsl:template>
   <xsl:template name="in:list">
      <body>
         <p>Here is a list of the inputs:</p>
         <ul>
            <xsl:call-template name="out:item"/>
         </ul>
      </body>
   </xsl:template>

Note in the above how the result tree will be constructed by out:list calling in:list should the importing stylesheet have nothing to say about the processing of out:list.

Should the importing stylesheet have something to say, it can say it by overriding the out:list named template and then continue processing by calling the in:list named template, as in the following:

<xsl:import href="test-frag.xsl"/>

<!--set the context for the entire list to be "/tests"-->

<xsl:template name="out:list">
  <xsl:apply-templates select="/tests"/>
</xsl:template>
<xsl:template match="/tests">
  <xsl:call-template name="in:list"/>
</xsl:template>

Note that the above example importing stylesheet is using the "push" style of writing XSLT stylesheets as this modularity provides for even further specialization by other stylesheets importing this stylesheet. The "pull" style of writing XSLT stylesheets would work equally as well.

The above excerpts are part of the complete example in Section 5, “ Illustrative complete test”.

4.  Vocabulary

ResultXSLT is a vocabulary of annotation attributes and an element used to decorate a prototypical result instance of an arbitrary XML vocabulary. This environment will validate the use of these annotations as expected on the input prototypical instance and then will accommodate the annotations in the synthesis of the output XSLT stylesheet fragment.

The following documentary conventions are used for namespace prefixes. Of course namespace prefixes are entirely arbitrary and you are not obliged to use the prefixes used in the following summary of namespace URI strings:

  • xmlns:x="http://www.CraneSoftwrights.com/ns/result"

  • xmlns:xa="http://www.CraneSoftwrights.com/ns/result/attr"

  • xmlns:xap="http://www.CraneSoftwrights.com/ns/result/attrp"

The vocabulary is normatively described by the supplied result.rnc schema using the ISO/IEC 19757-2 compact syntax also called RELAX-NG.

4.1.  Action annotation attributes

These attributes dictate the fragmentation of the synthesized stylesheet fragment. These are required attributes to make the result fragment useful to an importing stylesheet.

  • x:branch="template-name"

    • create an out/in branch pair of the given name in the output stylesheet fragment with the top element of the "in" template rule being the element on which this attribute is used

  • x:branch-children="template-name"

    • create an out/in branch pair of the given name in the output stylesheet fragment with the top constructs of the "in" template rule being the child constructs of the element on which this attribute is used

4.2.  Annotation namespace declarations

These required attributes on the document element of the input declare the namespaces to be used for the importing stylesheet to interact with the synthesized stylesheet fragment.

  • x:out-prefix="namespace-prefix"

    • declare the prefix of an in-scope namespace URI string to be used in the output stylesheet fragment for the prefix of the "out" template rule in an out/in branch pair

  • x:in-prefix="namespace-prefix"

    • declare the prefix of an in-scope namespace URI string to be used in the output stylesheet fragment for the prefix of the "in" template rule in an out/in branch pair

4.3.  Attribute annotation namespaces

These two namespaces are used to override any attributes used in the result that need to be replaced with XSLT expressions.

  • xa:attribute-name="expression"

    • this declares the expression to use in the output stylesheet fragment in place of the attribute of the same name; when not accompanied by xap:attribute-name= this adds or overrides an attribute in no namespace

  • xap:attribute-name="namespace-prefix"

    • this is used in combination with xa:attribute-name of the same local-name part so as to add or override an attribute of the full name namespace-prefix:attribute-name= in the output stylesheet

4.4.  Housekeeping annotation attributes

These optional attributes do not affect the facilities of the synthesized fragment, but do serve an aesthetic purpose of organizing the fragmentation found in the synthesized fragment.

  • x:ignore="template-name"

    • this signals the element does not have a role in the output stylesheet and is to be ignored; the named template rule must exist (ostensibly to be the template rule that accommodates this result tree content) so as to assert this particular annotation was not inadvertently used

  • x:sort="numeric-value"

    • top-level stylesheet template rules and declarations are ordered in the output fragment in numerical order of this annotation attribute; an absent annotation indicates a numeric value of zero; annotated constructs of equal sort value are sorted in document order of the construct found in the input

  • x:comment="string"

    • this adds a top-level comment to the output before the top-level constructs created by the annotated element

  • x:comment-children="string"

    • this adds a top-level comment to the output before the top-level constructs created for the children of the annotated element

4.5.  Action element

This optional element is used to help in the organization of the synthesized fragment when the author wishes to expose global variables to be overridden or accessed from the importing stylesheet.

  • <x:decl name="qname" value="expression"/>

    • this adds a top-level variable declaration to the output using the given qualified name and XPath expression; note the attributes are not in any namespace so are not prefixed

    • this element may include x:comment= and x:sort= annotations provided those annotations are explicitly prefixed in the ResultXSLT namespace

5.  Illustrative complete test

The following is a transcription of a session creating an importable stylesheet fragment for the creation of an HTML result tree. Note how the prototypical result has four lines for illustrative purposes but the final result has all five tests from each of the input XML files.

To illustrate the independence of the one imported stylesheet fragment on different source vocabularies, a second data set using different element types is processed and illustrated.

T:\resultXSLT>rem Consider the input data that is to be processed by the stylesheet 

T:\resultXSLT>type test.xml 
<?xml version="1.0" encoding="iso-8859-1"?>
<tests>
  <test>First test source</test>
  <test>Second test source</test>
  <test>Third test source</test>
  <test>Fourth test source</test>
  <test>Fifth test source</test>
</tests>
T:\resultXSLT>rem Annotate a prototypical result that illustrates the desired output 

T:\resultXSLT>type testout.xhtml 
<html xmlns:x="http://www.CraneSoftwrights.com/ns/result"
      x:out-prefix="out"
      x:in-prefix="in"
      xmlns:out="urn:ss-URI:out"
      xmlns:in="urn:ss-URI:in">
  <head>
    <title>A test of ResultXSLT(TM)</title>
  </head>
  <body x:branch="list">
    <p>Here is a list of the inputs:</p>
    <ul>
      <li x:branch="item">
        <i x:branch-children="item-content">
          test line 1
        </i>
      </li>
      <li x:ignore="item"><i>test line 2</i></li>
      <li x:ignore="item"><i>test line 3</i></li>
      <li x:ignore="item"><i>test line 4</i></li>
    </ul>
  </body>
</html>
T:\resultXSLT>rem Validate the use of the annotations 

T:\resultXSLT>jing -c result.rnc testout.xhtml 

T:\resultXSLT>rem Synthesize the importable stylesheet fragment 

T:\resultXSLT>saxon -o test-frag.xsl testout.xhtml result.xsl 

T:\resultXSLT>rem Examine the result fragment 

T:\resultXSLT>type test-frag.xsl 
<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xst="http://www.w3.org/1999/XSL/Transform" xmlns:out="urn:ss-URI:out" xmlns:in="urn:ss-URI:in" version="1.0" exclude-result-prefixes="out in">


<!--Root: default processing for the root node-->
   <xsl:template match="/">
      <html>
         <head>
            <title>A test of ResultXSLT(TM)</title>
         </head>
         <xsl:call-template name="out:list"/>
      </html>
   </xsl:template>

<!--Branch: list-->
   <xsl:template name="out:list">
      <xsl:call-template name="in:list"/>
   </xsl:template>
   <xsl:template name="in:list">
      <body>
         <p>Here is a list of the inputs:</p>
         <ul>
            <xsl:call-template name="out:item"/>
         </ul>
      </body>
   </xsl:template>

<!--Branch: item-->
   <xsl:template name="out:item">
      <xsl:call-template name="in:item"/>
   </xsl:template>
   <xsl:template name="in:item">
      <li>
         <i>
            <xsl:call-template name="out:item-content"/>
         </i>
      </li>
   </xsl:template>

<!--Branch: item-content-->
   <xsl:template name="out:item-content">
      <xsl:call-template name="in:item-content"/>
   </xsl:template>
   <xsl:template name="in:item-content">
          test line 1
        </xsl:template>
</xsl:stylesheet>
T:\resultXSLT>rem Write a stylesheet for access to the source node tree 

T:\resultXSLT>type test.xsl 
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:out="urn:ss-URI:out" 
  xmlns:in="urn:ss-URI:in" 
  exclude-result-prefixes="out in"
  version="1.0">

<xsl:import href="test-frag.xsl"/>

<!--set the context for the entire list to be "/tests"-->

<xsl:template name="out:list">
  <xsl:apply-templates select="/tests"/>
</xsl:template>
<xsl:template match="/tests">
  <xsl:call-template name="in:list"/>
</xsl:template>

<!--process each of the tests in the given set-->

<xsl:template name="out:item">
  <xsl:apply-templates select="test"/>
</xsl:template>
<xsl:template match="test">
  <xsl:call-template name="in:item"/>
</xsl:template>

<!--process the contents of a test-->
<xsl:template name="out:item-content">
  <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>
T:\resultXSLT>rem Process the input with the authored stylesheet 

T:\resultXSLT>saxon -o test.html test.xml test.xsl 

T:\resultXSLT>rem Get the desired result 

T:\resultXSLT>type test.html 
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   
      <title>A test of ResultXSLT(TM)</title>
   </head>
   <body>
      <p>Here is a list of the inputs:</p>
      <ul>
         <li><i>First test source</i></li>
         <li><i>Second test source</i></li>
         <li><i>Third test source</i></li>
         <li><i>Fourth test source</i></li>
         <li><i>Fifth test source</i></li>
      </ul>
   </body>
</html>
T:\resultXSLT>rem Consider another set of input data 

T:\resultXSLT>type test2.xml 
<?xml version="1.0" encoding="iso-8859-1"?>
<others>
  <other>First other source</other>
  <other>Second other source</other>
  <other>Third other source</other>
  <other>Fourth other source</other>
  <other>Fifth other source</other>
</others>
T:\resultXSLT>rem Write another stylesheet for access to the different vocabulary 

T:\resultXSLT>type test2.xsl 
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:out="urn:ss-URI:out" 
  xmlns:in="urn:ss-URI:in" 
  exclude-result-prefixes="out in"
  version="1.0">

<xsl:import href="test-frag.xsl"/>

<!--set the context for the entire list to be "/others"-->

<xsl:template name="out:list">
  <xsl:apply-templates select="/others"/>
</xsl:template>
<xsl:template match="/others">
  <xsl:call-template name="in:list"/>
</xsl:template>

<!--process each of the others in the given set-->

<xsl:template name="out:item">
  <xsl:apply-templates select="other"/>
</xsl:template>
<xsl:template match="other">
  <xsl:call-template name="in:item"/>
</xsl:template>

<!--process the contents of an other-->
<xsl:template name="out:item-content">
  <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>
T:\resultXSLT>rem Process the input with the authored stylesheet 

T:\resultXSLT>saxon -o test2.html test2.xml test2.xsl 

T:\resultXSLT>rem Get the desired result 

T:\resultXSLT>type test2.html 
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   
      <title>A test of ResultXSLT(TM)</title>
   </head>
   <body>
      <p>Here is a list of the inputs:</p>
      <ul>
         <li><i>First other source</i></li>
         <li><i>Second other source</i></li>
         <li><i>Third other source</i></li>
         <li><i>Fourth other source</i></li>
         <li><i>Fifth other source</i></li>
      </ul>
   </body>
</html>