RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Making XQuery Control Structures Work for You : Page 4

The XQuery language is the XML analogue of SQL, designed to augment XPath 2.0 by working with sets of values, not just with single scalar values.

Because XQuery can get complex fairly quickly, one construct that could be useful is a switch statement that allows you to create certain output based upon a given case value, for example:

    case $expr1:  $result1
    case $expr2: $result2
    default: $fallthruResult
XQuery doesn't have a simple switch. What it does have is a type switch, which lets you perform actions based upon the data type of a given variable. The idea behind the type switch initially was to provide a means of identifying an element in an XML document and performing some processing based upon that element:

    case $a as type1 return $expr1
    case $a as type2 return $expr2
    case $a as type3 return $expr3
    default $a return $fallthruResult
This approach may seem a little counterintuitive, though an example may make it a little clearer. Suppose you want to apply specialized formatting to each node in an employee record. You could do so with the typeswitch control as follows:

{for $employee in doc("employees.xml")/employees/employee return 
  for $node in $employee/*
  return typeswitch($node)
    case $a as element (firstname) return <span>{string($a)} </span>
    case $a as element (lastname) return <span>{string($a)}</span>
    case $a as element (title) return <div>{string($a)}</div>
    case $a as element (division) return <div><b>{string($a)}</b></div>
    default $a return <div>{string($a)}</div>
The problem with typeswitch is that it solves an edge case in the language, but doesn't do terribly well with the more common problem of conditionally choosing different paths based upon a given string token. Fortunately, with a little bit of work, you can make typeswitch more like a traditional switch. The trick is to turn a token into a temporary element by using an XQuery expression. You can generate different outputs depending upon which particular division a given person is in (see Listing 5).

The key to this routine is in the line:

    let $division := element {string($employee/division)}{}
The expression element {string($employee/division)}{} looks rather cryptic, but can be decomposed fairly readily—the first braced expression evaluates to the name of a division such as Materials or AcctsPayable, while the second empty braced expression indicates that this is an empty element. Together, this creates an element in the form <Materials/>, <AcctsPayable/>, etc. This element can then be used to trigger the various cases, such as:

case $a as element (Materials) return
    <h1 class="materials_title">Materials Section</h1>
    <div class="name">{concat($employee/firstname,' ',$employee/lastname)}</div>
    <div class="title">{string($employee/title)}</div>
    <div class="manager">{
      let $manager := $employees[@id = string($employee/supervisor)]
      return concat($manager/firstname,' ',$manager/lastname)
The output in turn is the appropriate format for that type of material. In the default case where there is no match, a warning message is thrown up indicating that there's a problem with that particular employee record. The $a variable in this case holds a pointer to the division element, but in the above example it is unused and is simply a placeholder for the case routine.

The XQuery 1.1 working draft hints at other control structures, including the GROUP BY operator that makes it possible to aggregate results by group selectors and WINDOW clauses, which provide an ability to easily do set operations on subsequences of a given sequence. Additionally, the XQuery Scripting Extensions (or XqueryScript) provide other control structures that are designed to make XQuery easier to use within a more formal scripting role. However, both these drafts are still very much in development, and currently no commercial or open source implementations of XQuery support these capabilities.

Control structures are not necessarily glamorous; indeed, they are about as exciting as rebar scaffolding, but like such scaffolding they are a critical part of building any XQuery application. Understanding how to work with these structures can make the difference between a useful, flexible application, and a one-off piece of code that will have to be written over and over again.

Kurt Cagle is the managing editor for XMLToday.org and a contributing editor for O'Reilly Media. He is currently working on a book about XBRL. Follow him on Twitter at twitter.com/kurt_cagle.
Email AuthorEmail Author
Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date