Home

People

Publications

Presentations

Downloads

Actors


Areas of work


Schedule

Study groups

Links


Tasks

NceXSL version 1.2.1 of 4-Sep-2002

NiceXSL defines a conventional textual representation of XSL that is more amenable to conventional editing. XML overheads are much reduced and abbreviated syntaxes are provided for all XSLT 2.0 constructs.

NiceXSL is supported by translators to and from standard XSL. (The translation from XSL is of course written in XSL).

Example

The compatibility example from Section 3.7 of the XSLT 2.0 working draft:

<xsl:stylesheet version="17.0"
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:choose>
      <xsl:when test="system-property('xsl:version') >= 17.0">
        <xsl:exciting-new-17.0-feature/>
      </xsl:when>
      <xsl:otherwise>
        <html>
          <head>
            <title>XSLT 17.0 required</title>
          </head>
         <body>
          <p>Sorry, this stylesheet requires XSLT 17.0.</p>
          </body>
        </html>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

can be expressed using NiceXSL as

stylesheet @version="17.0" {
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  match (/) {
    if (system-property('xsl:version') >= 17.0)
      <xsl:exciting-new-17.0-feature>
    else {
      <html
        <head
          <title "XSLT 17.0 required">
        >
        <body
          <p "Sorry, this stylesheet requires XSLT 17.0.">
        >
      >
    }
  }
}

Abbreviated XML Syntax

NiceXSL eliminates the XML prohibitions on lexical nesting and makes the repetitive end-of construct keywords optional. A NiceXSL construct that starts with < therefore ends at the matching >. NiceXSL allows XML tag names to be re specified at the end of a construct, and this may be used for documentation or diagnosis of deep hierarchies.

The XML <a><b/></a> must therefore be rewritten in NiceXSL, to use hierarchical nesting as <a <b> >. Use of additional construct closers as in <a <b/> /> or <a <b /b> /a> is optional.

Text nodes must be written in quotes, so the XML <a>some text</a> must be written as <a "some text"> or <a 'some text'>

The attribute name in an attribute node should be prefixed by an @, so the XML <a key="word"/> should be written as <a @key="word">. Parentheses, rather than quotes should be used when the argument is an XPath expression: <a @key=(word)>. [Omission of the @ prefix is a deprecated syntax that is ambiguous when the attribute name corresponds to an XSL construct Use of quotes around the attribute name is another deprecated syntax.]

The standard XML &amp; &gt; &lt; &quot; &#decimal; and &#xhexadecimal; policies for character references in strings are supported; A new line should therefore be entered as &#xA; (not as \n).

A group of child nodes may be enclosed in braces to assist structuring: <a { @b = "c" <d> } >.

XML comments can be provided using the standard <!-- introducer and --> terminator. Alternatively purely local comments can be placed at the end of a line following --. Local comments are not translated to XSL.

Abbreviated XSL Syntax

Abbreviated non <> syntaxes are provided using { }'s and ; in a way that should be familiar to C or Java programmers. Abbreviated XSL constructs of the form such as <xsl:otherwise> may be written otherwise ... ; when there is at most one child abbreviated XSL construct, or otherwise ... { ... } when there are any number of child abbreviated XSL constructs. XML nodes (elements, attributes, namespaces, text, comments, processing-instructions) are not abbreviated XSL constructs and so may be placed as required in either of the ellipsis positions. Braced groups of XML nodes (and abbreviated XSL constructs) may only be placed within braces.

Primary XPath attribute

The introductory name for XSL constructs with a mandatory primary attribute, such as select or test, may be omitted immecditaely preceding the parenthesised XPath expression.

<xsl:value-of select="concat(‘prefix’,$suffix)"/> 

may be abbreviated to

value-of (concat(‘prefix’,$suffix)); 

[Use of quotes rather than parentheses is deprecated and suppresses validation of XPath syntax.]

Primary non-XPath attribute

The introductory name for other XSL constructs with a mandatory primary attribute such as elementshref, or method may also be omitted. No punctuation is needed for the mandaotory argument.

<xsl:include href="b"/> 

may be abbreviated to

include "b"; 
<xsl:output method="text"/> 

may be abbreviated to

output text ; 
<xsl:preserve-space elements="title nested:*"/> 

may be abbreviated to

preserve-space title,nested:*; 

Secondary attributes

Some constructs have a secondary attribute which may be specified with an = prefix:

<xsl:namespace-alias stylesheet-prefix="a" result-prefix="b"/> 

may be abbreviated to

namespace-alias "a" = "b" ... ; 
<xsl:variable name="a" select="b"/>

may be abbreviated to

variable a = (b); 

Other attributes

Only the primary (and secondary) attribute can be supplied without a keyword; other attributes are specified normally: value-of (name) @disable-output-escaping="no";

Parameter lists

Parameter lists are specified in parentheses following the template function name, template match expression, or the stylesheet keyword.

<xsl:call-template name="yyy" ... > 
  <xsl:with-param name="a" select="b"/> 
  <xsl:with-param name="c">...</xsl:with-param> 
  ... 
</xsl:call-template> 

may be abbreviated to

call yyy(a := b, c := { ... }) ... ; 
<xsl:apply-templates select="yyy" ... > 
  <xsl:with-param name="a" select="b"/> 
  <xsl:with-param name="c">...</xsl:with-param> 
  ... 
</xsl:apply-templates> 

may be abbreviated to

apply-templates (yyy)(a := b, c := { ... }) ... ; 
<xsl:stylesheet ... > 
<xsl:param name="a" select="b"/> 
... 
</xsl:stylesheet> 

may be abbreviated to

stylesheet(a := b, ... ) ... ; 
<xsl:template name="yyy" ... > 
<xsl:param name="a" select="b"/> 
... 
</xsl:template> 

may be abbreviated to

function yyy(a := b, ... ) ... ; 
<xsl:template match="yyy" ... > 
  <xsl:param name="a" select="b"/> 
  ... 
</xsl:template> 

may be abbreviated to

match yyy(a := b, ... ) ... ; 

The case of a template with both a name and match expression may be defined by adding a match attribute to a function or a name attribute to a match:.

match yyy(a := b, ... ) @name="zzz"... ; 

or

function zzz(a := b, ... ) @match=(yyy)... ; 

Within the parenthesized context, it is not necessary to provide additional parentheses around the XPath expression (unless it is a sequence. The use of := rather than the deprecated = is intended to avoid the confusion with the XPath comparison operator. )

if elseif else

The abbreviated form of if is extended to recognise trailing elseif and else clauses. This is equivalent to (and translated to) a choose enclosing when and otherwise clauses, but is a little easier to type, and of course suffers from all the traditional dangling else problems.It is therefore advisable to use braces to ensure that multiple abbreviated XSL constructs are grouped as children of the intended else.

Syntax Summary

The NiceXSL form of XSL syntax is summarised by way of examples in the following tables.

Typewriter font denotes exact text.

Italic font denotes a parametric value.

... denotes an incomplete example.

+ denotes one or more repetitions of the preceding construct.

* denotes zero or more repetitions of the preceding construct

NiceXML Preferred Syntax Summary.

Preferred NiceXSL syntax XML equivalent
-- end-of-line-comment
<!-- multi-line-comment --> <!-- multi-line-comment -->
<key attr* node*> <key attr*> node* </key>
<key attr*> <key attr*/>
<? key processing-instruction ?/> <? key processing-instruction ?/>
@attribute-name attribute-name
@attribute-name="attribute-value" attribute-name="attribute-value"
@attribute-name=(xpath-expression) attribute-name="xpath-expression"
namespace:name="namespace-value" namespace:name="namespace-value"
"multi-line-text" multi-line-text

NiceXSL Preferred Syntax Summary

Preferred NiceXSL syntax XSL equivalent
construct-name attribute*;
<xsl:construct-name ...attribute...*
  /xsl:construct-name>
construct-name attribute* element;
<xsl:construct-name   ...attribute...* 
  ...element... 
</xsl:construct-name>
construct-name attribute* { 
  attribute* element* }
<xsl:construct-name   ...attribute...* 
  ...element...* 
</xsl:construct-name>
analyze-string (select) ... <xsl:analyze-string select="select" ...
apply-imports ... <xsl:apply-imports ...
apply-templates (select) ... <xsl:apply-templates select="select" ...
apply-templates (select)(p1,
  p2 := s2,
  p3 := {...s3...}) ...
<xsl:apply-templates select="select" ... 
  <xsl:with-param name="p1"/> 
  <xsl:with-param name="p2" select="s2"/> 
  <xsl:with-param name="p3"> 
    ... s3 ... 
  </xsl:with-param> 
... 
</xsl:apply-templates>
attribute name ... <xsl:attribute name="name" ...;
attribute name = (select) ...
<xsl:attribute name="name" ...> 
  <xsl:value-of select="select"/> 
</xsl:attribute>
attribute-set name ... <xsl:attribute-set name="name" ...
call name ... <xsl:call-template name="name" ...
call name(p1, p2 := s2,
  p3 := {...s3...}) ...;
<xsl:call-template name="name" ...> 
  <xsl:with-param name="p1"/> 
  <xsl:with-param name="p2" select="s2"/> 
  <xsl:with-param name="p3"> 
    ... s3 ... 
  </xsl:with-param> 
  ... 
</xsl:call-template>
choose ... <xsl:choose ...
comment ... <xsl:comment ...
copy ... <xsl:copy ...
copy-of (select) ... <xsl:copy-of select="select" ...
decimal-format ... <xsl:decimal-format ...
element name ... <xsl:element name="name" ...;
fall-back ... <xsl:fall-back ...
for-each (select) ... <xsl:for-each select="select" ...
for-each-group (select) ... <xsl:for-each-group select="select" ...
function name(p1, p2 := s2,
  p3 := {...s3...}) { 
  ... 
}
<xsl:template name="name"> 
  <xsl:param name="p1"/> 
  <xsl:param name="p2" select="s2"/> 
  <xsl:param name="p3"> 
    ... s3 ... 
  </xsl:param> 
... 
</xsl:template>
function name(p1, p2 := s2,
  p3 := {...s3...}) { 
  ... 
  result = (return-value); 
}
<xsl:function name="name"> 
  <xsl:param name="p1"/> 
  <xsl:param name="p2" select="s2"/> 
  <xsl:param name="p3"> 
    ... s3 ... 
  </xsl:param> 
... 
  <xsl:result select="return-value"/> 
</xsl:function>
if (test) ... <xsl:if test="test" ...
if (test1) ...; 
elseif (test2) ...; 
else ...;
<xsl:choose> 
  <xsl:when test="test1" ... 
  <xsl:when test="test2" ... 
  <xsl:otherwise ... 
</xsl:choose>
import (href) ... <xsl:import href="href" ...
import-schema ... <xsl:import-schema ...
include (href) ... <xsl:include href="href" ...
key name ... <xsl:key name="name" ...
match (match) ... <xsl:template match="match" ...
match (match)(p1, p2 := s2,
  p3 := {...s3...}) ...
<xsl:template match="match" ... 
  <xsl:param name="p1"/> 
  <xsl:param name="p2" select="s2"/> 
  <xsl:param name="p3"> 
    ... s3 ... 
  </xsl:param> 
... 
</xsl:template>
matching-substring ... <xsl:matching-substring ...
message ... <xsl:message ...
namespace name ... <xsl:namespace name="name" ...
namespace-alias stylesheet-prefix
  = result-prefix ...
<xsl:namespace-alias
  stylesheet-prefix="stylesheet-prefix"
  result-prefix="result-prefix" ...
non-matching-substring ... <xsl:non-matching-substring ...
number ... <xsl:number ...
otherwise ... <xsl:otherwise ...
output method ... <xsl:output method="method" ...
preserve-space e1,e2 ... <xsl:preserve-space elements="e1 e2" ...
principal-result-document ... <xsl:principal-result-document ...
processing-instruction name ... <xsl:processing-instruction name="name" ...
result = (select) ... <xsl:result select="select" ...
result-document ... <xsl:result-document ...
sort ... <xsl:sort ...
sort-key name ... <xsl:sort-key name="name" ...
strip-space e1,e2 ... <xsl:strip-space elements="e1 e2" ...
stylesheet ... <xsl:stylesheet ...
stylesheet(p1, p2 := s2,
  p3 := {...s3...}) ... { 
  ... 
}
<xsl:stylesheet ... > 
  <xsl:param name="p1"/> 
  <xsl:param name="p2" select="s2"/> 
  <xsl:param name="p3"> 
    ... s3 ... 
  </xsl:param> 
  ... 
</xsl:stylesheet>
text ... <xsl:text ...
value-of (select) ... <xsl:value-of select="select" ...
variable name ... <xsl:variable name="name" ...
variable name = (select) ... <xsl:variable name="name" select="select" ...
when (test) ... <xsl:when test="test" ...

NiceXSL Alternate Syntax Summary

Prior to NiceXSL version 1.2, it was necessary to provide XPath expressions as unchecked string literals. This syntax remains for compatibility and is deprecated with the exception of the following syntaxes where the quoted string is more intuitive than parentheses

Alternate syntax XSL equivalent
import "href" ...
<xsl:import href="href" ...
include "href" ...
<xsl:include href="href" ...

NiceXSL Deprecated Syntax Summary

Deprecated syntax XSL equivalent
attribute-name="attribute-value" 
"attribute-name"="attribute-value"
attribute-name="attribute-value"
parameter-name="parameter-value" 
"parameter-name"="parameter-value"
parameter-name="parameter-value"

Debugging

[Version 1.1 of NiceXSL used an LL parser and consequently only reported the first error with an unhelpful stack dump. XPath syntax errors were not diagnosed at all, requiring errors reported against XSL line numbers to be manually reinterpreted as errors in the NiceXSL source].

Version 1.2 uses an LALR parser with error recovery for the full XPath syntax. All syntax errors should therefore be diagnosed, leaving only semantic errors to be resolved against the generated XSL.

Construct nesting depth in XSL programs is often greater than that in more conventional languages and experience shows that simple end of construct indicators such as ; or } can get out of step. This is not a problem in XML where the end of construct indicators are verbose. It is also not a problem if you use a syntax sensitive editor. For naive editors NiceXSL allows verbose end of constructs, and clarifying one of two construct ends can rapidly resolve the hierarchy anomaly. Migrating a premature /stylesheet} between function templates is particularly effective at narrowing the problem from the entire source to a single function.

Usage

The forward transformation from NiceXSL to XSL is provided by the example main program in the nicexsl.main class. It may be invoked in the standard distribution as:

java -jar nicexsl_1v2p1.jar input-file.nicexsl output-file.xsl 

The main program is a simple driver that constructs a

nicexsl.lexer
to read from a file stream and invokes the
parse()
function of
nicexsl.parser
to populate a DOM Document, which is then converted to an XML string for output as XSL. Custom applications may therefore embed the NiceXSL parser by copying about 10 lines from the example main program.

The reverse transformation from XSL to NiceXSL is provided by XSL2NiceXSL.xsl. This may be used to convert existing code, or to get examples of the NiceXSL form of constructs.

Bug Reports

Please report bugs, or make other suggestions, to Ed.Willink@uk.thalesgroup.com.

Contact 
©2002-2018 U.C. Regents