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>
|