XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Interactive Web Applications with XQuery

Interactive Web Applications with XQuery

May 14, 2003

In this installment of Practical XQuery I continue to discuss practical uses of XQuery, focusing this time on interactive web page generation. The sample application will display a list of books; based on user input, it will also display detailed information about the selected title.

The example exercises an interesting capability of the QEXO XQuery implementation, which is open source software. It allows front-end web applications with custom look and feel to be written very easily, using business logic from remote web services.

Amazon.com allows anyone to register and build a collection of favorite titles. The collection can be seen either directly via HTML pages on the web site or accessed via a REST-style web service. In the latter case the XML response contains information about book titles, book image icons, and unique book identifiers. The identifier can be used to access another web service offered by Amazon, which supplies book details, including price, user rating, and so on.

To create the example application, I will write two XQuery programs. The first, favbooks.xql, will provide a custom view of my favorite books. The second, bookdetails.xql, will show the details of a chosen book.

To get a taste for what is coming, you can play with this example application.

Let's look at the source code and explain the key points. The long xml.amazon.com URL in Listing 1 is wrapped for readability.

Listing 1: favbooks.xql

define function row ($name, $icon, $baseurl, $link) 
{
  <div>
    <a href="{$baseurl}{$link}">
      <img src="{$icon}"/>
      {$name}
    </a>
  </div>
}

define function filter-books ($bookListUrl, $detailsBaseUrl) 
{
 for $i in document($bookListUrl)/ProductInfo/Details
   return row($i/ProductName/text(), $i/ImageUrlSmall/text(),
     $detailsBaseUrl, $i/Asin/text())
}

<html>
  <body>
  <i>Book List Demo, written in XQuery. 
    Compiled and Run by The Open Source QEXO.org
engine.</i>
  <hr/>

 {filter-books(
"http://xml.amazon.com/onca/xml?v=1.0&t=webservices-20&
dev-t=D2GNXHNXXYM094&ListManiaSearch=1AU8KSU46JLPD&
type=lite&f=xml",
    "bookdetails.xql?AsinSearch="
    )
 }

  </body>
</html>

When executed, this XQuery program will produce output similar to Figure 1 below.

book list
Figure 1. Example output

(click for larger image)

When the user clicks on a book image or title, the application will take the user to the next page, which runs the following XQuery program (long URL line wrapped for readability).

Listing 2: bookdetails.xql

<html>
  <body>
  <i>Book List Demo, written in XQuery. 
   Compiled and Run by The Open Source QEXO.org engine.</i>
  <hr/>
 {
    let $baseBookUrl := "http://xml.amazon.com/onca/xml?
v=1.0&t=webservices-20&dev-t=D2GNXHNXXYM094&type=heavy
&f=xml&"
    let $bookDetailsUrl := concat($baseBookUrl,
      invoke($request, 'getQueryString'))
    let $book := document($bookDetailsUrl)/ProductInfo/Details

    return
     <div>
      <p><img src="{$book/ImageUrlMedium}"/></p>
      <p><b>{$book/ProductName/text()}</b></p>
      <p>author: <b>{$book/Authors/Author[1]}</b></p>
      <p>price: <b>{$book/OurPrice}</b></p>
      <p>readers rating: 
     <b>{$book/Reviews/AvgCustomerRating}</b> ( out of 5)</p>
      <p><b><a href="{$book/@url}">Buy this book</a></b></p>
      <p><b><a href="favbooks.xql">Back to books list</a></b></p>
     </div>
 }
  </body>
</html>

It renders an HTML page similar to that of Figure 2.

Book Details
Figure 2. Book details page

(click for larger image)

More from Practical XQuery

XQuery Implementation

Processing RSS

The favbooks.xql program resembles the example from an earlier article. The significant new element here is that each row is associated with a link to bookdetails.xql, with an URL query parameter AsinSearch that passes the unique identifier of the selected book to the next page.

The book details page is also very simple. The only bits worth mentioning explicitly are the use of the invoke function and the implicit $request variable. The invoke function is QEXO extension. It allows any Java function visible to the XQuery program classloader to be invoked. The implicit variable $request is another QEXO extension that allows XQuery programs to interface with the J2EE environment they are deployed in. For more information on the uses of the various QEXO extensions, visit the QEXO web site.

You've probably noticed that the two programs have no special logic for extracting book titles and images from proprietary sources such as a database or a file system. All the work is performed by the remote web service and is conveniently searched and presented by the XQuery programs. This demonstrates the ability of XQuery to naturally employ web services.

Resources