Split a string based on Pipe delimiter and except inside brackets () - xquery

I want to split a string by '|' delimiter and exclude those inside the brackets (). I used tokenize function to split by delimiter and have some issue with exclusion part(RegEx format). Please help.
Input: Test|Test1|Test2|(Test3|Test4)|Test5|(Test6)(Test7)|Test8
Output: Test,Test1,Test2,(Test3|Test4),Test5,(Test6)(Test7),Test8
Thanks in advance.

Perhaps the analyze-string function suffices to break up the string, I don't think the single example makes the rules clear but it would be like
analyze-string('Test|Test1|Test2|(Test3|Test4)|Test5|(Test6)(Test7)|Test8','(\([^)]*\))+')/*
/(if (. instance of element(fn:match)) then data() else tokenize(., '\|'))[normalize-space()]
either => string-join(',') that result or use
declare option output:method 'text';
declare option output:item-separator ',';
analyze-string('Test|Test1|Test2|(Test3|Test4)|Test5|(Test6)(Test7)|Test8','(\([^)]*\))+')/*
/(if (. instance of element(fn:match)) then data() else tokenize(., '\|'))[normalize-space()]

Related

How to add one value hardcoded in a return statement in xquery

I have a function in which a return statement is already written as :-
return
if (fn:count($somevariable1) eq 1)
then some-method($var1, $var2, $var3)
else fn:concat(...some string values..)
The above statement is written inside a function. And some-method is another function which is declared somewhere. Now I want to hardcode a value just after the if statement and before the else statement. How can I do that?
Instead of returning just the product of some-method($var1, $var2, $var3), you want to return a sequence that also includes a hard-coded string value?
You can return a sequence of values, just separate with a comma and wrap with parenthesis.
if (fn:count($somevariable1) eq 1)
then ( some-method($var1, $var2, $var3), "my hardcoded value" )
else fn:concat(...some string values..)

How to replace the single quote ( ' ) into double quotes ( " ) in Robot Framework?

I have a List, items are created by append by a Loop. I want to use this list as a json. The problem is that the items of that list use the single quote so it can't be the json.
Get Order Items
[Tags] Get Order Items
Set Headers ${HEADER CUSTOMER}
GET ${ORDER GET BY CODE ENDPOINT}/${ORDER CODE}
Integer response status 200
${NUMBER OF ITEMS} Output $.number_of_items
${NUMBER OF ITEMS} Evaluate ${NUMBER OF ITEMS} + 1
${ORDER ITEMS} Create List
:FOR ${i} IN RANGE 1 ${NUMBER OF ITEMS}
\ Append To List ${ORDER ITEMS} ${ORDER CODE}${i}
Set Global Variable ${ORDER ITEMS}
Actual result: ['N19072596HB1', 'N19072596HB2', 'N19072596HB3', 'N19072596HB4', 'N19072596HB5']
Expected result: ["N19072596HB1", "N19072596HB2", "N19072596HB3", "N19072596HB4", "N19072596HB5"]
This: ['N19072596HB1', 'N19072596HB2', 'N19072596HB3', 'N19072596HB4', 'N19072596HB5'] , is python's string representation of a list, and they have picked to use single quotes for it.
As your end goal is to use the double-quoted version in a json, the best bet is to use the python's json library to convert it for you, instead of replacing single with double quotes:
${list as string}= Evaluate json.dumps($ORDER_ITEMS) json
(note how the variable is not surrounded by curly brackets - thus you're passing the actual variable to the method, not its value)
Why not to use a simple string replacement?
Because you don't want to deal with cases where a list member may have a quote, single or double - like ['N19072596HB1', "N1907'2596HB2", 'N19072596HB1', 'N19072"596HB2'].
A trivial string replace will fail miserably, while the json library is designed to handle these cases as expected.

Assign ' in string

I have the following value that needs to be assign into string -
ABC'DEFGH
How I can assign the sign of ' into string?
example -
str := 'ABC'DEFGH'
It's the same as with plain SQL: to escape a single quote, double it.
str := 'ABC''DEFGH';
You could also use the quoted string: q'<delimiter character><string<closing delimiter character>', e.g.:
str := q'{ABC'DEFGH}'
You can use a variety of characters as the quote delimiters. For more information, see the documentation for information on text literals, which includes how to use the q operator.

Count number of occurences of a character in an element using xquery

I have a variable which has | separated values like below.
I need to make sure it never has more than 30 sequences separated by '|', so i believe if i count number of occurrences of '|' in the var it would suffice
class=1111|2222|3333|4444
Can you please help in writing xquery for the same.
I am new to xquery.
If you remove all characters but the bar and then use string-length as in let $s := '1111|2222|3333|4444' return string-length(translate($s, translate($s, '|', ''), '')) you get the number of | characters. That use of string-length and the double translate to remove anything but a certain character is an old XPath 1 trick, of course as XQuery also has replace you could as well use let $s := '1111|2222|3333|4444' return string-length(replace($s, '[^|]+', '')).
You could use the tokenize() function to split the value by the | character, and then count how many items in the sequence with fn:count().
Just remember that the tokenize function uses a regex pattern, so you would need to escape the | as \|:
let $PSV := "1111|2222|3333|4444"
let $tokens := fn:tokenize($PSV, "\|")
let $token-count := fn:count($tokens)
return
if ($token-count > 30) then
fn:error((), "Too many pipe separated values")
else
(: less than thirty values, do stuff with the $tokens :)
()
Just for good measure, and in case you want to do any performance comparisons, you could try
let $sep := string-to-codepoints('|')
return count(string-to-codepoints($in)[.=$sep])
This has the theoretical advantage that (at least in Saxon) it doesn't construct any new strings or sequences in memory.

xquery- how to increment a counter variable within a for loop/ how to convert array of string values into node

In a java program, I am using Saxon Library to parse some XQuery commands.
Now, first I use tokenize() to split some text into a number of text values.
An example of the text is--
Mohan Prakash, Ramesh Saini
I use tokenize() on above text with ',' as the delimiter. And store the result of tokenize in variable $var
After this, I want to loop over those text values, and give as output the following--
Mohan Prakash,1
Ramesh Saini,2
As you can see from above, the last value in each row is a counter- for first row, this value is 1, for second row this value=2 and so on...
I thought of using something like the code below--
for $t in $var/position()
return concat($var[$t], ',', $t)
However I am getting an error that I cannot use position() on $var because $var is expected to be a node.
So there are 2 ways to resolve this--
(a) Convert the values in $var to a node
I tried text{$var} but that is not giving accurate results.
How do I convert the array of values into nodes?
(b) Use the following--
for $t in $var
Here, how do I create and use a counter within the for loop, so that the count value can be output along with each value of $t?
You can use the at keyword inside the for clause:
let $var := tokenize('Mohan Prakash, Ramesh Saini', ', ')
for $t at $pos in $var
return concat($t, ',', $pos)
This returns the two strings Mohan Prakash,1 and Ramesh Saini,2.
This XQuery (which also happens to be an XPath 2.0 expression):
for $text in 'Mohan Prakash, Ramesh Saini',
$i in 1 to count(tokenize($text, ','))
return concat(tokenize($text, ',')[$i], ',', $i, '
')
produces the wanted, correct result:
Mohan Prakash,1
Ramesh Saini,2

Resources