[xsl] xslt style

Subject: [xsl] xslt style
From: S Woodside <sbwoodside@xxxxxxxxx>
Date: Fri, 10 Jan 2003 02:38:00 -0500
On Thursday, January 09, 2003 5:51 PM, Jeni Tennison wrote:

But to answer your more general question, you're correct that in
unextended XSLT 1.0 you have to call templates to perform functions
and that sometimes this can lead to verbose and ungainly code.
However, most XSLT processors have a mechanism for defining extension
functions. Several support EXSLT's func:function/func:result elements,
which enable you to do:


Correct me if I'm wrong, or restarting an ancient debate, but it strikes me that using XSLT in this way is basically "Wrong" or a Bad Thing. I've found that usually there is a fairly simple way to avoid procedural techniques if I conceptualize the program as being the XML data, and think of it as the data making calls on the XSLT. In other words, in writing XSLT I'm basically writing functions that are called by the data, as the processor walks the tree. As far as XSLT being very verbose, I haven't really found that to be true yet either.


Perhaps you've covered this already in your book (I haven't read any of the XSLT books). But in reading XSLT code (not here, but in open source projects) I often am surprised. I've attached my latest code for transforming RNG -> HTML forms to the bottom, just in case anyone is interested. It's a work in process, not even alpha. I'm including it just as an illustration of how I'm using XSLT right now. (It assumes that all RNG refs have been expanded fully (i have another XSLT to do that) and that the RNG begins with a plain <grammar> tag.)

simon


<?xml version="1.0"?>


<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  version="1.0">

  <xsl:strip-space elements="*" />
  <xsl:output omit-xml-declaration = "yes"/>



  <xsl:template match="grammar">
    <div class="form">
      <h1>A Form</h1>
        <p>Here's a form for you. It's based on an RNG grammar.</p>
        <form action="form.html" method="GET">
            <xsl:apply-templates/>
          <button type="reset">Reset</button>
          <button type="submit">Submit</button>
        </form>
        <p>That's the end of the form.</p>
    </div> <!--form-->
  </xsl:template>

  <xsl:template match="start">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="choice">
      Choice:
      <xsl:call-template name="simpleRecurse"/>
  </xsl:template>

  <xsl:template match="value">
      <xsl:call-template name="radio"/>
      Value could be <b><xsl:value-of select="."/></b>
  </xsl:template>

  <xsl:template match="group">
      Group:
      <xsl:call-template name="simpleRecurse"/>
  </xsl:template>

  <xsl:template match="optional">
      <input type="checkbox">
        <xsl:attribute name="name">
          <xsl:call-template name="namesAttrsOfAncestors"/>
          <xsl:call-template name="nameAttrOfDescendant"/>
        </xsl:attribute>
      </input>
      <xsl:call-template name="namesAttrsOfAncestors"/>
      <xsl:call-template name="nameAttrOfDescendant"/>
      [
      <xsl:call-template name="simpleRecurse"/>
      ]
  </xsl:template>

  <xsl:template match="zeroOrMore">
      Zero or More:
      <xsl:call-template name="simpleRecurse"/>
  </xsl:template>

  <xsl:template match="oneOrMore">
      One or More:
      <xsl:call-template name="simpleRecurse"/>
  </xsl:template>

  <xsl:template match="element">
      <xsl:choose>
        <xsl:when test="not(./*)"> <!--no children--><!--or ./empty-->
          <ul><li>
              <xsl:call-template name="labelTemplate"/>
              <xsl:call-template name="inputTemplate"/>
          </li></ul>
        </xsl:when>
        <xsl:otherwise>
          <b><xsl:call-template name="namesAttrsOfAncestors"/></b>
          <xsl:call-template name="simpleRecurse"/>
        </xsl:otherwise>
      </xsl:choose>
  </xsl:template>

  <xsl:template match="attribute">
      <xsl:choose>
        <xsl:when test="not(./*) or ./empty"> <!--no children-->
          <xsl:call-template name="labelTemplate"/>
          <xsl:call-template name="inputTemplate"/>
        </xsl:when>
        <xsl:otherwise>
          <b><xsl:call-template name="namesAttrsOfAncestors"/></b>
          <xsl:call-template name="simpleRecurse"/>
        </xsl:otherwise>
      </xsl:choose> ((Attribute))
  </xsl:template>


<xsl:template match="text"> <!--Text:--> <!--[[xsl:call-template name="labelTemplate"/]]--> <xsl:call-template name="inputTemplate"/> (text) <xsl:call-template name="simpleRecurse"/> </xsl:template>

  <xsl:template match="list">
      List:
      <xsl:call-template name="simpleRecurse"/>
  </xsl:template>

  <xsl:template match="data">
      <xsl:call-template name="labelTemplate"/>
      <xsl:call-template name="listInput"/>
      (<xsl:value-of select="@type"/>)
      <!--should check for param children-->
  </xsl:template>


<!--******************************--> <!--Named templates-->

<xsl:template name="nameAttrOfAncestor">
<xsl:value-of
select="ancestor-or-self::*[self::element or self::attribute][@name][1]/@name"/>
</xsl:template>


<xsl:template name="nameAttrOfDescendant">
<xsl:value-of
select="descendant-or-self::*[self::element or self::attribute][@name][1]/@name"/>
</xsl:template>


<xsl:template name="namesAttrsOfAncestors">
<xsl:for-each
select="ancestor-or-self::*[self::element or self::attribute][@name]/@name">
<xsl:value-of select="."/><xsl:text>.</xsl:text>
</xsl:for-each>
</xsl:template>


  <xsl:template name="simpleRecurse">
    <br />
      <xsl:apply-templates/>
    <br />
  </xsl:template>


<xsl:template name="radio"> <input type="radio"> <xsl:attribute name="name"> <xsl:call-template name="namesAttrsOfAncestors"/> </xsl:attribute> <xsl:attribute name="value"> <xsl:value-of select="."/> </xsl:attribute> </input> </xsl:template>


<xsl:template name="listInput"> <input> <xsl:if test="../choice"> <xsl:attribute name="type">radio</xsl:attribute> <xsl:attribute name="name"> <xsl:call-template name="namesAttrsOfAncestors"/> </xsl:attribute> </xsl:if> <xsl:attribute name="id"> <xsl:call-template name="namesAttrsOfAncestors"/> </xsl:attribute> <xsl:attribute name="value"> <xsl:call-template name="namesAttrsOfAncestors"/> </xsl:attribute> </input> </xsl:template>


<xsl:template name="labelTemplate"> <label> <xsl:attribute name="for"> <xsl:call-template name="namesAttrsOfAncestors"/> </xsl:attribute> <b> <xsl:call-template name="namesAttrsOfAncestors"/> </b> </label> </xsl:template>

  <xsl:template name="inputTemplate">
    <input>
      <xsl:attribute name="name">
        <xsl:call-template name="namesAttrsOfAncestors"/>
      </xsl:attribute>
      <xsl:attribute name="value">
        <xsl:call-template name="namesAttrsOfAncestors"/>
      </xsl:attribute>
    </input>
  </xsl:template>

  <xsl:template match="define">
    [Define:
      <b><xsl:value-of select="@name"/></b>]
  </xsl:template>

</xsl:stylesheet>



---
www.simonwoodside.com


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread