XQuery
Priscilla Walmsley (pwalmsley@datypic.com)
ISBN: 1491915103
2nd edition, , O'Reilly Media, Inc.
Chapter 9: Advanced Queries
Please note that the book contains many inline examples and informal tables that are not provided here.
let $count := 0 for $prod in doc("catalog.xml")//product[@dept = ("ACC", "WMN")] let $count := $count + 1 return <p>{$count}. {data($prod/name)}</p>
<p>1. Fleece Pullover</p> <p>1. Floppy Sun Hat</p> <p>1. Deluxe Travel Bag</p>
for $prod in doc("catalog.xml")//product[@dept = ("ACC", "WMN")] return <p>{$prod/position()}. {data($prod/name)}</p>
for $prod at $count in doc("catalog.xml")//product[@dept = ("ACC", "WMN")] return <p>{$count}. {data($prod/name)}</p>
<p>1. Fleece Pullover</p> <p>2. Floppy Sun Hat</p> <p>3. Deluxe Travel Bag</p>
for $prod at $count in doc("catalog.xml")//product where $prod/@dept = ("ACC", "MEN") order by $prod/name return <p>{$count}. {data($prod/name)}</p>
<p>4. Cotton Dress Shirt</p> <p>3. Deluxe Travel Bag</p> <p>2. Floppy Sun Hat</p>
let $sortedProds := for $prod in doc("catalog.xml")//product where $prod/@dept = "ACC" or $prod/@dept = "MEN" order by $prod/name return $prod for $sortedProd at $count in $sortedProds return <p>{$count}. {data($sortedProd/name)}</p>
<p>1. Cotton Dress Shirt</p> <p>2. Deluxe Travel Bag</p> <p>3. Floppy Sun Hat</p>
xquery version "3.0"; for $prod in doc("catalog.xml")//product where $prod/@dept = ("ACC", "MEN") order by $prod/name count $count return <p>{$count}. {data($prod/name)}</p>
xquery version "3.0"; for $prod in doc("prices.xml")//prod order by $prod/price/number(.) descending count $count where $count <= 2 return <p>{$count}. {data($prod/price)}</p>
<p>1. 69.99</p> <p>2. 39.99</p>
xquery version "3.0"; for $item in doc("order.xml")//item group by $d := $item/@dept count $count return <p>{concat("Group ", $count, ": ", $d)}</p>
<p>Group 1: ACC</p> <p>Group 2: MEN</p> <p>Group 3: WMN</p>
<p>{ let $prods := doc("catalog.xml")//product let $numProds := count($prods) for $prod at $count in $prods return if ($count = $numProds) then concat($prod/name, ".") else concat($prod/name, ",") }</p>
<p>Fleece Pullover, Floppy Sun Hat, Deluxe Travel Bag, Cotton Dress Shirt.</p>
<p>{ let $prods := doc("catalog.xml")//product for $prod in $prods return if ($prod is $prods[last()]) then concat($prod/name, ".") else concat($prod/name, ", ") }</p>
xquery version "3.0"; for tumbling window $w in (1, 4, 3, 12, 5, 13, 8) start $s when $s mod 2 = 0 return <window>{$w}</window>
<window>4 3</window> <window>12 5 13</window> <window>8</window>
xquery version "3.0"; let $props := <properties> <propname>x</propname> <value>xval</value> <alt-value>xval2</alt-value> <propname>y</propname> <value>yval</value> <alt-value>yval2</alt-value> </properties> for tumbling window $w in $props/* start $s when name($s) = 'propname' end $e when name($e) = 'value' return <property>{$w}</property>
<property> <propname>x</propname> <value>xval</value> </property> <property> <propname>y</propname> <value>yval</value> </property>
xquery version "3.0"; for tumbling window $w in (1, 4, 3, 12, 5, 13, 8) start at $s-pos when true() end at $e-pos when $e-pos - $s-pos = 2 return <window>{$w}</window>
<window>1 4 3</window> <window>12 5 13</window> <window>8</window>
xquery version "3.0"; for tumbling window $w in (1, 4, 3, 12, 5, 13, 8) start at $s-pos when true() only end at $e-pos when $e-pos - $s-pos = 2 return <window>{$w}</window>
<window>1 4 3</window> <window>12 5 13</window>
xquery version "3.0"; for tumbling window $w in doc("order.xml")//item start $s previous $s-prev when $s/@dept != $s-prev/@dept return (<p>Department {data($s/@dept)}</p>, $w)
<p>Department ACC</p> <item dept="ACC" num="563" quantity="1"/> <item dept="ACC" num="443" quantity="2"/> <p>Department MEN</p> <item dept="MEN" num="784" quantity="1" color="white"/> <item dept="MEN" num="784" quantity="1" color="gray"/> <p>Department WMN</p> <item dept="WMN" num="557" quantity="1" color="black"/>
xquery version "3.0"; for tumbling window $w in doc("order.xml")//item start $s when true() end $e next $e-next when string($e/@dept) != string($e-next/@dept) return (<p>Department {data($s/@dept)}</p>, $w)
<p>Department WMN</p> <item dept="WMN" num="557" quantity="1" color="navy"/> <p>Department ACC</p> <item dept="ACC" num="563" quantity="1"/> <item dept="ACC" num="443" quantity="2"/> <p>Department MEN</p> <item dept="MEN" num="784" quantity="1" color="white"/> <item dept="MEN" num="784" quantity="1" color="gray"/> <p>Department WMN</p> <item dept="WMN" num="557" quantity="1" color="black"/>
xquery version "3.0"; for sliding window $w in (1, 4, 3, 12, 5, 13, 8) start at $s-pos when true() only end at $e-pos when $e-pos - $s-pos = 2 return <window>{$w}</window>
<window>1 4 3</window> <window>4 3 12</window> <window>3 12 5</window> <window>12 5 13</window> <window>5 13 8</window>
declare namespace functx = "http://www.functx.com"; declare function functx:add-attributes ( $elements as element()*, $attrNames as xs:QName*, $attrValues as xs:anyAtomicType* ) as element()* { for $element in $elements return element { node-name($element)} { for $attrName at $seq in $attrNames return if ($element/@*[node-name(.) = $attrName]) then () else attribute {$attrName} {$attrValues[$seq]}, $element/@*, $element/node() } };
declare namespace functx = "http://www.functx.com"; declare function functx:remove-attributes ($elements as element()*, $names as xs:string*) as element()* { for $element in $elements return element {node-name($element)} {$element/@*[not(name() = $names)], $element/node() } };
declare namespace functx = "http://www.functx.com"; declare function functx:remove-attributes-deep ($nodes as node()*, $names as xs:string* ) as node()* { for $node in $nodes return if ($node instance of element()) then element { node-name($node)} { $node/@*[not(name() = $names)], functx:remove-attributes-deep($node/node(), $names)} else if ($node instance of document-node()) then functx:remove-attributes-deep($node/node(), $names) else $node };
declare namespace functx = "http://www.functx.com"; declare function functx:remove-elements-deep ($nodes as node()*, $names as xs:string*) as node()* { for $node in $nodes return if ($node instance of element()) then if (name($node)=$names) then () else element { node-name($node)} { $node/@*, functx:remove-elements-deep($node/node(), $names)} else if ($node instance of document-node()) then functx:remove-elements-deep($node/node(), $names) else $node };
declare namespace functx = "http://www.functx.com"; declare function functx:remove-elements-not-contents ($nodes as node()*, $names as xs:string*) as node()* { for $node in $nodes return if ($node instance of element()) then if (name($node) = $names) then functx:remove-elements-not-contents($node/node(), $names) else element {node-name($node)} {$node/@*, functx:remove-elements-not-contents($node/node(), $names)} else if ($node instance of document-node()) then functx:remove-elements-not-contents($node/node(), $names) else $node };
declare namespace functx = "http://www.functx.com"; declare function functx:change-element-names-deep ($nodes as node()*, $oldNames as xs:QName*, $newNames as xs:QName*) as node()* { if (count($oldNames) != count($newNames)) then error(xs:QName("Different_Number_Of_Names")) else for $node in $nodes return if ($node instance of element()) then let $newName := if (node-name($node) = $oldNames) then $newNames[index-of($oldNames, node-name($node))] else node-name($node) return element {$newName} {$node/@*, functx:change-element-names-deep($node/node(), $oldNames, $newNames)} else $node };
declare namespace functx = "http://www.functx.com"; let $order := doc("order.xml")/order let $oldNames := (xs:QName("order"), xs:QName("item")) let $newNames := (xs:QName("purchaseOrder"), xs:QName("purchasedItem")) return functx:change-element-names-deep($order, $oldNames, $newNames)
<purchaseOrder num="00299432" date="2015-09-15" cust="0221A"> <purchasedItem dept="WMN" num="557" quantity="1" color="navy"/> <purchasedItem dept="ACC" num="563" quantity="1"/> <purchasedItem dept="ACC" num="443" quantity="2"/> <purchasedItem dept="MEN" num="784" quantity="1" color="white"/> <purchasedItem dept="MEN" num="784" quantity="1" color="gray"/> <purchasedItem dept="WMN" num="557" quantity="1" color="black"/> </purchaseOrder>
let $cat := doc("catalog.xml")/catalog for $dept in distinct-values($cat/product/@dept) return <li>Department: {if ($dept = "ACC") then "Accessories" else if ($dept = "MEN") then "Menswear" else if ($dept = "WMN") then "Womens" else () } ({$dept})</li>
<li>Department: Womens (WMN)</li> <li>Department: Accessories (ACC)</li> <li>Department: Menswear (MEN)</li>
let $deptNames := <deptNames> <dept code="ACC" name="Accessories"/> <dept code="MEN" name="Menswear"/> <dept code="WMN" name="Womens"/> </deptNames> let $cat := doc("catalog.xml")/catalog for $dept in distinct-values($cat/product/@dept) return <li>Department: {data($deptNames/dept[@code = $dept]/@name) } ({$dept})</li>
let $tempResults:= for $item in doc("order.xml")//item, $prod in doc("catalog.xml")//product where $item/@num = $prod/number return <item num="{$item/@num}" name="{$prod/name}" color="{$item/@color}" quant="{$item/@quantity}"/> return <table> <tr> <th>#</th><th>Name</th><th>Color</th><th>Quan</th> </tr> {for $lineItem in $tempResults return <tr> <td>{data($lineItem/@num)}</td> <td>{data($lineItem/@name)}</td> <td>{data($lineItem/@color)}</td> <td>{data($lineItem/@quant)}</td> </tr> } </table>
<item num="557" color="navy" name="Fleece Pullover" quant="1"/> <item num="563" color="" name="Floppy Sun Hat" quant="1"/> <item num="443" color="" name="Deluxe Travel Bag" quant="2"/> <item num="784" color="white" name="Cotton Dress Shirt" quant="1"/> <item num="784" color="gray" name="Cotton Dress Shirt" quant="1"/> <item num="557" color="black" name="Fleece Pullover" quant="1"/>
<table> <tr> <th>#</th><th>Name</th><th>Color</th><th>Quan</th> </tr> <tr> <td>557</td> <td>Fleece Pullover</td> <td>navy</td> <td>1</td> </tr> <!-- ... --> </table>