Both following queries run fine on eXist-db but produce the following errors on MarkLogic server. Any help appreciated.
Query:
for $cust in //Customer[#id=1011]
for $ord in //Order[#Acct = $cust//Accounts//Account/#id/fn:string(.)]
return $ord/OrdQty/#Cash
return max($orderprice)
Error:
[1.0-ml] XDMP-UNEXPECTED: (err:XPST0003) Unexpected token syntax error, unexpected Return_, expecting $end or SemiColon_
Stack Trace
At line 10 column 0:
In xdmp:eval("xquery version "1.0-ml";
declare namespace html = ...", (), 13899855847338100900different-tr...)
8.
9. return $ord/OrdQty/#Cash
10. return max($orderprice)
Query:
for $cust in //Customer
return <Customer>
{$cust/#id}
{$cust/Name}
<Customer_Securities>
{for $account in $cust/Accounts/Account
return <Account BALANCE="{$account/Balance/OnlineActualBal}"
ACCOUNT_ID="{$account/#id}">
<Securities>
{$account/Holdings/Position/Name}
</Securities>
</Account> }
</Customer_Securities>
</Customer>
Error:
[1.0-ml] XDMP-EXPNTREECACHEFULL: for $cust in fn:collection()/descendant::Customer return { $cust/#id }{ $cust/Name }{ for $account in $cust/Accounts/Account return { $account/Holdings/Position/Name } } -- Expanded tree cache full on host gkomninos-pc.studentcom.co.uk
Stack Trace
At line 3 column 0:
In xdmp:eval("xquery version "1.0-ml";
declare namespace html = ...", (), 13899855847338100900different-tr...)
1. xquery version "1.0-ml";
2. declare namespace html = "http://www.w3.org/1999/xhtml";
3. for $cust in //Customer
4.
5. return
For the first error, that may be related to some additional syntax leeway provided by eXist; however, the for shouldn't have two returns (see XQuery spec on FLWORs) (also $orderprice is not defined):
for $cust in //Customer[#id=1011]
for $ord in //Order[#Acct = $cust//Accounts//Account/#id/fn:string(.)
return ($ord/OrdQty/#Cash, max($orderprice))
The second query is throwing an exception because it selects too much data to fit into the expanded tree cache. This will be dependent on the number of customers in your database. Is it possible to select fewer customers (i.e.: maybe this report only needs to select those with overdue balances, etc.)? Alternatively, you can generate your report in batches to avoid filling the cache.
Related
I copy paste this example from http://www.w3schools.com/xquery/xquery_functions.asp (though I added the namespace declaration):
declare namespace local="local";
declare function local:minPrice($p as xs:decimal?,$d as xs:decimal?) as
xs:decimal? {
let $disc := ($p * $d) div 100
return ($p - $disc)
};
But when I try to run it, the SAXON output is:
Error on line 6 column 1 of newq.xq:
XPST0003 XQuery syntax error near #...v 100 return ($p - $disc) };#:
Unexpected token "<eof>" in path expression
Static error(s) in query
Anyone idea? Bug in SAXON, or is it using another syntax?
Definitely not a Saxon bug. The reason for the error is the only thing in your XQuery is a function declaration; there is no expression. You're only allowed to do this if you declare it as a module.
Otherwise you'll actually have to do something in the XQuery...
declare namespace local="local";
declare function local:minPrice($p as xs:decimal?, $d as xs:decimal?) as xs:decimal? {
let $disc := ($p * $d) div 100
return ($p - $disc)
};
(:Do something...:)
local:minPrice(10,10)
Results of running this XQuery (using Saxon 9):
9
I'm using OSM 7.2.0.3 and I have cartridge with an Order Recognition Rule, with its Order Data Rule (inside Transformation tab)
In the ODR I have this XQuery code:
declare namespace im="http://xxx";
declare namespace xs="http://www.w3.org/2001/XMLSchema";
declare variable $order := fn:root(.)/im:Order;
<_root>
<Order>
{
for $moli in $order/MainOrderLineItem
return {
<OrderLineItem>
{$moli/LineItemAttributeInfo/LineItemAttribute}
</OrderLineItem>
{
for $oli in $moli/OrderLineItem
return
<OrderLineItem>
{$oli/LineItemAttributeInfo/LineItemAttribute}
</OrderLineItem>
}
}
}
</Order>
</_root>
There's no compile error in OSM, but on runtime I get:
Invalid Order Specification Fault
Order data expression failed due to oracle.communications.ordermanagement.rule.XMLRuleException
I run the OSM by submitting an XML through Web Service.
Thanks a lot for your replies.
The returned XML should actually be in parentheses instead of braces. There also needs to be a comma between the first returned OrderLineItem element and the FLWOR expression instead of wrapping it in braces:
declare namespace im="http://xxx";
declare namespace xs="http://www.w3.org/2001/XMLSchema";
declare variable $order := fn:root(.)/im:Order;
<_root>
<Order>{
for $moli in $order/MainOrderLineItem
return (
<OrderLineItem>
{$moli/LineItemAttributeInfo/LineItemAttribute}
</OrderLineItem>,
for $oli in $moli/OrderLineItem
return
<OrderLineItem>
{$oli/LineItemAttributeInfo/LineItemAttribute}
</OrderLineItem>
)
}</Order>
</_root>
I have a content.xml modelled as below
<root>
<childnode>
Some text here
</childnode>
</root>
I am trying to remove the <childnode> and update the content.xml with only the value of it
so the output looks like
<root>
Some Text here
</root>
I wrote a function to perform this but anytime I run it it gives me error as "unexpected token: modify". I was thinking of a way to accomplish this without using functx functions.
xquery version "1.0";
declare namespace request="http://exist-db.org/xquery/request";
declare namespace file="http://exist-db.org/xquery/file";
declare namespace system="http://exist-db.org/xquery/system";
declare namespace util="http://exist-db.org/xquery/util";
declare namespace response="http://exist-db.org/xquery/response";
declare function local:contentUpdate() {
let $root := collection('/lib/repository/content')//root/childNode
let $rmChild := for $child in $root
modify
(
return rename node $child as ''
)
};
local:updateTitle()
Thanks in advance
There are multiple problems with your query:
Updating functions must be declared as updating.
You're calling another function than you defined (probably you didn't notice as there still have been syntax errors).
Rename node expects some element (or processing instruction, attribute) as target, the empty string is not allowed.
At least BaseX doesn't allow updating statements when defining code as XQuery 1.0. Maybe exist doesn't care about this, try adding it if you need to know.
You do not want to rename, but replace all <childnode />s with its contents, use replace node.
This code fixes all these problems:
declare updating function local:contentUpdate() {
let $root := collection('/lib/repository/content')
return
for $i in $root//childnode
return
replace node $i with $i/data()
};
local:contentUpdate()
eXist-db's XQuery Update syntax is documented at http://exist-db.org/exist/update_ext.xml. Note that this syntax predates the release of the XQuery Update Facility 1.0, so the syntax is different and remains unique to eXist-db.
The way to do what you want in eXist-db is as follows:
xquery version "1.0";
declare function local:contentUpdate() {
let $root := doc('/db/lib/repository/content/content.xml')/root
return
update value $root with $root/string()
};
local:contentUpdate()
The primary changes, compared to your original code, are:
Inserted the eXist-db syntax for your update
Prepended '/db' to your collection name, as /db is the root of the database in eXist-db; replaced the collection() call with a doc() call, since you stated you were operating on a single file, content.xml
Changed //root to /root, since "root" is the root element, so the // (descendant-or-self) axis is extraneous
Replaced updateTitle() with the actual name of the function, contentUpdate
Removed the extraneous namespace declarations
For more on why I used $root/string(), see http://community.marklogic.com/blog/text-is-a-code-smell.
I get this error from Saxon,
Engine name: Saxon-PE XQuery 9.2.1.2
Severity: fatal
Description: XQuery syntax error in #... (:return :) let $#: expected "return", found "let"
Start location: 776:0
on this function
declare function local:set-internet-type($req1 as element(ns0:req), $cate as element()) as xs:string {
if(count( for $itm in $req/*:cust/*:inter/*:itm
where $789/*:product/*:030/*:specs/*:name/text()= data($11/INTERNET)
and $22/*:action/text()="CHANGE"
return $33)>0) then
(
for $44 in $55
where $tt/*:name/text()= data($t/INTERNET)
and $u/*:action/text()="CHANGE"
(:return <fake/>:)
let $z:= $a/*:product/*:c/*:e[1]
return concat($x,'>',$y)
) else ("")
};
I am new with xquery and I spent a lot on this error without getting a solution. Vars were masked intentionally but from the error message seems something related to the function flow.
Any help is appreciated.
Thanks in advance
Alessandro
Saxon only declares to have "partial support of XQuery 1.1". Therefore, I guess, it supports the old FLWOR format in which you cannot use let after where. Just try to swap these clauses:
for $44 in $55
let $z:= $a/*:product/*:c/*:e[1]
where $tt/*:name/text()= data($t/INTERNET)
and $u/*:action/text()="CHANGE"
return concat($x,'>',$y)
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.