JavaScript Editor Free JavaScript Editor     JavaScript Debugger 




Main Page

Previous Page
Next Page

12.3. Generic XSLT

Whenever I'm creating an XSL style sheet, unless I'm very, very careful, my style sheets are basically a one-trick pony. Yeah, they do that one trick well, but as I said before, I'm paid by the page, not by the line. Maybe this is the reason the style sheets that I create arehmm, how to put it nicely?weird. Yes, that's the word, weird.

It isn't that they don't workthey work perfectly well. It is more along the lines that I use a lot of relative positioning. Although this approach might seem somewhat dangerous, there are several ways to decrease the danger to tolerable levels. More simply put, take cautions to prevent the style sheets from blowing up and taking the web page out with them. One of these methods is to always make sure that the XML document has the same basic structure, /root/row/node. This makes it far less likely that you will encounter any surprises.

Remember back to Chapter 9, "XPath," to the brief introduction to XPath with all the slashes and asterisks? Well, the asterisks are wildcards, used when the node name is unknown. This means that /*/*/* is the equivalent to /root/row/nodeat least, when we want all the nodes that are the second descendant of the root node.

12.3.1. Forms

As long as the structure of the XML document is known, it isn't very difficult to create generic XSL style sheets. Knowing the names of the individual nodes isn't important, either, although, for the extremely lazy, like myself, the names can be important when creating either labels or column headers. To show what I mean, it is necessary to introduce two XSLT functions.

The first of these functions is the name function. It provides the name of the node passed, which, in these cases, is the context node ".". It returns the actual node name, so if the node name is item_price, then item_price is returned. Yes, I am aware that a label or header with item_price isn't much better than no label at all, which is where the second function, translate, comes in.

The translate function, well, translates. It replaces one character with another, so instead of having a label or a header of item_price, it can be ITEM PRICE. For me, the latter is a lot more like what I expect when visiting a website. Accepting three parametersthe source string, the from string, and the to stringit returns a string consisting of one-for-one replacements of characters.

I should cover a couple things before we use the translate function. The first of these is that in instances when the from string doesn't contain a particular character, that character is copied unchanged. The second thing is that it is a good idea to verify that characters in the from string and characters in the to string are in the same position in their respective strings. Or, more simply stated, using a from string of qwerty and a to string of wertyu will result in a Caesar Cipher. And although a Caesar Cipher might have been state-of-theart in 40 B.C., I'm reasonably sure that it isn't the result that you've hoped for.

With that out of the way, let's take a look at Listing 12-8, which is an XSL style sheet that creates a basic form.

Listing 12-8. Generic XSL Style Sheet to Produce an HTML Table


<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" indent="yes" media-type="text/html"/>

      <xsl:template match="/">

            <xsl:element name="table">
                  <xsl:apply-templates select="/*/*/*" />
            </xsl:element>

      </xsl:template>

      <xsl:template match="*">

            <xsl:element name="tr">
                  <xsl:element name="td">
                        <xsl:value-of
select="translate(name(.),'qwertyuiopasdfghjklzxcvbnm_','QWERTYUIOPASDFGHJ
KLZXCVBNM ')" />
                  </xsl:element>
                  <xsl:element name="td">
                        <xsl:element name="input">
                              <xsl:attribute
name="type">text</xsl:attribute>
                              <xsl:attribute name="name">
                                    <xsl:value-of select="name(.)" />
                              </xsl:attribute>
                              <xsl:attribute name="value">
                                    <xsl:value-of select="." />
                              </xsl:attribute>
                        </xsl:element>
                  </xsl:element>
            </xsl:element>

      </xsl:template>

</xsl:stylesheet>

This is nothing fancy, but it is a proof of concept that can be taken further to show that it is, in fact, possible to create a generic XSL style sheet that produces HTML forms. Although it is rather simpleprimitive, evenit is easy to imagine some possibilities, such as specifying input types via parameters.

12.3.2. Tabular

Applying a generic XSL style sheet to tabular information isn't very different from applying it to create a form. Really only a couple differences arise when working with tabular information instead of a form. The first difference is that, instead of labels at the side, they're column headers on the top. All that is required to do this is to create two templates; the first deals with creating a table row, and the second creates a table header. Other than that, the only real difference is the addition of a predicate, [1], to ensure that the header is created only once. We then have an XSL style sheet that looks like the one in Listing 12-9.

Listing 12-9. Generic XSL Style Sheet to Produce an HTML Table with Headers Based upon the Node Name


<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" indent="yes" media-type="text/html"/>

      <xsl:template match="/">
            <xsl:element name="table">
                  <xsl:apply-templates select="/*/*[1]" mode="header" />
                  <xsl:apply-templates select="/*/*" mode="row" />
            </xsl:element>
      </xsl:template>

      <xsl:template match="*" mode="header">
            <xsl:element name="tr">
                  <xsl:apply-templates select="./*" mode="column" />
            </xsl:element>
      </xsl:template>

      <xsl:template match="*" mode="row">
            <xsl:element name="tr">
                  <xsl:apply-templates select="./*" mode="node" />
            </xsl:element>
      </xsl:template>

      <xsl:template match="*" mode="column">
            <xsl:element name="th">
                  <xsl:value-of
select="translate(name(.),'qwertyuiopasdfghjklzxcvbnm_','QWERTYUIOPASDFGHJ
KLZXCVBNM ')" />
            </xsl:element>
      </xsl:template>

      <xsl:template match="*" mode="node">
            <xsl:element name="td">
                  <xsl:value-of select="." />
            </xsl:element>
      </xsl:template>

</xsl:stylesheet>

Of course, the examples shown here are rather simple, and there are a number of ways to improve them. One of these ways to dress up the generic style sheets is to write the header template with xsl:when to output more meaningful headers. Another possibility is to use Cascading Style Sheets to give a more polished look and feel. Finally, right-justifying numbers wouldn't hurt.


Previous Page
Next Page




JavaScript Editor Free JavaScript Editor     JavaScript Debugger


©