Now: Tutorial for Web and Software Design > XML > Styles > XML Content
> XSLT Recipes for Interacting with XML Data [Bookmark it]
XSLT Recipes for Interacting with XML Data
XSLT Recipes for Interacting with XML Data

XSLT Recipes for Interacting with XML Data

by Jon Udell
August 13, 2003

In last month's column, "The Document is the Database", I sketched out an approach to building a web-based application backed by pure XML (and as a matter of fact, XHTML) data. I've continued to develop the idea, and this month I'll explore some of the XSLT-related recipes that have emerged.

Oracle's Sandeepan Banerjee, director of product management for Oracle Server Technologies, made a fascinating comment when I interviewed him recently. "It's possible," he said, "that developers will want to stay within an XML abstraction for all their data sources". I suppose my continuing (some might say obsessive) experimentation with XPath and XSLT is an effort to find out what that would be like.

It's true that these technologies are still somewhat primitive and rough around the edges. Some argue that we've got to leapfrog over them to XQuery or to some XML-aware programming language in order to colonize the world of XML data. But it seems to me that we can't know where we need to go until we fully understand where we are. And there's no better reality check than a practical application. In order to set the stage for this month's installment, let's review the XHTML data formats for an evolving application that gathers and displays information about conference speakers and sessions. Here's the format of the speakers file:

<?xml version="1.0"?>
<body>
<style>
.speaker { margin-bottom: 10px }
.speakerName { font-weight: bold }
.speakerTitle { font-style: italic }
</style>
<speakers>
<div class="speaker" email="jon_udell@infoworld.com">
<div class="speakerName">
Jon Udell
</div>
<div class="speakerTitle">
lead analyst, InfoWorld
</div>
<div class="speakerBio">
<span class="bio"><p>See http://udell.roninhouse.com/bio.html</p></span>
</div>
</div>
</speakers>
</body>
Figure 1. The speakers "database"

And here's the format of the sessions file:

<?xml version="1.0"?>
<body>
<style>
.session { margin-bottom: 10px }
.sessionTitle { font-weight: bold }
.sessionTrack { font-style: italic }
</style>
<sessions>
<div class="session" id="01" day="3" start="10:30" end="12:00">
<div class="sessionTitle">Grade-school CMS lessons</div>
<div class="sessionTrack">general</div>
<div class="speakerEmail">jon_udell@infoworld.com</div>
<div class="speakerEmail">paul@zope-europe.org</div>
<div class="sessionDescription">
<span class="description"><p>Paul's introduction, Jon's keynote</p></span></div>
</div>
</sessions>
</body>
Figure 2. The sessions "database"     

More from Jon Udell

The Beauty of REST

Lightweight XML Search Servers, Part 2

Lightweight XML Search Servers

The Social Life of XML

Interactive Microcontent

Note that both of these formats suffer from a syndrome that might be called "div-itis". I've chosen to maintain a browser-friendly XHTML format to ensure that the raw data files are always viewable without special transformation. In fact, that was never completely true: the files contain some fictitious attributes (e.g. 'id' and 'start' in the speakers file) that aren't kosher in HTML, and don't display in the browser.

On balance, I still think it's handy to be able to browse the data file directly. But the techniques I'm exploring in the last column and this one don't require use of XHTML. Indeed, they'll work more easily when element names, rather than attributes, carry the semantics.

It's crucial to be able to visualize data. As browsers are increasingly able to apply CSS stylesheets to arbitrary XML, the XHTML constraint becomes less important. The Microsoft browser has been able to do CSS-based rendering of XML for a long time. Now Mozilla can too. Safari doesn't, yet, but I'll be surprised if it doesn't gain that feature soon. So while I'm sticking with XHTML for now, that may be a transient thing. Of more general interest are the ways in which XPath and XSLT can make XML data (of any flavor) interactive.

An XSLT-driven form generator

Here's a form, driven by both of the data sources, that's used to update information for a session:

Screen shot.
Figure 3. The session update form.

The script that builds the form is based on the Zope XSLT wrapper we explored last month. It accepts one argument: the id of a session. That id is used to create a series of form widgets of different types, drawing on different data sources:

nametypedata source(s) sessionDaySELECTcurrent session element and ZODB property sessionTitleINPUTcurrent session element sessionTrackSELECTcurrent session element and ZODB property sessionStartSELECTcurrent session element and ZODB property sessionEndSELECTcurrent session element and ZODB property sessionSpeakersSELECTcurrent session element and related speaker elements sessionDescriptionTEXTAREAcurrent session element
Figure 3. Widget types and data sources for the session update form.

Two of these widgets -- sessionTitle and sessionDescription -- are easily made using XPath expressions to pick out the corresponding data from the sessions file, as shown in bold Figure 5. But the rest require more spelunking.

datafile = 'sessions.html'
id = context.REQUEST.form['id']

xsl = '''%s

<xsl:template match="//*[@id='%s']">
<form method="post" action="updateSession">
<div><input type="hidden" name="sessionId" value="{@id}"/></div>
<div>sessionDay: <select name="sessionDay">
%s
</select></div>
<div>sessionTitle: <input size="70" 
      name="sessionTitle" value="{*[@class='sessionTitle']}" /> </div>
<div>sessionTrack: <select name="sessionTrack">
%s
</select></div>
<div>sessionStart: <select name="sessionStart">
%s
</select></div>
<div>sessionEnd: <select name="sessionEnd">
%s
</select></div>
<div>sessionSpeakers: %s </div>
<div>sessionDescription: <textarea rows="10" cols="70" name="sessionDescription">
<xsl:copy-of select="*[@class='sessionDescription']/*" />
</textarea></div>
<div><input value="updateSession" type="submit"/></div>
</form>
</xsl:template>

<xsl:template match="text()" />

</xsl:stylesheet>'''

xsl = xsl % (context.xsltPreamble(), id,
             context.makeList('sessionDays', "@day"),
             context.makeList('sessionTracks', "*[@class='sessionTrack']"),
             context.timesAsSelectWidget ( context.sessionsAsDict()[id]['start'] ),
             context.timesAsSelectWidget ( context.sessionsAsDict()[id]['end'] ), 
             context.speakersAsSelectWidget(id),
             )

result = context.xslt(xsl, datafile)

result = context.adjustSelectWidget ( result )
Figure 5.

Because this is a Zope application, the SELECT widgets for sessionDay and sessionTrack can use lists of values stored as ZODB properties. That means an authorized administrator -- a non-programmer, presumably -- can edit the lists using Zope's through-the-web management interface.

[Bookmark][Print] [Close][To Top]
  • Prev Article-XML:

  • Next Article-XML:
  • Related Materias
    Appreciating Libxslt
    Comparing CSS and XSL: A R
    Printing XML: Why CSS Is B
    Converting XML  to RDF
    From XML to SMIL
    Opening Open Formats with 
    XSLT Reflection
    EXSLT for MSXML
    Transclusion with XSLT 2.0
    Shortening XSLT Stylesheet
    Topics
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Graphic Design Tutorial
     

    Coreldraw Tutorial

      Illustrator Tutorial
      3D Graphics Articles
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial&Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial&Articles
     

    XML Style Tutorial

      AJAX Tutorial
      XML Mobile
    Flash Tutorial&Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial&Articles
     

    Linux Tutorial

      Symbian Tutorial
      MacOS Tutorial