« | Home | »

Displaying Lists – Part 2

In my first Displaying Lists post, I described how to use an HTML view to display a list of values formatted using a CSS stylesheet. This time I’ll use an XSL stylesheet to convert the XML data into HTML for display.

The advantage of using XSL over CSS is that you can restructure the incoming XML data in any way you like. For instance, with CSS, you are stuck with the order of XML elements, but with XSL you can re-order them. Additionally, the XSL stylesheet can incorporate additional HTML markup, such as column headings.

Here’s a fairly simple XSL stylesheet that converts the XML into an HTML table, complete with headings.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"/>

  <xsl:template match="doc">
        <html>
        <head>
            <title><xsl:value-of select="@name"/></title>
            <link rel="stylesheet" type="text/css2" href="foo.css"/>
        </head>
        <body>
          <table width="100%" border="0" cellpadding="0" cellspacing="0">
            <tr>
              <td>
                <table width="100%" border="0" cellspacing="1" cellpadding="0">
                  <tr>
                    <td height="15" width="140" nowrap="yes">
                      <table width="100%" height="15" border="0" cellpadding="0" cellspacing="0">
                        <tr>
                          <td class="tablehead">Name</td>
                        </tr>
                      </table>
                    </td>
                    <td height="15" width="140" nowrap="yes">
                      <table width="100%" height="15" border="0" cellpadding="0" cellspacing="0">
                        <tr>
                          <td class="tablehead">Modification Date</td>
                        </tr>
                      </table>
                    </td>
                    <td height="15" nowrap="yes">
                      <table width="100%" height="15" border="0" cellpadding="0" cellspacing="0">
                        <tr>
                          <td class="tablehead">Path</td>
                        </tr>
                      </table>
                    </td>
                  </tr>

                  <xsl:apply-templates/>

                </table>
              </td>
            </tr>
          </table>
        </body>
        </html>

  </xsl:template>

  <xsl:template match="row">

        <xsl:variable name="rowStyle">
            <xsl:choose>
                <xsl:when test='(position() mod 2) = 1'>oddRow</xsl:when>
                <xsl:otherwise>evenRow</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <tr valign="top"><xsl:attribute name='class'><xsl:value-of select='$rowStyle'/></xsl:attribute>
          <td height="14" width="140" class="tabletext">
            <xsl:value-of select="./name"/>
          </td>
          <td height="14" width="140" class="tabletext">
            <xsl:value-of select="./date"/>
          </td>
          <td height="14" width="100%" class="tabletext">
            <xsl:value-of select="./path"/>
          </td>
        </tr>
  </xsl:template>
</xsl:stylesheet>

And here’s the AppleScript code that generates the XML data, and displays it in an HTML view. Its very similar to the CSS example. The key difference is the inclusion of the <?xml-stylesheet type=”text/xsl” href=”foo.xsl”?> directive in the XML data which directs the HTML view to apply the foo.xsl stylesheet to the data before displaying it.

on didInvokeListFinderFiles(theObject)
    local rsrcsFolder, theNames, theURLs, theDates, theXML

    set rsrcsFolder to POSIX path of (get my application's resources folder)

    try
        --  Generate XML listing the files in the top Finder window
        tell application "Finder" to ¬
            set {theNames, theURLs, theDates} to {name, URL, modification date} of items of first window

        set theXML to {"<?xml version="1.0"?>"}
        set end of theXML to "<?xml-stylesheet type="text/xsl" href="foo.xsl"?>" -- associated a XSL stylesheet with this XML document
        set end of theXML to "<doc>"
        repeat with i from 1 to length of theNames
            set end of theXML to "  <row>"
            set end of theXML to "    <name>" & (item i of theNames) & "</name>"
            set end of theXML to "    <path>" & (item i of theURLs) & "</path>"
            set end of theXML to "    <date>" & (item i of theDates) & "</date>"
            set end of theXML to "  </row>"
        end repeat
        set end of theXML to "</doc>"

        --  Convert the list of strings we have accumulated into one long string that we can display
        set AppleScript's text item delimiters to {return}
        set theXML to theXML as string

        --  A this point we end up with an XML document looking something like this:
        --
        --  <?xml version="1.0"?>
        --  <?xml-stylesheet type="text/xsl" href="foo.xsl"?>
        --  <doc>
        --    <row>
        --      <name>AbstractConnection.h</name>
        --      <path>file://localhost/Users/mall/Desktop/connection/trunk/AbstractConnection.h</path>
        --      <date>Friday, July 13, 2007 4:59:01 PM</date>
        --    </row>
        --    <row>
        --      <name>AbstractConnection.m</name>
        --      <path>file://localhost/Users/mall/Desktop/connection/trunk/AbstractConnection.m</path>
        --      <date>Friday, July 13, 2007 4:59:01 PM</date>
        --    </row>
        --    ...
        --  </doc>

        --  Display the XML in an HTML view using an XSL stylesheet to make it look like a nice pretty table.
        tell my htmlView
            set value MIME type to "text/xml" -- makes the HTML view treat the string as XML rather then HTML
            set value base URL to (path to resource "foo.xsl") -- tells the HTML view where the resources are (stylesheets, CSS & gifs)
            set value to theXML -- apply the XSL stylesheet and display the resulting HTML
        end tell
    on error errMsg
        display alert "No Finder Window" message "Please open a Finder window to list." buttons "OK" over my window
    end try
end didInvokeListFinderFiles

When you put all this together in FaceSpan, here’s what it looks like:

xsl.jpg

Display XML (XSL) Example Project


About this entry