How to avoid "invalid lexical value" while adding empty nodes - xquery

let $a := <product>
<p1>100</p1>
<p2>100</p2>
<p3/>
</product>
for $i in $a
return $i/p1 + $i/p2 + $i/p3
Why do i get invalid lexical value here when i expect the sum to be displayed?

Your last line return $i/p1 + $i/p2 + $i/p3 is evaluated as return xs:double($i/p1) + xs:double($i/p2) + xs:double($i/p3). This works for p1 and p2, but not p3:
xs:double($i/p3) = xs:double(<p3/>)
= xs:double(xs:untypedAtomic('')) (: atomization :)
= xs:double('')
Since + returns the empty sequence () if one of its arguments is the empty sequence, your approach would not have worked either way. You can use fn:sum($sequence) instead, summing over the text nodes inside the elements:
let $a :=
<product>
<p1>100</p1>
<p2>100</p2>
<p3/>
</product>
for $i in $a
return sum(($i/p1/text(), $i/p2/text(), $i/p3/text()))
The last line can even be shortened to:
return sum($i/(p1, p2, p3)/text())

Related

Unable to understand this xquery statement

I am new to xquery and unable to understand what does it means :
$bottles=getallBottles()
$cups=getallCups()
<containers>
{
($bottles,$cups) //this line i am unable to get
}
<containers>
The comma forms a sequence. Presumably $bottles is a sequence of zero-to-many items and $cups is a sequence of zero-to-many items. The comma forms a sequence of all of the items in $bottles and all of the items in $cups.
For example:
let $x := (1, 2, 3)
let $y := ('a', 'b', 'c')
return ($x,$y)
yields:
1 2 3 a b c
In the above example, the parentheses are necessary so that forming the sequence of $x, $y takes precedence over return and the entire constructed sequence is returned.
In an example similar to the original question, parentheses are unnecessary because precedence is not ambiguous:
let $x := <a><x>5</x><x>6</x></a>
let $y := <b><y>1</y><y>2</y></b>
return <container>{$x, $y}</container>
yields:
<container><a><x>5</x><x>6</x></a><b><y>1</y><y>2</y></b></container>

How do you access name of a ProtoField after declaration?

How can I access the name property of a ProtoField after I declare it?
For example, something along the lines of:
myproto = Proto("myproto", "My Proto")
myproto.fields.foo = ProtoField.int8("myproto.foo", "Foo", base.DEC)
print(myproto.fields.foo.name)
Where I get the output:
Foo
An alternate method that's a bit more terse:
local fieldString = tostring(field)
local i, j = string.find(fieldString, ": .* myproto")
print(string.sub(fieldString, i + 2, j - (1 + string.len("myproto")))
EDIT: Or an even simpler solution that works for any protocol:
local fieldString = tostring(field)
local i, j = string.find(fieldString, ": .* ")
print(string.sub(fieldString, i + 2, j - 1))
Of course the 2nd method only works as long as there are no spaces in the field name. Since that's not necessarily always going to be the case, the 1st method is more robust. Here is the 1st method wrapped up in a function that ought to be usable by any dissector:
-- The field is the field whose name you want to print.
-- The proto is the name of the relevant protocol
function printFieldName(field, protoStr)
local fieldString = tostring(field)
local i, j = string.find(fieldString, ": .* " .. protoStr)
print(string.sub(fieldString, i + 2, j - (1 + string.len(protoStr)))
end
... and here it is in use:
printFieldName(myproto.fields.foo, "myproto")
printFieldName(someproto.fields.bar, "someproto")
Ok, this is janky, and certainly not the 'right' way to do it, but it seems to work.
I discovered this after looking at the output of
print(tostring(myproto.fields.foo))
This seems to spit out the value of each of the members of ProtoField, but I couldn't figure out the correct way to access them. So, instead, I decided to parse the string. This function will return 'Foo', but could be adapted to return the other fields as well.
function getname(field)
--First, convert the field into a string
--this is going to result in a long string with
--a bunch of info we dont need
local fieldString= tostring(field)
-- fieldString looks like:
-- ProtoField(188403): Foo myproto.foo base.DEC 0000000000000000 00000000 (null)
--Split the string on '.' characters
a,b=fieldString:match"([^.]*).(.*)"
--Split the first half of the previous result (a) on ':' characters
a,b=a:match"([^.]*):(.*)"
--At this point, b will equal " Foo myproto"
--and we want to strip out that abreviation "abvr" part
--Count the number of times spaces occur in the string
local spaceCount = select(2, string.gsub(b, " ", ""))
--Declare a counter
local counter = 0
--Declare the name we are going to return
local constructedName = ''
--Step though each word in (b) separated by spaces
for word in b:gmatch("%w+") do
--If we hav reached the last space, go ahead and return
if counter == spaceCount-1 then
return constructedName
end
--Add the current word to our name
constructedName = constructedName .. word .. " "
--Increment counter
counter = counter+1
end
end

Code for sorting letters of a word is not working?

For solving this question in Hackerrank,I wrote the following piece of code.It worked well on my machine, but when it was submitted,it is evaluated as a wrong answer.
T = int(input().strip())
arr = []
result = []
for i in range(T):
s = input().strip()
arr.append(s)
for item in arr:
odd = [];even = []
for value in item:
n = item.index(value)
if n%2 ==0:
even.append(value)
if n%2 == 1:
odd.append(value)
p = ''.join(even) ; q = ''.join(odd)
result.append(p + " " + q)
odd.clear();even.clear();
for value in result:
print(value)
Try this test case:
2
aaB
Baa
Your code is giving wrong results. Inner for loop is looping the characters. What if two characters are same? Your code will give wrong index number.

pyparsing delimitedList(..., combine=True) giving inconsistent result

I'm using pyparsing==2.1.5 with Python 3.4, and I'm getting what seems to be an odd result:
word = Word(alphanums)
word_list_no_combine = delimitedList(word, combine=False)
word_list_combine = delimitedList(word, combine=True)
print(word_list_no_combine.parseString('one, two')) # ['one', 'two']
print(word_list_no_combine.parseString('one,two')) # ['one', 'two']
print(word_list_combine.parseString('one, two')) # ['one']: ODD ONE OUT
print(word_list_combine.parseString('one,two')) # ['one,two']
It's not obvious to me why the "combine" option causes one of the parts of the list to be swallowed when a space is present, but not when it's absent. Is this a pyparsing bug or am I missing something obvious?
Rather than modify pyparsing, I suggest you do this work using normal uncombined delimited list with a custom parse action:
word_list_combine_using_parse_action = word_list_no_combine.copy().setParseAction(','.join)
print(word_list_combine_using_parse_action.parseString('one, two'))
Will print one,two
Looks like it's due to the behaviour of Combine(), specifically its default "adjacent=True" option, which is then used by delimitedList():
class Combine(TokenConverter):
"""Converter to concatenate all matching tokens to a single string.
By default, the matching patterns must also be contiguous in the input string;
this can be disabled by specifying C{'adjacent=False'} in the constructor.
"""
def __init__( self, expr, joinString="", adjacent=True ):
# ...
def delimitedList( expr, delim=",", combine=False ):
# ...
dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
if combine:
return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
else:
return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)
So it can be solved with a replacement:
def delimitedListPlus(expr, delim=",", combine=False, combine_adjacent=False):
dlName = str(expr) + " [" + str(delim) + " " + str(expr) + "]..."
if combine:
return Combine(expr + ZeroOrMore(delim + expr),
adjacent=combine_adjacent).setName(dlName)
else:
return (expr + ZeroOrMore(Suppress(delim) + expr)).setName(dlName)

Check if palindrome while ignoring special characters

I'm failing the last test case, which is the one with the spaces and single quotation mark.
I used s.strip, but the error still persists.
Is there another way to go about this?
Thank you.
from test import testEqual
def removeWhite(s):
s.strip()
s.strip("'")
return s
def isPal(s):
if s == "" or len(s) == 1:
return True
if removeWhite(s[0]) != removeWhite(s[-1]):
return False
return isPal(removeWhite(s[1:-1]))
testEqual(isPal(removeWhite("x")),True)
testEqual(isPal(removeWhite("radar")),True)
testEqual(isPal(removeWhite("hello")),False)
testEqual(isPal(removeWhite("")),True)
testEqual(isPal(removeWhite("hannah")),True)
testEqual(isPal(removeWhite("madam i'm adam")),True)
At first your removeWhite function doesn't return all spaces because strip only removes from the end and the beginning of a string. See:
>>> " a ".strip()
'a'
>>> " a a ".strip()
'a a'
So i suggest this approach:
def removeWhite(s):
return ''.join(filter(lambda x: x not in " '", s))
Please note that I use join because filter returns an iterator which needs to be converted back to a string.
For finding the palindromes i would suggest this function:
def isPal(s):
if len(s) <= 1: # Special case to prevent KeyError later
return True
stripped = removeWhite(s) # Strip off all whitespaces
first = stripped[:len(stripped) // 2] # First half of the string
if len(stripped) % 2: # Length of string is even?
second = stripped[len(stripped) // 2 + 1:] # Drop the middle character
else:
second = stripped[len(stripped) // 2:] # Else keep it
secondrev = ''.join(reversed(second)) # Reverse the second half
return first == secondrev # And return wether they're equal.
This holds for all your examples. But it think your isPal function should work too if you fix your removeWhite function

Resources