1

I'm trying to query an exist-db with xquery by taking parameters from the URL and building up seach parameters

xquery version "1.0";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace xs="http://www.w3.org/2001/XMLSchema";
declare option exist:serialize "method=xml media-type=text/xml omit-xml-declaration=no indent=yes";

let $param1:= request:get-parameter("param1",'0')

let $person :=
    if($param1 = '0') 
    then "'*'"
    else concat('contributions/person/@val="',$param1,'"')

return

<xml>
{
    for $x in subsequence(//foo/bar[$person],1,3)
    return $x
}
</xml>

The code above shows that I get the parameter from the url $param1.

variable $person checks to see if there was a parameter and based on that creates a query parameter. This variable works fine, from testing it prints out either '*' for no param or

contributions/person/@val='hello, world'

When I run the query it prints out as if the value is '*'. In the for $x part, can I pass a variable like that? I've tried putting concat($person,'') with the same results. Hardcoding the full path gives me the results I'm looking for, but I'm looking to create something more dynamic.

To note: there is only one variable, $person, but there will be others once I get it to work

1
  • I think the problem is that $person is now a string and now a path. But I can't seem to not keep it as a string. Commented Oct 22, 2012 at 15:14

1 Answer 1

1

I think ideally you would avoid dynamic string evaluation. In this example, some pretty simple reorganization would solve the problem without it:

<xml>
{
  for $x in subsequence(//foo/bar[
    if ($param1 = '0')
    then *
    else (contributions/person/@val = $param1)
  ],1,3)
  return $x
}
</xml>

However, you can use eval(), but keep in mind there are security risks:

<xml>
{
  for $x in subsequence(eval(
    concat('//foo/bar[',$person,']')
  ),1,3)
  return $x
}
</xml>
Sign up to request clarification or add additional context in comments.

5 Comments

May have spoken too soon. If I wanted to check $param2 with the same expression but contribution/link/@val = 'test'. How would I do that? I did 'and if($param2 = "0")' but I get this error message :- error FORG0006: effectiveBooleanValue: first item of '(false, false)' is not a node, and sequence length > 1
@user9418 If I understand you correctly, I think you just need if (($param1 = '0') and ($param2 = '0'))
What I'm trying to achieve is more of a faceted search like pastebin.com/CYAdpUi5 but based off of your example I'm getting an error message in oxygen on the first then. When I run the query I get 'Parse error: element name containing whitespace: unexpected token: then at line: 15 column: 25'
OK, managed to get it to work pastebin.com/8jTcWjuy - performance is a bit slow. But thanks for your help
Probably not the most efficient code (referring to your pastebin link that you just said works). For example, the for loop is unnecessary - just directly call the subsequence function instead of iterating over its results just to return them all. Also, you test for whether ($param1 = '0') twice; I bet you meant the second one to test $param2, no? Lastly, you might check the "How to Optimize your Queries" article on eXist-db's site exist-db.org/exist/tuning.xml - sections 4.3 and 4.6 are applicable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.