Boolean value not assignable in xquery - xquery

let $my_val as xs:boolean := fn:true
return $my_val
This returns context undefined error.
Not understanding why.
I also tried this:
let $my_val as xs:boolean := (1 = 1)
return $my_val
With success

Just a small type-o.
fn:true() is a function.
You have fn:true, so it thinks you trying to reference an element named true in the fn namespace without a context node to anchor to.
let $my_val as xs:boolean := fn:true()
return $my_val

Related

Handling undefined number of external variables

I'm using baseX in a REST environment and I'm quite stuck trying to run an .xq script with an undefined number of GET variables (could be 1 but could be 10)
I'd like to make my xq script generic about that and construct my query independently.
Is there a way to achieve that, playing with array or sending differently my variables, or I dunno how ?
here is my API call
http://basex:8984/rest/?run=WEB-INF/data/test.xq&$tag=p&value=sciences&tag2=p&value2=test&tag3=testdzq
here is my text.xq
declare variable $tag external;
declare variable $value external;
declare variable $tag2 external;
declare variable $value2 external;
<documents>
{for $doc in collection("testdb2")
where $doc//*[name() eq $tag]/text()[matches(., $value )]
and $doc//*[name() eq $tag2]/text()[matches(., $value2 )]
return <doc>{$doc//titleStmt/title/text()}</doc>
}
</documents>
Thanks !
found this here (see http-params function) https://www.balisage.net/Proceedings/vol18/print/Murray01/BalisageVol18-Murray01.html
(: BaseX example :)
(: In the controller ... :)
module namespace c = "http://balisage.net/ns/Bal2016murr0319/controller";
import module namespace request = "http://exquery.org/ns/request";
import module namespace item = "http://balisage.net/ns/Bal2016murr0319/views/item" at "views/item.xqm";
(:~ Returns a map containing the HTTP request parameters. :)
declare function c:http-params()
as map(*)
{
map:merge(
for $name in request:parameter-names()
let $value := request:parameter($name)
return map:entry($name, $value)
)
};
(:~ Calls the appropriate view, based on user input. :)
declare function c:get-view()
as element(html)
{
(: get HTTP request parameters :)
let $params := c:http-params()
return
if (map:get($params, "id")) then
(: the presence of "id" indicates that the user is requesting the item-level page for this unique identifier :)
(: call the item-level view :)
item:get-html($params)
else if ... (: call some other view :)
else if ... (: call some other view :)
else (: call the view for the home page ... :)
};

getting this error while migrating from xquery 2004 to xquery 1.0 version

//Invalid Xquery content:line 89, column 44: {http://www.w3.org/2005/xqt-errors}XPST0003 [{http://xmlns.oracle.com/xdk/xquery/error}XPST0003c]: Syntax error. "/ns1:produ" is unexpected
Xquery after migrating to 1.0 V
xquery version "1.0";
(: Caring Included Logic Reset/#actioncode :)
(: Caring Fix#358 :)
(: Included CR for Project Caring :)
(: Added a xf:escape-dot function as a part of Jan - Break Fix :)
(: Included changes for Project Caring :)
(: Included mapping for accountGroups - CUG Migration :)
(: Included changes for Project AggregatedAlerts :)
(:: pragma bea:global-element-parameter parameter="$manageServiceOrder" element="ns3:manageServiceOrder" location="../../schemas/pf.bil.BillingProvisioning_3.0.xsd" ::)
(:: pragma bea:global-element-return element="ns0:CreateOrderCustomerRequest" location="../../../../resources_3.0/util/BRMAdapter/interfaces/InfranetUtilityCreate.xsd" ::)
declare namespace ns2 = "http://vodafone.com.au/ebo/vha/ProvisioningAndFulfilmentComponents/V3.0";
declare namespace ns1 = "http://vodafone.com.au/ebo/vha/CommonComponents/V3.0";
declare namespace ns3 = "http://vodafone.com.au/pf/bil/ebm/BillingProvisioning/V3.0";
declare namespace ns0 = "http://www.vodafone.co.au/infranetUtilityCreate/schema";
declare namespace xf = "http://tempuri.org/pf.bil_3.0/resources/billingProvisioning/BRM/EBO.SyncSubscription.billingProvisioning_xForm_BRM.createOrder/";
declare namespace temp = "http://www.w3.org/2001/XMLSchema";
declare xqse function xf:formatDateTimes($dateTime as element(*)*) as xs:dateTime?
{
declare $dateTimeValue :=data($dateTime);
try
{
return value (xs:dateTime(replace(fn-bea:dateTime-to-string-with-format("yyyyMMddHHmmss",$dateTimeValue),"^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$","$1-$2-$3T$4:$5:$6")));
}
catch (* into $err, $msg)
{
return value (xs:dateTime(replace(fn-bea:date-to-string-with-format("yyyyMMdd",$dateTimeValue),"^(\d{4})(\d{2})(\d{2})$","$1-$2-$3T00:00:00")));
};
};
declare xqse function xf:isValidChargeShareAtribute( $chargeShareLines as element(*)) as xs:boolean?
{
try
{
iterate $attribute over $chargeShareLines/ns1:productService/ns1:attributes/ns1:attribute[fn:upper-case(ns1:name/text()) eq "CSG REFERENCE" or fn:upper-case(ns1:name/text()) eq "CSG SPONSORSHIP"]
{
if (
( ($attribute/ns1:value ne "" and $chargeShareLines/#actionCode eq "New")
or
$chargeShareLines/#actionCode eq "Modified"
or
($attribute/ns1:value ne "" and $chargeShareLines/#actionCode eq "Deleted")
)
) then return value (fn:boolean("true")) else return value( (fn:boolean("false")));
};
}
catch (* into $err, $msg)
{ return value (fn:boolean("false"));
};
};
declare function xf:lookupDVMWrapper($dvmName as xs:string, $sourceColumn as xs:string,$sourceValue as xs:string, $targetColumn as xs:string, $needAnException as xs:boolean)as element(*)
{
let $dvmres :=(fn-bea:lookupDVM($dvmName,$sourceColumn,$sourceValue,$targetColumn,'NO DATA FOUND'))
return
if ((($dvmres='') or ($dvmres='NO DATA FOUND')) and $needAnException)
then
<dvmresp>
<dvmexception>
{
concat($sourceValue,' for ',$sourceColumn,' in ',$dvmName,'.dvm', ' not found' )
}
</dvmexception>
</dvmresp>
else if((($dvmres='') or ($dvmres='NO DATA FOUND')) and not($needAnException))
then
<dvmresp></dvmresp>
else
<dvmresp>
{
$dvmres
}
</dvmresp>
};
declare function xf:formatDate( $dateTime as element(*)*) as xs:dateTime?
{
let $dateTimeValue :=data($dateTime)
return xs:dateTime(replace(fn-bea:date-to-string-with-format("yyyyMMdd",$dateTimeValue),"^(\d{4})(\d{2})(\d{2})$","$1-$2-$3T00:00:00"))
};
declare function xf:calculateVFPeriodEndDate($manageServiceOrder as element (*),$serviceLines as element(*))
as xs:dateTime? {
if ($serviceLines/#actionCode eq "Deleted" or $serviceLines/#actionCode eq "Suspended")
then xf:formatDateTimes(element{"billEffectiveDate"}{ $manageServiceOrder/ns3:serviceOrder/ns2:billingDetails/ns2:billEffectiveDate/text()})
else if (fn:string-length(data($serviceLines/ns1:productService/ns1:periodEndDate)) >0 and data($serviceLines/ns1:productService/ns1:periodEndDate) ne "")
then xf:formatDate( element { "periodEndDate" } {if(fn:contains(data($serviceLines/ns1:productService/ns1:periodEndDate),"T"))then
fn:substring-before(data($serviceLines/ns1:productService/ns1:periodEndDate),"T")
else
$serviceLines/ns1:productService/ns1:periodEndDate/text()})
else if (
for $expiryDate in $serviceLines/ns1:productService/ns1:attributes/ns1:attribute[ns1:name/text() eq "Expiry Date"]/ns1:value/text()
return
if (fn:string-length($expiryDate) >0) then xf:formatDateTimes( element { "expiryDate" } {$expiryDate}) else() )
then
(
for $expiryDate in $serviceLines/ns1:productService/ns1:attributes/ns1:attribute[fn:upper-case(ns1:name/text()) eq "EXPIRY DATE"]/ns1:value/text()
return xf:formatDateTimes( element { "expiryDate" } {$expiryDate})
)
else ()
};
There are several things here that aren't allowed in XQuery 1.0. The ones that stand out are:
declare $dateTimeValue :=data($dateTime);
You can't declare local variables like that. You need let $v := expr return XXX.
return value (xs:dateTime(...);
The keyword return value is wrong and should be removed.
iterate $attribute over $chargeShareLines
I've no idea what the iterate expression does, but it's not XQuery. Looks like some variant of a for expression, but I don't know how it differs.
try {
requires XQuery 3.0/3.1, and the syntax is slightly different from yours.

How to evaluate the query by supplying a variable whose value is evaluated at runtime?

I have a piece of code where I want to return total number of documents in a specific forest. I want to determine whether a forest doc count is 0 or more.
declare function local:forest-doc-count($db-name,
$f-id as xs:unsignedLong) as xs:integer {
let $_ := xdmp:log(xdmp:describe(fn:concat("$db-name -->", $db-name), (),()))
let $query := 'xquery version "1.0-ml";
declare variable $f-id as xs:unsignedLong external;
xdmp:estimate(cts:search(fn:doc(), (), (), (), $f-id))'
let $count := xdmp:eval($query , (),
map:entry("f-id", $f-id),
map:entry("database", xdmp:database($db-name))
)
return $count
};
where $f-id is forest Id and $db-name is Database name. For now I'm getting
Undefined variable $f-id
Declare an external variable in the query and then bind a value to the external variable in the call.
The following sketch is untested, but something along these lines should work:
declare function local:forest-doc-count(
$db-name as xs:string,
$f-id as xs:unsignedLong
) as xs:integer {
xdmp:eval(
'xquery version "1.0-ml";
declare variable $f-id as xs:unsignedLong external;
xdmp:estimate(cts:search(fn:doc(), (), (), (), $f-id))',
map:entry("f-id", $f-id),
map:entry("database", xdmp:database($db-name))
)
};
A footnote: You might want to declare the type of parameters and return values when they are determinate to take advantage of type checking.
Hoping that's useful,

Pass a map to External function

I have the following module
xquery version "1.0-ml";
declare variable $datasets as map:map external;
...
I want to call this so I do an xdmp:invoke like this
...
let $update := xdmp:invoke("/app/lib/my-module.xqy", (xs:QName("datasets"), $map), <options xmlns="xdmp:eval">
<modules>{xdmp:modules-database()}</modules>
</options>)
...
$map is of type map:map.
Running this gives me the following error
[1.0-ml] XDMP-ARG: xdmp:invoke("/app/lib/20140527-0916-copy-y-axis-labels-from-chart-to-dataset-...", fn:QName("", "datasets"), <options xmlns="xdmp:eval"><modules>0</modules></options>) -- Invalid argument
Why is that?
It's hard to know for sure from the limited code samples you've posted, but I think that your $map variable is bound to the empty sequence (the rough analogue of null in XPath/XQuery).
I've created the following main module, that simply returns the external variable $datasets:
xquery version "1.0-ml";
declare variable $datasets as map:map external;
$datasets
Invoking it as follows works correctly:
let $map := map:entry("key", "value")
return
xdmp:invoke("/test.xqy",
(xs:QName("datasets"), $map),
<options xmlns="xdmp:eval">
<modules>{xdmp:modules-database()}</modules>
</options>)
This results in the "invalid argument" error:
let $map := ()
return
xdmp:invoke("/test.xqy",
(xs:QName("datasets"), $map),
<options xmlns="xdmp:eval">
<modules>{xdmp:modules-database()}</modules>
</options>)
XQuery flattens sequences (they don't nest like s-expressions), so when $map is the empty sequence, the <options/> element becomes the value of the $datasets param, which is an invalid value for the external variable.
Update: Doh! #mblakele's comments below explain the error conditions ...
TL;DR: () is not an instance of map:map.

Recursive function returning boolean, with a for loop inside

My data is a binary tree, and will check through every child, returning true if it finds the data i want, if not, it keeps looking for it.
In some way i want to return the variable #exists or something.. Well anyone might have a solution for my problem. I was thinking something like this but i couldn't get it to work! (code-snippet)
declare function local:test($id as xs:integer, $topic as xs:integer) as xs:boolean {
let $exists := fn:false()
for $x in ...
return
if .. then
set exists to fn:true()
else
set exists to exists OR local:test($x,$topic)
return #exists in some way
};
This is a case for an XQuery quantified expression. Using that, your function translates to
declare function local:test($id as xs:integer, $topic as xs:integer) as xs:boolean
{
some $x in ...
satisfies
if (..) then
fn:true()
else
local:test($x,$topic)
};
As it was already mentioned XQuery is a functional language. You can't just set variable and return it. Your query can be though rewritten like:
declare function local:test($id as xs:integer, $topic as xs:integer) as xs:boolean {
exists(for $x in ...
where (: here is condition expression on $x :)
return $x)
};
Function exists(Expr) returns true if the value of Expr is not the empty sequence; otherwise, the function returns false.
In this case exists returns true if there is $x which meets specified condition.
You cannot change the values of variables in xquery.
Is your whole function not just this:
declare function local:test($topic as xs:integer) as xs:boolean {
... OR local:test($topic/...)
};

Resources