Monday, December 3, 2012

XQuery Short Tutorial - Part 2


This is the second part of XQuery Short Tutorial.   To view the first part click on this url: XQuery Short Tutoril - Part1

Variables

In XQuery a variable is very easy to be identified.  All XQuery variables always start with $.

There are two types of variables: global variable and local variable.  

Global variable implies that it can be accessible from anywhere within XQuery.   Global variable is declared in the prolog part in XQuery.

Local variable is only accessible within the scope where it is declared such as in one FLOWR expression.

One thing needs to be remembered that once variables are assigned they cannot be assigned with new value.

Example 1

declare variable $displayedText as xs:string := ‘No result found based on the given conditions’;


In above example one global variable of xs:string type is declared and assigned a value:  'No result found based on the given conditions'.

Example 2

let $products := (<product>
                    <id>143</id>
                    <name>Cable</name>
                  </product>,
                  <product>
                    <id>234</id>
                    <name>Adapter</name>
                  </product>)
return $products


FLOWR expression

FLOWR expression is essential in XQuery body part.  Actually the body part of one useful XQuery is consisted of many FLOWR expressions. In order to use XQuery effectively you should master FLOWR expression.

FLOWR stands for For, Let, Order, Where, Return.  This expression is used to iterate, assign, filter, order and retrieve one XML document.

The below is a FLOWR expression.

Example 3

let $result := $flightOpsData/FlightLeg
for $flight in $result/InboundFlights
return $flight


This FLOWR expression first assign the node FlightLeg under variable $flightOpsData to a local variable $result and then iterates a list of nodes of InboundFlights under the variable $result and then retrieve the list back.

The next example goes further to add where to filter the nodes to be returned.

Example 4

let $result := $flightOpsData/FlightLeg
for $flight in $result/InboundFlights
where $flight/ArrivalPort=’SYD’
return $flight


The above FLOWR expression will retrieve the flights whose ArrivalPort is SYD.

In the above 3 examples we have seen Let, For, Where, Return already now we add the last one: Order to the expression.

Example 5

let $result := $flightOpsData/FlightLeg
for $flight in $result/InboundFlights
where $flight/ArrivalPort=’SYD’
order by $flight/ArrivalDateTime
return $flight


This FLOWR expression will retrieve all the flights whose ArrivalPort is SYD and the retrieved result will be ordered by flight’s ArrivalDateTime.

When we get here we have use all clauses in a FLOWR expression.   In the reality not all clauses are needed to present in the expression.   When we write FLOWR expression we need to keep in mind the following point:

·         Each FLOWR expression should have return clause as its last clause.  It is mandatory.

·         where and order are optional.

·         At least either one of let clauses or one of for clauses should be used.

·         You can have multiple let clauses or multiple for clause.

·         FLOWR expression can be nested.


Functions

Like functions in other languages XQuery functions provides specialised functionality. Functions will make XQuery programming easier since you can reuse these functionalities and don’t need to implement it yourself.  They also make XQuery much easier to understand and maintain.

There are many built-in functions available for you to use immediately in your XQuery.  Also you can develop your own custom functions.

The custom functions are defined in prolog part in XQuery

The below is one example of XQuery function.

Example 6

 (: Function used to convert the duration into minutes :)
declare function xf:total-minutes-from-duration( $duration as xdt:dayTimeDuration? )  as xs:decimal? {
       $duration div xdt:dayTimeDuration('PT1M')
 } ;


You can see from the above. One function has the function name, function parameters, return parameter and implementation part.

Implementation part of function actually is the same as the body party of XQuery.   You can static and dynamic portions to implement your functionality. 

The function in example 6 is called xf:total-minutes-from-duration.  Its input parameter is $duration of type xds:dayTimeDuration and it will return the value(s) of type xs:decimal.   The function implementation part is: $duration div xdt:dayTimeDuration('PT1M').

The input parameters and return parameter can be typed or untyped.

Typed parameter means that you specify the type of the parameter.   These types can be atomic value type or node type.

The below are some example of types.

Example 7

xs:integer
xs:boolean
xs:anyAtomicType
xs:string
node()
element()
tns:ProductType


Function parameters can have no type.   No type means that you can pass anything (atomic value, node type or empty sequence) to the parameter. 

Function parameters can have modifier following the parameter name.   These modifiers are: ?, *. +.

Modifier ? means that you can one item or empty.   * means one or more than one items or empty.   + means one or more than one items.

The above rules also apply to the return parameter of the function.


Let us see one example listed as below.  In this function there are 3 typed function parameters.  One is a specific element type, second atomic type and the last generic element type.  And the last one can be one element or a sequence of elements or empty.    The return type of this function is generic element type and can be a sequence of elements or empty.

Example 8

declare function xf:filterFlightOpsData(
      $flightOperationsQueryRS1 aselement(tns:FlightOperationsQueryRS),
      $requestDateTime as xs:dateTime,
      $sortedFlightOpsDataList as element(ops:FlightOpsData)*) as element()* {
    (:  Funtion implementation is omitted here for brevity   :)
};


Make elements and attributes dynamically

Just XSLT XQuery also has the capability to create the element or attribute dynamically.   And this is quite useful in using XQuery. 

Actually it is rather simple to do in XQuery.

This is used to create element dynamically.

element {element_name} {element_value}


This is used to create attribute dynamically.

attribute {attribute_name} {attribute_value}


The below is one actual example that uses dynamic creation of attribute.   FlightSegements has two attributes: one is ID which is statically created and NumberOfStops which is dynamically created depending on if $FlightSegment has this attribute or not.

Example 9

<FlightSegment ID="{data($FlightSegment/@ID)}">
   if ($FlightSegment/@NumberOfStops)
   then
       attribute {"NumberOfStops"}{data($FlightSegment/@NumberOfStops)}
   else
    () 
</FlightSegment>




No comments:

Post a Comment