xquery empty sequence how to handle - xquery

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")

Related

xquery to check if the value is null then return null as string

I am new to XQuery. Please guide me to solve the issue below I want to return the null value as a string, if the below expression does not give any value.
Currently, the output doesn't show the 'name' field itself. I want to have a name with null. for eg-
if (IsNull(expression),null,expression)
$output.dataAccessResponse[1]/*:row/*:name/text()
You could use the fn:exists() function to test whether or not there is a text() node.
exists($output.dataAccessResponse[1]/:row/:name/text())
You could also use the fn:boolean() function to test the effective boolean value of the node.
boolean($output.dataAccessResponse[1]/:row/:name/text())
If you wanted to test whether or not there was a significant value i.e. something other than whitespace, you can fn:normalize-space() in a predicate, to ensure that only text() nodes that have meaningful text are selected, and then test fn:exists().
exists($output.dataAccessResponse[1]/:row/:name/text()[normalize-space()])
XQuery doesn't have null, so if you are asking what to return to indicate null, then you would want to return an empty sequence () instead of null.
So, you could execute something like this:
let $name := $output.dataAccessResponse[1]/:row/:name/text()
return
if (fn:exists($name))
then $name
else ()
But at that point, it's really the same as just attempting to select the text() with that XPath and it will either return the text() node or an empty sequence:
$output.dataAccessResponse[1]/:row/:name/text()

returning result from binary search tree

I'm trying to determine if a value is found in the binary search tree.
If it's found, the value is printed. If not, a message is printed saying it wasn't found.
My problem is that even when the value is found, the message is printed saying that it wasn't found.
My result seems to reset even after returning True, and I am confused as to why this is happening... I think it's because I'm calling the function recursively, but I don't know how to fix this problem. Any help would be appreciated, thank you.
def lookUpVal(bst,val,result):
if bst == None:#base case, if the tree is 0, return none
return
elif bst['data'] == val:
print ("value found")
result = True
return result
lookUpVal(bst['left'],val,result)
lookUpVal(bst['right'],val,result)
def main(bst):
print ("Enter the value you want to find")
val = int(input())
result = 0
lookUpVal(bst,stud,result)
if result != True:
print ("Value not found")
The problem is with your result variable, you probably think you are passing by reference, what is actually happening is close to pass-by-value.
Here is an example:
def voo(x):
print('x:',id(x))
x = True
print('x:',id(x))
p = False
print('p:',id(p))
voo(p)
print('value of p:',p)
print('p:',id(p))
'id' returns a unique id for any object, including of course boolean ones.
Here's the output: (numbers will vary in your pc)
p: 1613433952
x: 1613433952
x: 1613433936
value of p: False
p: 1613433952
First note, False in output, p's value has not changed. But to see why that's happening, closely examine the id values, specially how x's id changed after assignment in function; which means python allocated a new object. And old one is still referenced by 'p', as evident in it's output, which has not changed.

Parsing an array of dates in XQuery (MarkLogic v8 flavour)

My question seems trivial but could not figure out how to parse a string that contains a list of dates separated by commas. The parsing part of individual dates is not an issue but the empty values are. The trouble is the order of the dates are significant and some dates can be omitted. The dates are expected to be formatted in YYYY-mm-dd
So, the following are valid inputs and expected return values:
,2000-12-12,2012-05-03, ➔ ( NULL, 2000-12-12, 2012-05-03, NULL )
2000-12-12,,2012-05-03 ➔ ( 2000-12-12, NULL, 2012-05-03 )
And here is my function signature
declare function local:assert-date-array-param(
$input as xs:string
, $accept-nulls as xs:boolean?
) as xs:date*
I recognised the problem after realizing that there seems to be no equivalent of of NULL in XQuery for the returned values as placeholders for omitted dates, if you want to return a sequence, that is. Because empty sequences wrapped inside sequences are flattened to nothing.
I suppose, my fallback would be to use date like 1900-01-01 as the placeholder or return a map instead of a sequence, but I sure hope to find a more elegant way
Thank you,
K.
PS. I am working with MarkLogic v8 (and v9 soon) and any solution should execute with their XQuery processor.
UPDATE: thanks for both answers, in the end I chose to go with a placeholder date as XQuery works so nicely with sequences and anything else would have required some changes in other places. But the problem remains for the cases where the required return values are numerics. In this case, use of placeholder values would probably be not feasible. A null literal for xs:anyAtomicType would have solved the problem nicely, but alas.
You could consider returning a json:array(), or an array-node{} with null-node{}'s inside. But perhaps a null-date placeholder is not as bad as it sounds:
declare variable $null-date := xs:date("0001-01-01");
declare function local:assert-date-array-param(
$input as xs:string,
$accept-nulls as xs:boolean?
) as xs:date*
{
for $d in fn:tokenize($input, "\s*,\s*")
return
if ($d eq "") then
if ($accept-nulls) then
$null-date
else
fn:error(xs:QName("NULL-NOT-ALLOWED"), "Date is required")
else
if ($d castable as xs:date) then
xs:date($d)
else if ($d castable as xs:dateTime) then
xs:date(xs:dateTime($d))
else
fn:error(xs:QName("INVALID-DATE"), "Invalid date format: " || $d)
};
declare function local:print-date-array($dates) {
string-join(for $d in $dates return if ($d eq $null-date) then "NULL" else fn:string($d), ", ")
};
local:print-date-array(
local:assert-date-array-param(",2000-12-12,2012-05-03,", fn:true())
),
local:print-date-array(
local:assert-date-array-param("2000-12-12,,2012-05-03", fn:true())
)
HTH!
Multiple options .. in addition to above.
return a sequence of functions which when invoked return dates
for $i in string-tokenize-to-sequence-of-strings()
let $dt := my-parse-date($i)
return function() { $dt ;}
or
return function() { return my-parse-date($i) ;
return tokenized and validated but not parsed strings. Use "" for 'not valid', e.g.:
( "2014-01-22","","2017-03-30","" )
then there's arrays', maps, arrays of maps, and ... XML
parseFunction() as xs:element()*:
for ... return <date>{ parse-and-validate($value) } </date>

user defined function for xquery if else condition

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

Groovy NullObject should be null or not?

This example can be easily tested in the groovy console.
var a is evaluated to not null while b is evaluated to null.
Both are instances of org.codehaus.groovy.runtim.NullObject
def b = null
println b.getClass()
println b == null
def a = null.getClass().newInstance()
println a.getClass()
println a == null
Does anyone knows why?
This is a tricky thing when dealing with reflection code.
Actually I am wondering if this is not a bug. As an explanation... NullObject is a runtime/intermediate kind of Object. If you do anything on null, then NullObject is used. This, and the the implementation of NullObject#equals speaks for a==null returning true. It returns fails, because there is some internal code before that, that is for example determining if compareTo is called instead of equals and such things. Now this piece of code starts with
if (left == right) return true;
if (left == null || right == null) return false;
so null==null will return true, but NullObject==null will return false. On the other hand NullObject should not leak out if possible. Maybe we should fix newInstance() to return null.
I filled http://jira.codehaus.org/browse/GROOVY-5769 for this
In the equals method of NullObject, it only returns true if you are comparing it to null
As an instance of NullObject is not strictly null, it returns false...
Whether NullObject should return true if you call equals against another NullObject is probably a question best asked on the mailing list... I'll have a look and see if I can find any previous question.

Resources