1. Other Expressions

    In addition to location paths expressions, a number of other types of expressions are also available in XPath 3.0.

    1. Literal Expressions

      There are different ways to specify literals depending on which type they represent.

      '523'
      A literal of type 'xs:string' appears within single or double quotes.
      523
      A literal comprising of one or more digits [0-9] is of type 'xs:integer'.
      523E6
      A literal containing digits, a possible decimal point, and 'E' or 'e' for exponential, is of type 'xs:double'.
      5.23
      A literal containing digits and a decimal point is of type 'xs:decimal'.
      fn:true()
      The literals for the 'xs:boolean' values 'true' or 'false' can be represented by calling the 'fn:true()' or 'fn:false()' functions respectively.
      xs:date('2014-11-05')
      Values of other types can be created by calling the appropriate constructor function. Constructor functions exist for all generalized atomic and list types defined in the XML Schema specification, as well as for any user-defined simpleTypes defined in an associated XML schema document.
    2. Conditional Expressions

      An XPath expression beginning with the keyword 'if' signifies a conditional expression.

      if (/company/office[@location = 'Boston']/employee[1]/age = 35) then 'is 35' else 'is not 35'.
      • The keyword 'if' is followed by a test expression in parentheses which returns a boolean value i.e. 'true' or 'false'.
      • The keywords 'then' and 'else' appear after the test expression.
      • Both 'then' and 'else' are also followed by an expression.
      • If the test expression evaluates to 'true', the expression following 'then' is evaluated i.e. a singleton sequence with a string item 'is 35' is returned.
      • If the test expression evaluates to 'false', the expression following 'else' is evaluated i.e. a singleton sequence with a string item 'is not 35' is returned.

      Conditional Expression Examples

      if (/company/office[@location='Boston']/employee[1]/age = 35) then 'is 35' else 'is not 35'
      result:
      'is not 35'
      This conditional expression selects the first 'employee' in the Boston 'office' and checks whether the value of the 'age' element is equal to 35. If 'age' is equal to 35, the string 'is 35' is returned, otherwise the string 'is not 35' is returned.
      if (count(/company/office/employee) = 5) then true() else false()
      result:
      true()
      This conditional expression uses the XPath 'count' function to count the number of '/company/office/employee' elements. If there are 5 'employee' elements, the boolean value 'true' is returned, otherwise the boolean value 'false' is returned.
      for $i in /company/office/employee return if ($i/age >= 30) then upper-case($i/last_name) else lower-case($i/last_name)
      result:
      ('smith', 'JONES', 'BROWN', 'DAVIS', 'MASON')
      This 'for' expression declares a variable 'i' and binds it to the sequence of elements which the location path '/company/office/employee' evaluates to. It then iterates over all 'employee' elements in the sequence, and for each iteration a conditional expression is evaluated, If the 'age' of the 'employee' is 30 or higher, the 'last_name' is returned in uppercase, if it is lower than the 30 the 'last_name' is returned in lowercase.
    3. Logical Expressions

      A 'logical' expression is either an 'and' expression or an 'or' expression. The evaluation of a logical expression returns the boolean value 'true' or 'false'.

      first_name = 'John' and age = 40
      A logical expression consists of an operand followed by the keyword 'and' or 'or' followed by another operand. If the 'and' keyword is used, the effective boolean value of both operands must evaluate to 'true' for the expression to return 'true'. If the 'or' keyword is used, the effective boolean value of at least one of the operands must evaluate to 'true' for the expression to return 'true'.

      Logical Expression Examples

      The following examples are based on the XML document below. The examples assume that the context node is the first 'employee' element in the Boston 'office'.

      first_name  =  'John' and age  =  40
      result:
      false()
      This logical expression tests to see if the value of the 'first_name' child element of the context node is 'John' AND if the value of the 'age' child element of the context node is 40. Because only one of the subexpressions evaluates to 'true' (the other evaluates to 'false'), this expression returns 'false'.
      first_name  =  'John' or age  =  40
      result:
      true()
      This logical expression tests to see if the value of the 'first_name' child element of the context node is 'John' OR if the value of the 'age' child element of the context node is 40. Because at least one of the subexpressions evaluates to 'true', the expression returns 'true'.
    4. Sequence Expressions

      Sequences are fundamental to XPath. In XPath 3.0 operators are available to construct, combine and filter sequences.

      Constructing Sequences:

      (employee/first_name, employee/age)
      The comma operator i.e. ',' can be used to concatenate the sequences returned by each operand into a single result sequence.
      (1 to 10)
      • The 'to' operator can be used specify a range from which a sequence of integer values is constructed.
      • The value of the operand on the left hand side must be less than or equal to the operand on the right hand side or an empty sequence will be returned.

      Combining Sequences:

      (company/office[@location = 'Boston']/employee/age union company/office[@location = 'Vienna']/employee/age)
      • The 'union', 'intersect' and 'except' operators can be used to combine sequences of nodes.
      • Each of these operators has two operands, and each operand must be a sequence of nodes.
      • If the 'union' operator is used, a sequence containing all of the nodes occurring in either of the sequences is returned.
      • If the 'intersect' operator is used, a sequence containing nodes that occur in both sequences is returned.
      • If the 'except' operator is used, a sequence containing only the nodes that occur in the first operand, but not in the second operand, is returned.

      Sequence Construction Examples

      Some of the examples below are based on the XML document below. The examples assume that the context node is the first 'office' element (with a location attribute value of 'Boston').

      (5, 7, 3, 2, 8)
      result:
      (5, 7, 3, 2, 8)
      This expression constructs a sequence of integers 5, 7, 3, 2, 8. The comma ',' operator is used to separate each item in the sequence.
      (5, (7, 3), (), 2, 8)
      result:
      (5, 7, 3, 2, 8)
      Sequences cannot contain nested sequences. This expression constructs a sequence by combining 5 sequences (of length 1, 2, 0, 1 and 1 respectively) into a single sequence.
      (employee/first_name, employee/age)
      result:
      ('John', 'John', 25, 30)
      This expression constructs a sequence from the 'employee/first_name' elements and 'employee/age' elements of the context node. As you can see, sequences can also contain duplicate items.
      Please note that for clarity the results show the text value of the selected nodes, however the actual sequence returned is '(<first_name>, <first_name>, <age>, <age>)' where the values in angled brackets represent the node names.
      (1 to 5)
      result:
      (1, 2, 3, 4, 5)
      This range expression constructs a sequence of integers from 1 to 5 i.e. 1, 2, 3, 4, 5.

      Sequence Combining Examples

      The examples below are based on the XML document below. The examples assume that the context node is the 'cities_visited' element.

      traveller[@name = 'John']/city union traveller[@name = 'Jane']/city
      result:
      ('Hong Kong', 'Los Angeles', 'New York', 'Vancouver', 'London', 'Los Angeles', 'New York', 'Sydney')
      This example returns a union of the 'city' child elements of the travellers named 'John' and 'Jane' respectively.
      Please note that for clarity the the results show the text value of the selected nodes, however the actual sequence returned contains the element nodes themselves i.e. '(<city>, <city>, <city>, <city>, <city>, <city>, <city>, <city>,)' where the values in angled brackets represent the node names.
      traveller[@name = 'John']/city | traveller[@name = 'Jane']/city
      result:
      ('Hong Kong', 'Los Angeles', 'New York', 'Vancouver', 'London', 'Los Angeles', 'New York', 'Sydney')
      This example is the same as the previous example, the operator '|' is the equivalent of the 'union' operator.
      traveller/city intersect traveller[@name = 'John']/city
      result:
      ('Hong Kong', 'Los Angeles', 'New York', 'Vancouver')
      This example returns the intersection of all 'city' elements which are children of 'traveller' elements with the 'city' elements that are child elements of the traveller named 'John'.
      Please note that for clarity the results show the text value of the selected nodes, however the actual sequence which is returned contain the element nodes themselves i.e. '(<city>, <city>, <city>, <city>)'.
      traveller[@name = 'John']/city intersect traveller[@name = 'Jane']/city
      result:
      ()
      This example returns the intersection of the 'city' element children of the travellers 'John' and 'Jane'. Although it might seem strange that the empty sequence is returned, it is in fact quite logical: Although the 'city' element children of the 'traveller' John and the 'city' element children of the 'traveller'Jane may have the same name i.e. 'city', and also in some case have the same values i.e 'Los Angeles' and 'New York', they are in fact not the same nodes i.e. one set are the 'city' element children of the traveller named 'John' and the other set are the city element children of the traveller named 'Jane'. There is no intersection as in the previous example.
      traveller/city except traveller[@name = 'John']/city
      result:
      ('London', 'Los Angeles', 'New York', 'Sydney')
      This example returns all 'city' elements which are in the left operand (traveller/city) but not in the right operand (traveller[@name = 'John']/city), which in this case would be all of the 'city' child elements of the 'traveller' named 'Jane'.
      Please note that for clarity the the results show the text value of the selected nodes, however the actual sequence which is returned contain the element nodes themselves i.e. '(<city>, <city>, <city>, <city>)'.
    5. For Expressions

      The 'for' expression is used to iterate over sequences.

      for $i in company/office/employee return $i/first_name
      • In its most basic form, a 'for' expression begins with the keyword 'for' followed by a variable declaration (denoted by a '$' and a variable name).
      • The keyword 'in' appears after the variable declaration, and is followed by an expression which evaluates to a sequence of items.
      • The keyword 'return' appears after this expression, and is followed by another expression which is evaluated for each item in the sequence.

      For Expression Examples

      for $i in /company/office/employee return $i/first_name
      result:
      ('John', 'John', 'Mary', 'Peter', 'Mark')
      This 'for' expression declares a variable 'i' and binds it to the 'company/office/employee' element(s). It then iterates over all 'company/office/employee' element(s), and for each iteration returns the 'first_name' child element.
      distinct-values(for $i in /company/office/employee return $i/first_name)
      result:
      ('John', 'Mary', 'Peter', 'Mark')
      The 'for' expression in the example above is passed as an argument to the 'distinct-values' function to return a sequence of unique 'first_name' element values.
      for $i in (1 to  5) return $i*10
      result:
       (10, 20, 30, 40, 50)
      This expression uses the 'to' operator to construct a sequence of integers from 1 to 5. The 'for' keyword is then used to iterate through each item in the sequence and multiply it by 10.

      For Expression Examples Continued

      for $x in /cities/city, $y in /cities/city return concat('from: ', $x, '  to: ', $y)
      result:
      ('from: Los Angeles to: Los Angeles', 'from: Los Angeles to: Paris', 'from: Paris to: Los Angeles', 'from: Paris to: Paris')
      This 'for' expression declares and binds a variable 'x', and also declares and binds a variable 'y', to the 'cities/city' element(s). Because each variable contains two items, the result returns a sequence of four items. The built-in XPath 'concat' function is used to output the 'from city' and the 'to city'.
      for $x in /cities/city, $y in /cities/city return if ($x != $y) then concat('from: ', $x, '  to: ', $y) else ()
      result:
      ('from: Los Angeles to: Paris', 'from: Paris to: Los Angeles')
      In order to remove the items where the 'from city' is the same as the 'to city', an 'if else' expression is placed after the 'return' keyword of the 'for' expression. If the item identified by variable 'x' is not the same as the item identified by variable 'y', the values are passed to the concat function, if they are the same, an empty sequence is returned.
    6. Quantified Expressions

      A quantified expression tests to see if any or all items in a sequence match a particular condition.

      some $i in company/office/employee satisfies $i/age < 30
      • A quantified expression begins with the keyword 'some' or 'every' followed by a variable declaration and the keyword 'in'.
      • 'in' is followed by an expression which returns a sequence of items.
      • Following this expression is the keyword 'satisfies', and following 'satisfies' is a test expression.
      • If the keyword 'some' is used, the test expression must evaluate to 'true' for at least one of the items in the sequence in order for the whole quantitative expression to return 'true'.
      • If the keyword 'every' is used, the test expression must evaluate to 'true' for all of the items in the sequence in order for the whole quantitative expression to return 'true'.

      Quantified Expression Examples

      some $i in /company/office/employee satisfies $i/age < 30
      result:
      true()
      The quantified expression declares and binds the variable 'i' to the 'company/office/employee' element(s). The 'some' keyword is used at the beginning of the expression to test whether at least one of the 'age' element(s) has a value less than 30.
      every $i in /company/office/employee satisfies $i/age < 30
      result:
      false()
      The quantified expression declares and binds the variable 'i' to the 'company/office/employee' element(s). The 'every' keyword is used at the beginning of the expression to test whether all of the 'age' element(s) have a value less than 30.
    7. Comparison Expressions

      In XPath 3.0 there are three kinds of comparison expressions:value comparisons, general comparisons and node comparisons.

      Value Comparison:

      traveller[@name = 'John']/city[1]  eq 'Hong Kong'
      • Value comparisons are used for comparing single values (i.e. sequences of one 'item') with one another.
      • A value comparison consists of an operand followed by a value comparison operator, followed by a second operand.
      • Each operand is atomized.
      • If an operand is an empty sequence, the result of the comparison will also be an empty sequence.
      • If either of the operands is a sequence of more than one item an error will be thrown.

      General Comparison:

      traveller[@name = 'John']/city  = 'Los Angeles'
      • General comparisons may be used for comparing sequences of any length with one another.
      • A general comparison consists of an operand followed by a general comparison operator, followed by a second operand.
      • Each operand is atomized.
      • If at least one atomic value from the first operand and one from the second operand have the required relationship for the operator used e.g. 9 > 5 (9 is greater than 5), the result of the comparison is 'true', if they do not have the required relationship e.g. 5 > 9 (5 is greater than 9), the result of the comparison is 'false'.

      Node Comparison:

      traveller[@name = 'John']/city is traveller[1]/city[1]
      • Node comparisons may be used for comparing nodes based upon their identity or document order.
      • Node comparisons do not compare nodes based upon their value.
      • A node comparison consists of an operand followed by a node comparison operator, followed by a second operand.
      • Each operand must be a sequence of one node or an empty sequence.
      • If either operand is an empty sequence, the node comparison will return an empty sequence.
      • If the 'is' operator is used, the node comparison returns 'true' if both operand nodes have the same identity i.e. are the same node.
      • If the '<<' operator is used, the node comparison returns 'true' if the node of the left operand precedes (in document order) the node of the right hand operator.
      • If the '>>' operator is used, the node comparison returns 'true' if the node of the left operand follows (in document order) the node of the right hand operator.

      Value Comparison Examples

      The following examples are based on the XML document below. The examples assume that the context node is the root element 'cities_visited'.

      traveller[@name = 'John']/city[1]  eq 'Hong Kong'
      result:
      true()
      This value comparison expression compares the value of the first 'city' child element of the 'traveller' named 'John' with the string 'Hong Kong'.
      traveller[@name = 'John']/city[1]  eq 'New York'
      result:
      false()
      This value comparison expression compares the value of the first 'city' child element of the 'traveller' named 'John' with the string 'New York'. It returns 'false' because the value of the first 'city' is 'Hong Kong', not 'New York'.
      traveller[@name = 'John']/city  eq 'Hong Kong'
      result:
      false()
      This value comparison expression compares the value of all 'city' child elements of the 'traveller' named 'John' with the string 'Hong Kong'. It returns a 'type error' because the first operand is a sequence of 4 items and value comparisons can only compare sequences of one item (i.e. 'singleton' sequences) with one another.
      traveller[@name = 'John']/city[2] eq traveller[@name = 'Jane']/city[2]
      result:
      false()
      This value comparison expression compares the value of the second 'city' child element of the 'traveller' named 'John' with the second 'city' child element of the 'traveller' named 'Jane'. Because both of these nodes have the same value i.e. 'Los Angeles' the value expression returns true.
      traveller[1]/@age lt traveller[2]/@age
      result:
      false()
      This value comparison expression tests whether the value of the 'age' attribute of the first 'traveller' child element of the context node is less than the value of the 'age' attribute of the second 'traveller' child element.
      traveller[1]/@age gt traveller[2]/@age
      result:
      true()
      This value comparison expression tests whether the value of the 'age' attribute of the first 'traveller' child element (of the context node) is greater than the value of the 'age' attribute of the second 'traveller' child element.

      General Comparison Examples

      Some of the following examples are based on the XML document below. The examples assume that the context node is the root element 'cities_visited'.

      traveller[@name = 'John']/city[1]  = 'Hong Kong'
      result:
      true()
      This general comparison expression compares the value of the first 'city' child element of the 'traveller' named 'John' with the string 'Hong Kong'.
      traveller[@name = 'John']/city[1]  = 'New York'
      result:
      false()
      This general comparison expression compares the value of the first 'city' child element of the 'traveller' named 'John' with the string 'New York'. It returns false because the value of the first 'city' is 'Hong Kong', not 'New York'.
      traveller[@name = 'John']/city  = 'New York'
      result:
      true()
      This general comparison expression compares the value of the all 'city' child elements of the 'traveller' named 'John' with the string 'New York'. It returns true because at least one of the items in the sequence of the first operand is equal to 'New York'. Each operand in a general comparison can be a sequence with 1 or more items.
      traveller[1]/@age < traveller[2]/@age
      result:
      true()
      This value comparison expression tests whether the value of the 'age' attribute of the first 'traveller' child element (of the context node) is greater than the value of the 'age' attribute of the second 'traveller' child element.
      (5, 10, 15) = (15, 20, 25)
      result:
      true()
      This general comparison expression compares the values in the first sequence with the values in the second sequence and because at least one value from the first sequence is not equal to a value in the second sequence, the expression returns 'true'.
      (5, 10, 15) != (15, 20, 25)
      result:
      true()
      This general comparison expression compares the values in the first sequence with the values in the second sequence and because at least one value from the first sequence is not equal to a value in the second sequence, the expression returns 'true'.
      (1, 3) > (4, 2)
      result:
      true()
      This general comparison expression compares the values in the first sequence with the values in the second sequence. Because at least one value from the first sequence (3) is greater than a value in the second sequence (2), the expression returns 'true'.

      Node Comparison Examples

      The following examples are based on the XML document below. The examples assume that the context node is the root element 'cities_visited'.

      traveller[@name = 'John']/city[ . = 'Los Angeles'] is traveller[1]/city[1]
      result:
      false()
      This node comparison expression compares the 'city' child element with a value of 'Los Angeles' of the 'traveller' named 'John' (i.e. the second 'city' child element) with the first 'city' element child of the first 'traveller' child element. These are different nodes, so 'false' is returned.
      traveller[@name = 'John']/city[ . = 'Los Angeles'] is traveller[1]/city[2]
      result:
      true()
      This node comparison expression compares the 'city' child element with a value of 'Los Angeles' of the 'traveller' named 'John' (i.e. the second 'city' child element) with the second 'city' element child of the first 'traveller' child element. These are the same node, so 'true' is returned.
      traveller[@name = 'John']/city[ . = 'Los Angeles'] <<  traveller[1]/city[1]
      result:
      false()
      This node comparison expression checks whether the 'city' child element with a value of 'Los Angeles' of the 'traveller' named 'John' (i.e. the second 'city' child element) precedes the first 'city' element child of the first 'traveller' child element. It does not, so 'false' is returned.
      traveller[@name = 'John']/city[ . = 'Los Angeles']  >>  traveller[1]/city[1]
      result:
      true()
      This node comparison expression checks whether the 'city' child element with a value of 'Los Angeles' of the 'traveller' named 'John' (i.e. the second 'city' child element) follows the first 'city' element child of the first 'traveller' child element. It does, so 'true' is returned.
      traveller[@name = 'John']/city[ . = 'Los Angeles'] is traveller[@name = 'Jane']/city[ . = 'Los Angeles']
      result:
      false()
      This node comparison expression checks whether the 'city' child element with a value of 'Los Angeles' of the 'traveller' named 'John' is the same node as the 'city' child element with a value of 'Los Angeles' of the 'traveller' named 'Jane'. Although the value of these nodes is the same, the nodes themselves are not the same, i.e. one is the second 'city' child element of the 'traveller' named 'John'. and one is the second 'city' child element of the 'traveller' named 'Jane'.
    8. Arithmetic Expressions

      In XPath 3.0 there are six arithmetic operators for addition, subtraction, multiplication, division, integer division, and modulus. These are respectively: +, -, *, div, idiv and mod.

      5 + 4 * 20 + 3 - 2 * 2 div 3
      • Each operand in an arithmetic expression is first atomized.
      • If the operand is an empty sequence, the result of the arithmetic expression will also be an empty sequence.
      • Each operand may be an empty sequence or a sequence of one item. If the operand is a sequence of more than one item an error will be thrown.
      • If the atomized operand is of type 'xs:untypedAtomic', it will be cast to the numeric datatype 'xs:double'.
      • If the types of the operands are a valid combination for the arithmetic operator (see Operator Mapping section of XPath specification), the operator will be applied to the operands. This will result in an atomic value or an error e.g. when dividing by 0.

      Arithmetic Operators

      5 + 4 * 6 + 3 - 2 * 2
      • The '*', 'div', 'idiv' and 'mod' operators have operator precedence over the '+' and '-' operators meaning they will be evaluated before the '+' and '-' operators. This means that the expression above is equivalent to 5 + (4 * 6) + 3 - (2 * 2) and as such will return the value 28.
      • The 'idiv' operator is used for integer division i.e is used to return an integer value with no fractional part. The expression 10 idiv 4 will return 2. The expression 10 idiv 6 will return 1.
      • The 'mod' operator is used to return the remainder. The expression '10 mod 5' will return 0 and the expression '10 mod 3' will return 1.
      • The '+', '-', '*' and 'div' operators are not limited to numeric values. They may also be applied to operands of various date, time and duration types.

      Operand Types

      5 + 12.5
      Depending on the arithmetic operator used, if the types of the operands differ, type promotion may promote the type of one operand to the type of the other operand. In the example above the value 5 is an 'xs:integer' and the value 12.5 is an 'xs:decimal'. 5 will be promoted from an 'xs:integer' to an 'xs:decimal' and the return value of 17.5 will also be an 'xs:decimal'.

      Arithmetic Expression Examples

      Some of the following examples are based on the XML document below. The examples assume that the context node is the root element 'orders'.

      5 + 4 * 6 + 3 div 2
      result:
      30.5
      This arithmetic expression is equivalent to 5 + (4 * 6) + (3 div 2), which is equivalent to 5 + 24 + 1.5. The expression returns the 'xs:decimal' value 30.5.
      (5 + 4 * 6 + 3) div 2
      result:
      16.
      This arithmetic expression is equivalent to (5 + 24 + 3) div 2 and returns the 'xs:decimal' value 16.
      5 idiv 2
      result:
      2
      This example uses the integer division operator i.e. 'idiv' to divide the left operand by the right operand. The result is an 'xs:integer' value.
      for $i in ./order return $i/product/quantity * $i/product/price
      result:
      (450, 2439.6)
      This example uses a 'for' expression to iterate over each 'order' element and return the product of the 'product/quantity' and 'product/price' element values.
      sum(for $i in ./order return $i/product/quantity * $i/product/price
      result:
      2889.6
      This example uses the aggregate 'sum' function to sum the items in the sequence returned by the 'for' expression.
      order[1]/date_shipped + order[1]/date_received
      result:
      error
      The elements 'date_shipped' and 'date_received' are of type 'xs:date' according to the XML schema document 'orders.xsd' which is associated to 'orders_1.xml'. Two 'xs:date' operands ARE NOT a valid combination for the '+' operator and therefore this expression returns an error.
      order[1]/date_shipped - order[1]/date_received
      result:
      xs:dayTimeDuration('P4D')
      As opposed to the previous example, two 'xs:date' operands ARE a valid combination for the '-' operator. This expression returns an 'xs:dayTimeDuration' value of 'P4D' i.e. the difference between the 'shipped_date' and 'received_date' is 4 days.
    9. String Concatenation Expressions

      A string concatenation expression simply concatenates the string representation of values.

      traveller[1]/@name || traveller[2]/@name
      • The '||' operator is used to concatenate the string representation of two values. This operator is new to XPath 3.0.
      • '||' is equivalent to the built-in XPath 'concat' function.

      String Concatenation Examples

      Some of the following examples are based on the XML document bwloe. The examples assume that the context node is the root element 'cities_visited'.

      traveller[1]/@name  ||  traveller[2]/@name
      result:
      'JohnJane'
      This string concatenation expression concatenates the value of the 'name' attribute of the first 'traveller' element with the value of the 'name' attribute of the second 'traveller' element.
      'XPath ' || 'is ' || 'awesome'
      result:
      'XPath is awesome'
      This string concatenation expression concatenates three strings into one.
      'One thousand is ' || 1E3
      result:
      'One thousand is 1000'
      This string concatenation concatenates the string 'One thousand is ' with the string value of the literal IE3 (an 'xs:double') which has a string value of '1000'.
    10. Let Expressions

      A let expression allows a variable to be declared and bound to a value. The scope of the variable declaration is the scope of the let expression.

      let $x := 2, $y := 3 return $x * $y
      • The 'let' keyword is followed by a variable declaration.
      • A variable declaration starts will the '$' character followed by a variable name e.g. '$x'.
      • The variable name is followed by ':=' and the value to be assigned to the variable e.g. 'let $x := 2'.
      • Multiple variables can be bound in a let expression. If multiple variables are declared, each variable binding must be separated by a comma ','.
      • The variable bindings are followed by the 'return' keyword.
      • A declared variable can be referenced in the 'let' expression by supplying the variable name prepended by '$' e.g. '$x'.

      Let Expression Examples

      Some of the following examples are based on the XML document below. The examples assume that the context node is the root element 'company'.

      let $x := office[@location = 'Boston'],
          $y := office[@location = 'Vienna']
          return (avg($x/employee/age), avg($y/employee/age))
      result:
      (27.5, 36)
      This example binds two variables '$x' and '$y' to the 'Boston' and 'Vienna' offices respectively. '$x' and '$y' are referenced in the return clause which returns a sequence of 'xs:double' values representing the average age of the employees in each office by calling the built-in function 'avg'. The expression 'Sx/employee/age' is equivalent to 'office[@location = 'Boston']/employee/age', and '$y/employee/age' is equivalent to 'office[@location = 'Vienna']/employee/age'.
      let $r := 5,
          $pi := 3.14
          return  'area = ' || $pi * ($r * $r)
      result:
      'area = 78.5'
      This example simply binds two literals to the '$r' and '$pi' variables respectively. These variables are then referenced in the return statement of the 'let' expression.
      let $pi := 3.14,
          $area := function ($arg)
            {
               'area = ' ||	$pi * $arg * $arg
            },
          $r := 5
          return $area($r)
      result:
      'area = 78.5'
      This example simply binds two literals to the '$r' and '$pi' variables respectively. It also binds a third variable '$area' to an inline function. The return statment calls the inline function by using its variable reference '$area' and passing the '$r' variable to it.
    11. Expressions on SequenceTypes

      The 'instance of', 'cast', 'castable', and 'treat' operators are used in expressions on sequence types.

      instance of

      'hello world' instance of xs:string
      • The 'instance of' expression is a boolean expression which returns true or false depending on whether or not the operand on the left is an 'instance of' the right operand. The right operand can be an atomic type (e.g. 'xs:integer', 'xs:date' etc.), but it can also be one of the node types defined by the XPath data model (e.g. 'element()', 'attribute()' etc.).
      • The right operand can also specify the following occurrence specifiers: '?', '*', '+' to test for sequences of 'zero or one item', 'zero or more items' and 'one or more items' respectively. If no occurrence specifier is provided only a sequence with exactly one item will conform to the type.

      cast as

      '6' cast as xs:integer
      The 'cast' operator is used to cast a value from one atomic type to another atomic type e.g. 'xs:string' to 'xs:integer'. Unlike the 'instance of' and 'treat' operators which permit atomic types or node type operands, the operands in a 'cast' expression can only be atomic types. If it is possible to cast the value of the left operand to the target datatype specified by the right operand, the value will be cast to the target atomic datatype, otherwise an error will be thrown.

      castable

      'hello world' castable as xs:integer
      The 'castable' expression is a boolean expression which simply determines whether it is possible to cast a particular value / type to the target datatype.

      treat as

      product/stock treat as xs:integer
      The 'treat' expression is similar to the 'cast' expression, however 'treat' does not change the dynamic type or value of the operand like 'cast' does. Also, unlike the 'cast' operator, the 'treat' operator can also operate on node types.

      Instance of Expression Examples

      'hello world' instance of xs:integer
      result:
      false()
      This example checks whether the 'xs:string' value 'hello world' is an instance of 'xs:integer'. As 'hello world' is a string value, this expression returns 'false'.
      10 instance of xs:integer
      result:
      true()
      This example checks whether 10 is an instance of 'xs:integer'. As 10 is an integer value, the expression returns 'true'.
      (10, 100) instance of xs:integer
      result:
      false()
      This expression returns 'false' because there are two 'xs:integer' values in the left operand and the right operand only tests for one.
      (10, 100) instance of xs:integer*
      result:
      true()
      This expression evaluates to 'true' because the occurrence specifier after the datatype in the right operand i.e. '*' specifies that the input sequence can consist of multiple items.
      /orders/order instance of element()
      result:
      false()
      This expression evaluates to 'false' because there is more than one item in the left operand sequence but the right operand specifies a sequence of only one element item.
      /orders/order instance of element()*
      result:
      true()
      This expression evaluates to 'true' because the occurrence indicator on the right operand '*' allows for multiple element items in the input sequence.
      /orders/order[1]/date_received instance of xs:date
      result:
      false()
      This expression evaluates to 'false' because 'date_received' is an element.
      data(/orders/order[1]/date_received) instance of xs:date
      result:
      true()
      This expression evaluates to 'true' because the 'data' function retrieves the value in 'date_received', which is of type 'xs:date' as defined in the associated XML schema document 'orders.xsd.'
      ('hello world', 12345) instance of item()*
      result:
      true()
      This expression evaluates to 'true' because the sequence consists of 0 or more items. An 'item()' can be any atomic or node type.

      Cast as and castable Expression Examples

      'hello world' cast as xs:integer
      result:
      error
      This example attempts to cast the string 'hello world' to an 'xs:integer'. As the string 'hello world' contains characters which do not correspond to any lexical value representation of an 'xs:integer', an error is thrown.
      '8' cast as xs:integer
      result:
      8
      This example casts the string '8' to an 'xs:integer'.
      '10.0E3' cast as xs:double
      result:
      10000
      This example attempts to cast the string '10.0E3' to an 'xs:double'. As the string '10.0E3' corresponds to a permissible lexical value for the 'xs:double' datatype, the value is cast to the target datatype.
      6.5 cast as xs:integer
      result:
      6
      This example attempts to cast the 'xs:decimal' 6.5 to an 'xs:integer', and returns an 'xs:integer' with a value of 6. This example demonstrates that casting can result in a loss of data when the right operand is a type which is derived from the type of the right operand ('xs:integer' is derived from 'xs:decimal' in the XML Schema type system).
      /orders/order[1]/date_received cast as xs:dateTime
      result:
      xs:dateTime('2014-06-06T00:00:00')
      This example casts the xs:date to xs:dateTime.
      ('2014-02-31') cast as xs:date
      result:
      error
      This example attempts to cast the string '2014-02-31' to an 'xs:date', however February does not have 31 days and therefore this value cannot be cast to an 'xs:date'. An error is thrown.
      'hello world' castable as xs:integer
      result:
      false()
      This example checks whether it is possible to cast the 'xs:string' 'hello world' to an 'xs:integer'.
      '100' castable as xs:integer
      result:
      true()
      This example checks whether it is possible to cast the 'xs:string' '100' to an 'xs:integer'.