Introduction to FLWOR Expressions

If you have used SQL, then you will have recognized the last example as a join between two tables - the videos table and the actors table. Join queries are not quite the same in XML, because the data is hierarchic rather than tabular, but XQuery allows you to write join queries in a similar way to the familiar SQL approach. The equivalent of the SQL SELECT expression is called the FLWOR expression, named after its five clauses: for, let, where, order by, return. Here is the last example (all videos with an actor named `Lisa', rewritten this time as a FLWOR expression.

let $doc := .
               
for $v in $doc//video,
               
    $a in $doc//actors/actor
               
where ends-with($a, 'Lisa')
               
    and $v/actorRef = $a/@id
               
return $v/title 
               

            

When we run this XQuery, we get the same result as before.

Let's examine the FLWOR expression:

  • The let clause simply declares a variable. We included this here because when we deploy the query we might want to set this variable differently; for example, we might want to initialize it to doc(`videos.xml'), or to the result of some complex query that locates the document in a database.
  • The for clause defines two range variables: one processes all the videos in turn, the other processes all the actors in turn. Taken together, the FLWOR expression is processing all possible pairs of videos and actors.
  • The where clause then selects those pairs that we are actually interested in. We are only interested if the actor appears in that video, and we are only interested if the actor's name ends in `Lisa'.
  • Finally the return clause tells the system what information we want to get back. In this case we want the title of the video.

If you have been following very closely, you might have noticed one little XPath trick that we retained in this query: most videos will feature more than one actor (though this particular database does not attempt to catalog the bit-part players). The expression $v/actorRef therefore selects several elements. The rules for the = operator in XPath (and therefore also in XQuery) are that it compares everything on the left with everything on the right and returns true if there is at least one match. In effect, it is doing an implicit join. If you want to avoid exploiting this feature, and you want to write your query in a more classically relational form, you could express it as follows:

let $doc := .
               
for $v in $doc//video,
               
    $va in $v/actorRef,
               
    $a in $doc//actors/actor
               
where ends-with($a, 'Lisa')
               
    and $va eq $a/@id
               
return $v/title 
               

            

This time we used a different equality operator, eq, which follows more conventional rules than = does: it strictly compares one value on the left with one value on the right. (But like comparisons in SQL, it has special rules to handle the case where one of the values is absent.)

What about the O in FLWOR? That is there so you can get the results in sorted order. Suppose you want the videos in order of their release date. Here's the revised query:

let $doc := .
               
for $v in $doc//video,
               
    $a in $doc//actors/actor
               
where ends-with($a, 'Lisa')
               
    and $v/actorRef = $a/@id
               
order by $v/year
               
return $v/title
               

            

If you are wondering why FLWOR is not really a LFWOR expression: the for and let clauses can appear in any order, and you can have any number of each. To learn more about the FLWOR expression, see Understanding FLWOR Expressions.

 
Free Stylus Studio XML Training:
W3C Member