My code is working fine if I don't use function.
declare function local:samlefamily(
$pers as xs:string?) as xs:string?
{
some stuff
};
if (exists(/*/FamilyRec/Child/Link[#Ref = "IN0099"]))
then
for $family in doc("family.xml") /*/FamilyRec
where $family/Child/Link[#Ref = "IN0099"]
return if (local:samlefamily(data($family/HusbFath/Link/#Ref))) then local:samlefamily(data($family/HusbFath/Link/#Ref)) else "na1"
else "na2"
But problem occurs when I tried to define function
declare function local:giveParent($pers as xs:string) as xs:string
{if (exists(/*/FamilyRec/Child/Link[#Ref = $pers]))
then
for $family in doc("gedcom.xml") /*/FamilyRec
where $family/Child/Link[#Ref = $pers]
return if (local:samlefamily(data($family/HusbFath/Link/#Ref))) then local:samlefamily(data($family/HusbFath/Link/#Ref)) else "na1"
else "na2"
};
I am getting error:
Description: Unexpected token "< eof >" in path expression
It is not occurring for passing parameter($pers). Even I use static ("IN0099") parameter to it, same error I am getting.
Can anyone please help? Can't I use If ... else in user defined function? Advanced thanks for your support
You need to have at least one non-function statement in the xquery file, i.e. add anything after the last semicolon
Otherwise your code looks fine
Related
I have to do something like:
declare function xf:NameOfXQ($myIn as element(ns2:myIn))
as element() {
<ns0:tagIn>
<myObj>
{
for $var in $myValueOfVar
return
if ($var= "X") then
<tagA>A</tagA>
<tagB>B</tagB>
<tagC>C</tagC>
else
<tagD>D</tagD>
}
</myObj>
</ns0:tagIn>
};
But when the xquery is build, my project says "Invalid expression, expecting ELSE, found '>'"
I try then use 4 IF's, one to fill each tag, like:
declare function xf:NameOfXQ($myIn as element(ns2:myIn))
as element() {
<ns0:tagIn>
<myObj>
{
for $var in $myValueOfVar
return
if ($var= "X") then
<tagA>A</tagA>
else
()
if ($var= "X") then
<tagB>B</tagB>
else
()
if ($var= "X") then
<tagC>C</tagC>
else
()
if ($var != "X") then
<tagD>D</tagD>
else
()
}
</myObj>
</ns0:tagIn>
};
Then my project says "Invalid expression: unexpected token: if"
How I can do it correctly?
XQuery doesn't consider multiple consecutive tags as syntactically correct, an XML fragment must have a root tag to be valid.
It however allows you to use sequence types with the syntax (item1, item2, ... itemN) which you can use to let the return clause of your FLWOR expression yield multiple XML tags :
for $var in $myValueOfVar
return
if ($var= "X") then
(
<tagA>A</tagA>,
<tagB>B</tagB>,
<tagC>C</tagC>
)
else
<tagD>D</tagD>
How to call a custom xquery function in exist-db using the REST API ?
Is it possible to have more than 1 function in the xquery file ?
declare function local:toto() as node() {
return doc("/db/ProjetXML/alice.xml")/raweb/identification/projectName)
};
declare function local:pomme() as node() {
return doc("/db/ProjetXML/carmen.xml")/raweb/identification/projectSize);
};
If I call it using :
http://localhost:8080/exist/rest/db/ProjetXML/orange.xqy?_query=local:toto()
I get the following error :
err:XPST0017 Call to undeclared function: local:toto [at line 1, column 1, source: local:toto()]
Your help is appreciated.
You have syntax errors in your XQuery:
You have two functions named local:toto(). Each function must have a distinct name.
There is no semicolon following the function definition, i.e. } should be };.
Also you should remove the return expression, as there is no preceding binding.
Another option would be to parameterize the input file, e.g.:
import module namespace request="http://exist-db.org/xquery/request";
declare function local:toto($name as xs:string) as node() {
let $doc :=
if($name eq "carmen")then
doc("/db/ProjetXML/carmen.xml")
else
doc("/db/ProjetXML/alice.xml")
return
$doc/raweb/identification/projectName);
};
local:toto(request:get-parameter("name", "alice"))
You can then call this via the REST Server using a URL like:
http://localhost:8080/exist/rest/db/ProjetXML/orange.xqy?name=carmen
I am trying to return either "Empty" if it is a empty sequence or "NotEmpty" if it is not. Let's say,
for $family in doc("gedcom.xml") /*/FamilyRec
where $family/Child/Link[#Ref = "IN006"]
return if(empty(data($family))) then "Empty" else "NotEmpty"
i am getting result in oxygen: NotEmpty
which is Ok.
but let's say, there is no value for IN005
for $family in doc("gedcom.xml") /*/FamilyRec
where $family/Child/Link[#Ref = "IN005"]
return if(empty(data($family))) then "Empty" else "NotEmpty"
then it should print: Empty
but instead of printing "Empty" I am getting
Engine name: Saxon-EE XQuery 9.3.0.5
Severity: warning
Description: Your query returned an empty sequence.
Can anyone please help me. Thanks in Advance.
If I understand the issue correctly, I think the problem is that your where clause will filter out the value that you're looking for: if "IN005" doesn't exist then it will never get to the return clause.
instead you should not have a where clause and do the check in the return:
for $family in doc("gedcom.xml") /*/FamilyRec
return if($family/Child/Link[#Ref = "IN005"]) then "NotEmpty" else "Empty"
I am trying to return either "Empty" if it is a empty sequence or "NotEmpty" if it is not.
What is "it"?
I'm having trouble working out exactly what your requirements are, but it sounds to me something like:
let $result :=
for ...
where ...
return ...
return (if empty($result) then "Empty" else "Not Empty")
I am trying to use a if condition to assign a value to a variable in an xquery. I am not sure how to do this.
This is what I tried:
declare namespace libx='http://libx.org/xml/libx2';
declare namespace atom='http://www.w3.org/2005/Atom';
declare variable $entry_type as xs:string external;
let $libx_node :=
if ($entry_type = 'package' or 'libapp') then
{element {fn:concat("libx:", $entry_type)} {()} }
else if ($entry_type = 'module') then
'<libx:module>
<libx:body>{$module_body}</libx:body>
</libx:module>'
This code throws an [XPST0003] Incomplete 'if' expression error. Can someone help me fix this?
Also, can someone suggest some good tutorials to learn xqueries.
Thanks,
Sony
That's because in XQuery's conditional expression specification else-expression is always required:
[45] IfExpr ::= "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle
So you have to write second else clause (for example, it may return empty sequence):
declare namespace libx='http://libx.org/xml/libx2';
declare namespace atom='http://www.w3.org/2005/Atom';
declare variable $entry_type as xs:string external;
let $libx_node :=
if ($entry_type = ('package','libapp')) then
element {fn:concat("libx:", $entry_type)} {()}
else if ($entry_type = 'module') then
<libx:module>
<libx:body>{$module_body}</libx:body>
</libx:module>
else ()
... (your code here) ...
Some obvious bugs are also fixed:
don't need {} around computed element constructor;
most likely, you want if($entry_type = ('package', 'libapp'))
Concerning XQuery tutorials. The W3CSchools's XQuery Tutorial is a pretty good starting point.
Im new on this project and am going to write, what i thought was a simple thing. A recursive function that writes nested xml elements in x levels (denoted by a variable). So far I have come up with this, but keeps getting a compile error. Please note that i have to generate new xml , not query existing xml:
xquery version "1.0";
declare function local:PrintTest($amount)
{
<test>
{
let $counter := 0
if ($counter <= $amount )
then local:PrintTest($counter)
else return
$counter := $counter +1
}
</test>
};
local:PrintPerson(3)
My error is:
File Untitled1.xquery: XQuery transformation failed
XQuery Execution Error!
Unexpected token - " ($counter <= $amount ) t"
I never understood xquery, and cant quite see why this is not working (is it just me or are there amazingly few resources on the Internet concerning XQuery?)
You have written this function in a procedural manner, XQuery is a functional language.
Each function body can only be a single expression; it looks like you are trying to write statements (which do not exist in XQuery).
Firstly, your let expression must be followed by a return keyword.
return is only used as part of a FLWOR expression, a function always evaluates to a value. As you have written it return is equivalent to /return and so will return a node called return.
The line $counter := $counter + 1 is not valid XQuery at all. You can only set a variable like this with a let expression, and in this case it would create a new variable called counter which replaced the old one, that would be in scope only in the return expression of the variable.
The correct way to do what you are trying to do is to reduce the value of $argument each time the function recurses, and stop when you hit 0.
declare function local:Test($amount)
{
if ($amount == 0)
then ()
else
<test>
{
local:Test($amount - 1)
}
</test>
};
local:Test(3)
Note that I have changed the name of the function to Test. The name "PrintTest" was misleading, as this implies that the function does something (namely, printing). The function in fact just returns a node, it does not do any printing. In a purely functional langauge (which XQuery is quite close to) a function never has any side effects, it merely returns a value (or in this case a node).
The line $counter := $counter + 1 is valid XQuery Scripting.