Reputation: 13
I want to produce an XQuery that outputs the price of three CDs, less the price of the cheapest CD. I have produced a user defined function sumtwomax() which takes three integer parameters and produces the sum of the largest two numbers. This works when I supply it with numbers. But I have a problem when supplying it with variables from a FLWOR expression. Could someone please help me with this?
Here is my XML code:
<items>
<item>
<code>c002</code>
<price>10</price>
<rating>5</rating>
</item>
<item>
<code>c006</code>
<price>15</price>
<rating>3</rating>
</item>
<item>
<code>c004</code>
<price>12</price>
<rating>3</rating>
</item>
<item>
<code>c001</code>
<price>7</price>
<rating>5</rating>
</item>
<item>
<code>c003</code>
<price>10</price>
<rating>4</rating>
</item>
<item>
<code>c005</code>
<price>8</price>
<rating>4</rating>
</item>
</items>
And here is my XQuery:
declare namespace myfn = "http://www.brookes.ac.uk/P00601/xquery/functions";
declare function myfn:sumtwomax( $first, $sec, $third) { sum(($first, $sec, $third)) - min (($first, $sec, $third))};
for $d in doc("shop.xml") //item
let $price1 := xs:integer($d/price/data()[$d/code="c002"])
let $price2 := xs:integer($d/price/data()[$d/code="c004"])
let $price3 := xs:integer($d/price/data()[$d/code="c006"])
return
myfn:sumtwomax($price1, $price2, $price3)
This produces '0 0 0' as a result, instead of the desired value '15'. Could someone please help with this?
Upvotes: 1
Views: 714
Reputation: 295619
A FLWOR expression doesn't make any sense in this context: It's only evaluating a single item
at a time (and return
ing one result per item
), but the expressions you run inside that loop only return useful results if they can search through all the items, to be able to fill out all three variables (as opposed to only the variable associated with the single item being iterated over by the loop at that time).
Consider instead iterating over items
elements (of which there's only one), if you really want to make this a FLWOR:
declare function myfn:sumtwomax( $first, $sec, $third) { sum(($first, $sec, $third)) - min (($first, $sec, $third))};
for $d in //items
let $price1 := xs:integer($d/item[code="c002"]/price)
let $price2 := xs:integer($d/item[code="c004"]/price)
let $price3 := xs:integer($d/item[code="c006"]/price)
return myfn:sumtwomax($price1, $price2, $price3)
...or, removing the needless for
entirely:
declare function myfn:sumtwomax( $first, $sec, $third) { sum(($first, $sec, $third)) - min (($first, $sec, $third))};
let $price1 := xs:integer(//item[code="c002"]/price)
let $price2 := xs:integer(//item[code="c004"]/price)
let $price3 := xs:integer(//item[code="c006"]/price)
return myfn:sumtwomax($price1, $price2, $price3)
Upvotes: 2