Switch and Typeswitch

Switch and Typeswitch Expressions

switch compares one atomized value with case values (several case lines may share a return) and falls back to default; it replaces chains of if. typeswitch dispatches on the dynamic type of a value, with sequence types such as element(title), attribute(), xs:integer, map(*) and unions written with |; the first matching case wins:

switch.xq: choosing a shelf by value and handling items by type
(: switch picks a shelf by value; typeswitch dispatches on the dynamic type of each item :)
(for $b in //book[position() le 3]
 return $b/@id || " -> " || (switch ($b/subject)
   case "Fiction" case "Science Fiction" return "fiction shelf"
   case "Technology" return "computing shelf"
   default return "general shelf")),
for $item in (//book[1]/@id, //book[1]/title, 312, 4.6, "BN-0001", map { "a": 1 }, [1, 2])
return typeswitch ($item)
  case attribute() return "attribute " || name($item)
  case element(title) return "title element"
  case xs:integer return "integer " || $item
  case xs:decimal | xs:double return "number " || $item
  case xs:string return "string " || $item
  case map(*) | array(*) return "map or array of size " || count($item?*)
  default return "something else"
Running switch and typeswitch
xquery -s:booknest-catalog.xml switch.xq
Output
"b1 -> fiction shelf"
"b2 -> computing shelf"
"b3 -> general shelf"
"attribute id"
"title element"
"integer 312"
"number 4.6"
"string BN-0001"
"map or array of size 1"
"map or array of size 2"

Order the case branches from specific to general: 312 is an xs:integer and also an xs:decimal, so the integer branch must come first. typeswitch is how XQuery code walks mixed content or the output of parse-json() safely, and it is the XQuery counterpart of XSLT's template matching (XSLT Templates and Modules).