XQuery nested for clause - xpath

I kept getting this error in XQuery, but I was sure that I opened and closed the brackets. What may go wrong with this query?
XPST0003 XQuery syntax error near #...{ $x/name }</name> {for#:
expected "}", found "{"
This is the query
<myquery>
<A>
{for $x in doc("example.xml")/example/A
where $x/name = "United States"
return
<name>{ $x/name }</name> (: error reported at this line of code :)
{for $y in $x/B
let $z := $y/C div $y/D
order by $z
return
<B>
<C>{$y/name/text()}</C>
<ratio>{ $z }</ratio>
</B>
}
}
</A>
</myquery>

Given you want to return the name tags followed by B tags, you will have to return a sequence:
<myquery>
<A>{
for $x in doc("example.xml")/example/A
where $x/name = "United States"
return ( (: Return a sequence here :)
<name>{ $x/name }</name>, (: Be aware of the comma :)
for $y in $x/B
let $z := $y/C div $y/D
order by $z
return
<B>
<C>{$y/name/text()}</C>
<ratio>{ $z }</ratio>
</B>
) (: end of sequence :)
}</A>
</myquery>
I also removed the unnecessary curly brackets around the FLWOR expression, and be aware I added a comma after the name tag.

Related

What do these symbols mean in the RFC docs regarding grammars?

Here are the examples:
Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
Upgrade = "Upgrade" ":" 1#product
Server = "Server" ":" 1*( product | comment )
delta-seconds = 1*DIGIT
Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
Questions are:
What is the 1#transfer-coding (the 1# regarding the rule transfer-coding)? Same with 1#product.
What does 1 times x mean, as in 1*( product | comment )? Or 1*DIGIT.
What do the brackets mean, as in [ comment ]? The parens (...) group it all, but what about the [...]?
What does the *(...) mean, as in *( ";" chunk-ext-name [ "=" chunk-ext-val ] )?
What do the nested square brackets mean, as in [ abs_path [ "?" query ]]? Nested optional values? It doesn't make sense.
What does 2DIGIT and 1DIGIT mean, where do those come from / get defined?
I may have missed where these are defined, but knowing these would help clarify how to parse the grammar definitions they use in the RFCs.
I get the rest of the grammar notation, juts not these few remaining pieces.
Update: Looks like this is a good start.
Square brackets enclose an optional element sequence:
[foo bar]
is equivalent to
*1(foo bar).
Specific Repetition: nRule
A rule of the form:
<n>element
is equivalent to
<n>*<n>element
That is, exactly <n> occurrences of <element>. Thus, 2DIGIT is a
2-digit number, and 3ALPHA is a string of three alphabetic
characters.
Variable Repetition: *Rule
The operator "*" preceding an element indicates repetition. The full
form is:
<a>*<b>element
where <a> and <b> are optional decimal values, indicating at least
<a> and at most <b> occurrences of the element.
Default values are 0 and infinity so that *<element> allows any
number, including zero; 1*<element> requires at least one;
3*3<element> allows exactly 3; and 1*2<element> allows one or two.
But what I'm still missing is what the # means?
Update 2: Found it I think!
#RULE: LISTS
A construct "#" is defined, similar to "*", as follows:
<l>#<m>element
indicating at least <l> and at most <m> elements, each separated
by one or more commas (","). This makes the usual form of lists
very easy; a rule such as '(element *("," element))' can be shown
as "1#element".
Also, what do these mean?
1*2DIGIT
2*4DIGIT

Match balanced occurrences of nested tag

I have a test string:
s = "A test [[you|n|note|content of the note with a [[link|n|link|http://link]] inside]] paragraph. wef [[you|n|note|content of the note with a [[link|n|link|http://link]] inside]] test".
I need to match the occurrences of the [[...]] parts of the string. There can be up to the second level of nested [[ ]] tags in the string (as shown in the test string).
I started with /\[\[.*?\]\]/, but that only matches the following:
[[you|n|note|content of the note with a [[link|n|link|http://link]] (it's missing the last occurrence of the ]].
How do I go about matching the remainder of each [[ .. ]] block? Is this possible with regex?
If you don't have single isolated [ or ], then it is pretty much simple. The following assumes no restriction on the nested level.
s.scan(/(?<match>\[\[(?:[^\[\]]|\g<match>)*\]\])/).flatten
returns:
[
"[[you|n|note|content of the note with a [[link|n|link|http://link]] inside]]",
"[[you|n|note|content of the note with a [[link|n|link|http://link]] inside]]"
]
Here's a non-regex solution. I've assumed left (right) brackets always appear in pairs.
level = 0
s.each_char.each_cons(2).with_index.with_object([]) do |(pair, i), a|
case pair.join
when "[["
level += 1
a << i if level==1
when "]]"
a << i+1 if level==1
level -= 1
end
end.each_slice(2).map { |b,e| s[b..e] }
#=> ["[[you|n|note|content of the note with a [[link|n|link|http://link]] inside]]",
# "[[you|n|note|content of the note with a [[link|n|link|http://link]] inside]]"]

Wrong preg_match - php

I have a question about regular expressions, I can't understand why the function returns 1 when it should return 0, because the string doesn't match the regular expression.
$t = preg_match("/DOC|doc|doc_[IVXCL]{1,6}_[A-Z]{1}_[A-Z0-9]{2,5}\.pdf/", "DOC_TRF4_DEZ_2014.pdf");
echo $t;
It returns TRUE because it matches DOC.
You have to group some part in your regex:
preg_match("/(?:DOC|doc|doc)_[IVXCL]{1,6}_[A-Z]{1}_[A-Z0-9]{2,5}\.pdf/", "DOC_TRF4_DEZ_2014.pdf");
// here __^ __^
But it isn't very clear what you're trying to match.

Counting occurrences of attributes in a sequence in XQuery

I have a sequence called $answer with the attributes I extracted from elements from an XML file. Inside $answer I have the following 3 attributes: 1, 3, 3 and another sequence of attributes called $p with: 1, 3
I tried to do this to get the number of occurrences by doing
for $x in $p
return count (index-of($x, $answer))
since I saw it as a solution in another posting but it gave me errors. What's the correct way to do this?
Do you want to sort all your attributes by its values? The group by statement might give you the expected results:
for $a in (attribute a {'A'}, attribute b {'B'}, attribute a {'A'})
group by $v := $a
return concat(count($a), ': ', $v)
Note, however, that your XQuery implementation needs to support XQuery 3.0.
You need to swap the arguments you passed to index-of():
for $x in $p
return count(index-of($answer, $x))
But a simpler way is to test for equality in a predicate:
for $x in $p
return count($answer[. eq $x])
which produces the same result for the given data.

Simple regular expression using preg_match

I am trying to retrieve the three digit number after this word and semi colon.
REF: 222
The code i have below works but its not good because its getting 3digit numbers from the $decoded_message string.
What i really want is only to grab three digit number after the word REF: ###
if (preg_match("([0-9]{3})", $decoded_message, $matches)) {
echo "Match was found <br />";
echo "ref = ".$matches[0];
}
Thanks in advance
You can search for REF: [0-9]{3} and then remove the REF: part.
if (preg_match("/REF: [0-9]{3}/", $decoded_message, $matches)) {
echo "Match was found <br />";
echo "ref = ".substr( $matches[0], 5 );
}
You may simply replace "REF: " by using
$output = preg_replace("/REF: /","", "REF: 222");
Afterwards, only the number should be contained in $output.

Resources