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 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"xquery -s:booknest-catalog.xml switch.xqOutput
"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).