Main Points

So we've built our first XSL transform and had the chance to play around with it. Now we'd like to start harnessing it so we can make it do what we want it to do.

Complete Titles List

This page sorted out all the problems that we were having with books in a series from page two.

<h3 id="bookTitle" tabindex="0">Book Title</h3>
<xsl:for-each select="//item/title">
<xsl:sort select="." />
<p><xsl:value-of select="." /></p>
</xsl:for-each>

First, is a complete list of all titles, including books in a series. On page two, we were only able to target references absolutely, e.g. select="/Bibliography/item/title". The result was that any book in a series was missed because it is found on the path select="/Bibliography/item/item/title". Here, we correct the problem using relative references to pick up any book title. All titles follow the item/title pattern, so in this example, we've used the relative "double slash" to indicate a node that falls anywhere, select="//item/title". Now we get every title in the XML document wherever it is.

Book Title

A Body in the Bathhouse

A Dying Light in Corduba

Atlas of World History

Breaking the Maya Code

Byzantium: The Apogee

Byzantium: The Decline and Fall

Byzantium: The Early Centuries

DHTML and CSS Advanced

Flash 8 Accelerated

Flash 8: Graphics, Animation, & Interactivity

Flash 8: Projects for Learning Animation and Interactivity

Gods and Generals

Gone for Soldiers

Hubble: The Mirror on the Universe

Iron Hand of Mars

Last Act in Palmyra

Ode to a Banker

One Virgin Too Many

Paris 1919: Six Months That Changed the World

Poseidon's Gold

Rise to Rebellion

Scandal Takes a Holiday

Shadows in Bronze

Silver Pigs

The Accusers

The Crusades Through Arab Eyes

The Fellowship of the Ring

The Glorious Cause

The Jupiter Myth

The Killer Angels

The Last Full Measure

The Return of the King

The Two Towers

Three Hands in the Fountain

Til We Have Faces

Time to Depart

Two for the Lions

Venus in Copper

Web Design: Tools and Techniques

Web Designers Reference: An Integrated Approach to Web Design with XHTML and CSS

World Atlas

Writing On Both Sides of the Brain

Skip to Main Points

Oddly Sorted Series Books

Next we tried to use XSLT more specifically with the series books. The following code matched everything up with the right books. Each title correctly includes which series it's a part of and what it's volume number is. To that extent, this was our first attempt to grab and organize multiple pieces of XML data from a record and present them together - ie each book's title, series, and volume. However, the books are organized by volume so the volume 1 of every series comes first, followed by the volume 2s, etc. You can take a look at our oddly sorted list with data from multiple elements. The output appears following the modified code.

<h3 id="titlesWithSeries" tabindex="0">Titles with Series (1st attempt)</h3>
<xsl:for-each select="/Bibliography/item/item">
<xsl:sort select="volume" />
<p><xsl:value-of select="title" />. <xsl:value-of select="series" />. Volume <xsl:value-of select="volume" />.</p>
</xsl:for-each>

Titles with Series (1st attempt)

Silver Pigs. Marcus Didius Falco. Volume 1.

Byzantium: The Early Centuries. Byzantium. Volume 1.

Gods and Generals. US Civil War. Volume 1.

Rise to Rebellion. US Revolution. Volume 1.

The Fellowship of the Ring. Lord of the Rings. Volume 1.

Two for the Lions. Marcus Didius Falco. Volume 10.

One Virgin Too Many. Marcus Didius Falco. Volume 11.

Ode to a Banker. Marcus Didius Falco. Volume 12.

A Body in the Bathhouse. Marcus Didius Falco. Volume 13.

The Jupiter Myth. Marcus Didius Falco. Volume 14.

Scandal Takes a Holiday. Marcus Didius Falco. Volume 15.

The Accusers. Marcus Didius Falco. Volume 16.

Shadows in Bronze. Marcus Didius Falco. Volume 2.

Byzantium: The Apogee. Byzantium. Volume 2.

The Killer Angels. US Civil War. Volume 2.

The Glorious Cause. US Revolution. Volume 2.

The Two Towers. Lord of the Rings. Volume 2.

Venus in Copper. Marcus Didius Falco. Volume 3.

Byzantium: The Decline and Fall. Byzantium. Volume 3.

The Last Full Measure. US Civil War. Volume 3.

The Return of the King. Lord of the Rings. Volume 3.

Iron Hand of Mars. Marcus Didius Falco. Volume 4.

Poseidon's Gold. Marcus Didius Falco. Volume 5.

Last Act in Palmyra. Marcus Didius Falco. Volume 6.

Time to Depart. Marcus Didius Falco. Volume 7.

A Dying Light in Corduba. Marcus Didius Falco. Volume 8.

Three Hands in the Fountain. Marcus Didius Falco. Volume 9.

Skip to Main Points

Sorted Series Books

Third, we went for the whole enchilada. This XSLT organizes the XML information into sections by series and finally got a list that looked fairly respectable.

<h3 id="titlesBySeries" tabindex="0">Titles by Series</h3>
<xsl:for-each select="/Bibliography/item/seriesName">
<xsl:sort select="." />
<h4><xsl:value-of select="." /></h4>
<ul>
<xsl:for-each select="../item">
<xsl:sort data-type="number" select="volume" />
<li>
<xsl:value-of select="title" /> (<xsl:value-of select="series" />. Volume <xsl:value-of select="volume" />)
</li>
</xsl:for-each>
</ul>
</xsl:for-each>

Basically this code consists of two loops, one nested inside the other. The outer loop searches for seriesName elements in the XML file, which are only present in series items. It then sorts them alphabetically and displays them as level four headings, h4. This provides the overall structure for the list of series.

<xsl:for-each select="/Bibliography/item/seriesName">
<xsl:sort select="." />
<h4><xsl:value-of select="." /></h4>
.
.
.
</xsl:for-each>

Within each series, we set up a list and create a new nested for-each loop to construct the list item, <li>, elements inside it. The nested for-each loop selects the books that belong to that series. They are item elements which are siblings of the seriesName elements, so we use ".." to indicate that we're backing up to the parent element and then selecting the book by it's <item> element, select="../item". This is what grabs each book in the series. Ideally, I would like to have used the sibling selectors in XPath, but they did not work properly for me. I will continue to work on them, though I'm not sure they will work like I want anyway. We also have an <xsl:sort> tag to sort the titles of the series by their volume. Note that in the oddly sorted list one problem is that volumes are sorted 1, 10, 11, 12, 2, 3, 4, etc. We've corrected that problem in this instance using the data-type="number" attribute.

So far, we haven't output any information, we've simply grabbed the book. We haven't done anything with it. Since we have to repeat this process for every volume in the series, we've placed the meat of the nested loop inside the <li> tags. An <xsl:value-of> element grabs the title, and we place some series information inside parenthesis. Another value-of element grabs the series names, followed by a period. Following the series name, we write the word "Volume" and a final value-of element grabs the actual volume number. Below the code is the output, titles organized by series with detailed information.

<ul>
<xsl:for-each select="../item">
<xsl:sort data-type="number" select="volume" />
<li>
<xsl:value-of select="title" /> (<xsl:value-of select="series" />. Volume <xsl:value-of select="volume" />)
</li>
</xsl:for-each>
</ul>

Titles by Series

The Byzantium series

  • Byzantium: The Early Centuries (Byzantium. Volume 1)
  • Byzantium: The Apogee (Byzantium. Volume 2)
  • Byzantium: The Decline and Fall (Byzantium. Volume 3)

The Lord of the Rings series

  • The Fellowship of the Ring (Lord of the Rings. Volume 1)
  • The Two Towers (Lord of the Rings. Volume 2)
  • The Return of the King (Lord of the Rings. Volume 3)

The Marcus Didius Falco series

  • Silver Pigs (Marcus Didius Falco. Volume 1)
  • Shadows in Bronze (Marcus Didius Falco. Volume 2)
  • Venus in Copper (Marcus Didius Falco. Volume 3)
  • Iron Hand of Mars (Marcus Didius Falco. Volume 4)
  • Poseidon's Gold (Marcus Didius Falco. Volume 5)
  • Last Act in Palmyra (Marcus Didius Falco. Volume 6)
  • Time to Depart (Marcus Didius Falco. Volume 7)
  • A Dying Light in Corduba (Marcus Didius Falco. Volume 8)
  • Three Hands in the Fountain (Marcus Didius Falco. Volume 9)
  • Two for the Lions (Marcus Didius Falco. Volume 10)
  • One Virgin Too Many (Marcus Didius Falco. Volume 11)
  • Ode to a Banker (Marcus Didius Falco. Volume 12)
  • A Body in the Bathhouse (Marcus Didius Falco. Volume 13)
  • The Jupiter Myth (Marcus Didius Falco. Volume 14)
  • Scandal Takes a Holiday (Marcus Didius Falco. Volume 15)
  • The Accusers (Marcus Didius Falco. Volume 16)

The US Civil War series

  • Gods and Generals (US Civil War. Volume 1)
  • The Killer Angels (US Civil War. Volume 2)
  • The Last Full Measure (US Civil War. Volume 3)

The US Revolution series

  • Rise to Rebellion (US Revolution. Volume 1)
  • The Glorious Cause (US Revolution. Volume 2)

In theory, I think this is the guts of my different display models. I simply need to adjust the information inside the list item tags to pull the data I want and put it into the proper format for bibliographic records. It will present a much more complex array of information, but the XSLT should look very similar. I will probably have to include author names by first, middle and last, rather than simply as <author> elements with the full name.

An inconvenient point has come up. This method simply alphabetizes the names of the series. There's no way to grab titles AND series names and have them alphabetized together. I guess that will be the next step; getting the book titles and series names alphabetized in one list.

[chroniclemaster1, 2007/11/02]
Skip to Main Points
← ← Jump back to XML / XSLT Play