Timmy
Timmy

Reputation: 745

Create a list using a for in XQuery 1.0

I would like to create a list of element using a for like in this example:

for $ingr in distinct-values(//Ingredient/Name)
let $res := (
  for $res2 in //Restaurant
  return if( some $ingr2 in $res2/Dish/Ingredient/Name satisfies $ingr2 eq $ingr )
    then( $res2 )
    else()
  )
return $ingr, $res

What I want to obtain is: For each ingredient return the list of restaurants that use it. I really don't understand where is the problem?

Here you can see an example: http://www.xpathtester.com/xquery/0c8f9699df404020afd07ff9f9517a46

It keep saying: ERROR - Variable $res has not been declared

Upvotes: 2

Views: 1308

Answers (3)

Gunther
Gunther

Reputation: 5256

As har07 correctly points out, parentheses are needed to get the final reference of $res into the scope of the FLWOR expression. However I think the query as you wrote it is overly complex, in particular the quantified expression can be replaced by just a path expression. Here is a simpler variant:

for $ingr in distinct-values(//Ingredient/Name)
return ($ingr, //Restaurant[Dish/Ingredient/Name = $ingr])

Upvotes: 3

har07
har07

Reputation: 89285

Your expression was read as (for ... let ... return $ingr), ($res). Which means that $res at the end is considered a different expression separate from the previous FLWOR expression, hence the undeclared variable error.

You can simply use parentheses to alter this unwanted grouping :

for $ingr in distinct-values(//Ingredient/Name)
let $res := (
  for $res2 in //Restaurant
  return if( some $ingr2 in $res2/Dish/Ingredient/Name satisfies $ingr2 eq $ingr )
    then( $res2 )
    else()
  )
return ($ingr, $res)

xpathtester demo

Upvotes: 5

Kindle Q
Kindle Q

Reputation: 944

The problem is in defining $res2 in your code
you have to change the for loop to let the child node inside the parent node

for $res2 in //Restaurant

   let $Ingredient := distinct-values(//Ingredient/Name/data()) 
                  (:This is a list of ingredients :)
   let $ingr := if (some $ingr2 in $Ingredient
satisfies (contains(lower-case($res2//Ingredient/Name), $ingr2)))
        then( $res2 )
        else()
      )
    return $ingr, $res2

Upvotes: 1

Related Questions