D A T Y P I C
XQuery

XQuery

Priscilla Walmsley (pwalmsley@datypic.com)
ISBN: 0596006349
1st edition, 2007, O'Reilly Media, Inc.
Amazon.com
Buy at 37% off list price


Chapter 15: Principles of Query Design

Example 15-1. Making use of whitespace

Less Clear Query

for $product in doc("catalog.xml")//product return
<product><number>{$product/number}</number>
<price>{for $price in doc("prices.xml")//prod
where $product/number = $price/@num
return $price/price}</price>
</product>

More Clear Query

for    $product in doc("catalog.xml")//product
return <product>
         <number>{$product/number}</number>
         <price>{for    $price in doc("prices.xml")//prod
                 where  $product/number = $price/@num
                 return $price/price}</price>
       </product>


Example 15-2. Documenting a function with xqdoc

(:~
: The <b>functx:substring-after-last</b> function returns the part
: of <b>$string</b> that appears after the last occurrence of
: <b>$delim</b>. If <b>$string</b> does not contain
: <b>$delim</b>, the entire string is returned.
:
: @param $string the string to substring
: @param $delim the delimiter
: @return the substring
:)
declare function functx:substring-after-last
($string as xs:string?, $delim as xs:string) as xs:string?
 { ...  };


Example 15-3. Avoid re-evaluating the same expression

Less Efficient Query

if (doc("prices.xml")/prices/priceList/prod[price < 30])
then <bargain-bin>{
       doc("prices.xml")/*/priceList/prod[price < 30]
     }</bargain-bin>
else ()

More Efficient Query

let $bargains := doc("prices.xml")/prices/priceList/prod[price < 30]
return if ($bargains)
       then <bargain-bin>{$bargains}</bargain-bin>
       else ()


Example 15-4. Avoid unnecessary sorting

Less Efficient Query

let $doc := doc("catalog.xml")
return $doc//number | $doc//name

More Efficient Query

unordered {
  let $doc := doc("catalog.xml")
  return $doc//(number|name)
}


Example 15-5. Avoid expensive path expressions

Less Efficient Query

doc("catalog.xml")//number

More Efficient Query

doc("catalog.xml")/catalog/product/number


Example 15-6. Use predicates instead of where clauses

Less Efficient Query

for $prod in doc("catalog.xml")//product
where $prod/@dept = "ACC"
order by $prod/name
return $prod/name

More Efficient Query

for $prod in doc("catalog.xml")//product[@dept = "ACC"]
order by $prod/name
return $prod/name


Useful Function. if-absent (see also functx:if-absent)

declare namespace functx = "http://www.functx.com";
declare function functx:if-absent (
  $node as node()?, $value as xs:anyAtomicType) as xs:anyAtomicType*
{
  if ($node)
  then data($node)
  else $value
};

(: Example call :)
for $prod in doc("prices.xml")//prod
return $prod/price - functx:if-absent($prod/discount, 0)


Useful Function. if-empty (see also functx:if-empty)

declare namespace functx = "http://www.functx.com";
declare function functx:if-empty (
  $node as node()?, $value as xs:anyAtomicType) as xs:anyAtomicType*
{
  if (string($node) != "")
  then data($node)
  else $value
};

(: Example call :)
for $prod in doc("prices.xml")//prod
return $prod/price - functx:if-empty($prod/discount, 0)