XQuery/Displaying data in HTML Tables

< XQuery

Motivation

You would like to display your XML data in an HTML table and display alternate rows using a colored background.

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>

<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>

<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>

</bookstore>

Screen Image

The following XQuery will perform the task.

xquery version "1.0";
declare option exist:serialize "method=xhtml media-type=text/html";
 
let $my-doc := doc("books.xml")
return
<html>
    <head>
        <title>Current Rates</title>
    </head>
    <body>
    <ul>
{
for $x in $my-doc/bookstore/book
order by $x/title
return <li>{data($x/title)}. Category: {data($x/@category)}</li>
}</ul>
   </body>
</html>

Discussion

Sorting before counting

There are two nested for loops. The outer loop has the additional at count parameter that increments a counter for each result returned. The inner loop has the loop that returns a generic sorted item to the outer loop. Note that the inner loop does the sorting first and the outer loop does the counting of each item so that alternate rows are shaded.

Note that if you know the original file is in the correct order the nested for loops are not necessary. A single for loop with the at $count is all that is needed.

Dynamic Element Construction

The following lines:

<tr> {if ($count mod 2)
         then (attribute bgcolor {'Lavender'})
         else ()}

conditionally creates a light blue background color for odds rows, rows which evaluate true because modulus 2 of their $count is not zero. This is an example of dynamic element construction.

Odd rows:

<tr bgcolor="Lavender">
   <td>...</td>
</tr>

Even rows:

<tr><td>...</td></tr>

It does this by conditionally adding an attribute bgcolor="Lavender" for odd rows in the table. If the test ($count mod 2) is zero, i.e. on even rows, an attribute will not be added.

It is recommended best practice that the style of shading alternate rows of a table be done in a central cascading style sheet. The most general way to keep the table formats standard throughout your site would be to add semantic class tags to each row to label them even or odd.

<tr> {if ($count mod 2)
         then (attribute  class  {'even'})
         else (attribute  class  {'odd'})}

The CSS file would then contain the following:

.odd {background-color: Lavender;}
This article is issued from Wikibooks. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.