XPATH - how to combine AND / OR - xpath

I have the following XPATH expression:
/prod[price/buynow[1] > 19 and text/desc[1][not(contains(.,"bier"))] or text/desc[1][not(contains(.,"kalender"))] or text/desc[1][not(contains(.,"ballon"))]]
I need the first part ( > 19) to be true for all data, whereas the following conditions can be OR.

You can use
expression and (expression or expression)
Here is working example

Related

How to extract substring data from Json response using JMeter

My Json response is:
"return":"/info?booking=KD6YGS4L8I"
Now I want to extract value after "=" (ex:"KD6YGS4L8I").
I used Regular Expression extractor:
- Regular Expression: "return":"(.+?)"
- Template: $1$
- Match No: -1
And output is:
"return":"/info?booking=KD6YGS4L8I"
Now I want to get string KD6YGS4L8I.
You can use the following regular expression: booking=(.+?)", with template $1$. Match Number (n) depends on your needs:
n > 0: matches the given occurence number,
n == 0: matches a random occurence,
n < 0: matches all occurences, and organizes them with subvariables.
See Regular Expression Extractor on JMeter website.
I suggest you to take a look at the following guides:
Regular Expressions,
how to use JMeter Regexp Extractor.
Add a Beanshell sampler as a sibling to your Regular Expression Extractor with the below code:
//Assuming your regular expression extractor variable is RegExpResult
String regExpResponse= ${RegExpResult};
String[] result= regExpResponse.split("=");
result[1].replaceAll("\"", "");
vars.put("BookingValue",result[1]);
Now BookingValue variable contains - KD6YGS4L8I
You can find the same issue been resolved in stackoverflow:
JMeter - using substring on a user variable
Hope this helps! :)

thymeleaf eq with spring variables bug?

I'm trying to run the following th:if:
th:if="${camelContext.getRouteStatus( route.id )} &eq; 'Hey'
but I get this error:
org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "${camelContext.getRouteStatus( route.id )} &neq; 'Hey' " (camel:92)
However, if I try
th:if="${camelContext.getRouteStatus( route.id )} > 41 "
I get a different error, but now indicating that it's able to parse the expression, its just that it cannot compare Strings and numbers:
Cannot execute GREATER THAN from Expression "${camelContext.getRouteStatus( route.id )} > 41". Left is "Started", right is "41" (camel:92)
That's fine, I just wanted to check if I was writing the syntax correctly, and I don't want to compare numbers anyways, I want to compare the RouteStatus string.
Anyways, maybe someone can help me with this problem? Basically I want to do a if-else on the contents of a string, but I can't get this to work..
Cheers
Have you tried this:
th:if="${camelContext.getRouteStatus( route.id )} == 'Hey'"
Maybe it will work like this?
The example on the thymeleaf shows something similar:
Values in expressions can be compared with the >, <, >= and <= symbols, as usual, and also the == and != operators can be used to check equality (or the lack of it). Note that XML establishes that the < and > symbols should not be used in attribute values, and so they should be substituted by < and >.
th:if="${prodStat.count} gt; 1"
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
Even though textual aliases exist for some of these operators: gt (>), lt (<), ge (>=), le (<=), not (!). Also eq (==), neq/ne (!=), it is sometimes still better to stick with the old fashion operators.
It seems that your expression is malformed, but maybe this a copy paste issue.
Could you try: th:if="${camelContext.getRouteStatus( route.id ) eq 'Hey'} ?

XPath 2.0:reference earlier context in another part of the XPath expression

in an XPath I would like to focus on certain elements and analyse them:
...
<field>aaa</field>
...
<field>bbb</field>
...
<field>aaa (1)</field>
...
<field>aaa (2)</field>
...
<field>ccc</field>
...
<field>ddd (7)</field>
I want to find the elements who's text content (apart from a possible enumeration, are unique. In the aboce example that would be bbb, ccc and ddd.
The following XPath gives me the unique values:
distinct-values(//field[matches(normalize-space(.), ' \([0-9]\)$')]/substring-before(., '(')))
Now I would like to extent that and perform another XPath on all the distinct values, that would be to count how many field start with either of them and retreive the ones who's count is bigger than 1.
These could be a field content that is equal to that particular value, or it starts witrh that value and is followed by " (". The problem is that in the second part of that XPath I would have refer to the context of that part itself and to the former context at the same time.
In the following XPath I will - instead of using "." as the context- use c_outer and c_inner:
distinct-values(//field[matches(normalize-space(.), ' \([0-9]\)$')]/substring-before(., '(')))[count(//field[(c_inner = c_outer) or starts-with(c_inner, concat(c_outer, ' ('))]) > 1]
I can't use "." for both for obvious reasons. But how could I reference a particular, or the current distinct value from the outer expression within the inner expression?
Would that even be possible?
XQuery can do it e.g.
for $s
in distinct-values(
//field[matches(normalize-space(.), ' \([0-9]\)$')]/substring-before(., '(')))
where count(//field[(. = $s) or starts-with(., concat($s, ' ('))]) > 1
return $s

Is there a way to correctly concatenate three arbitrary XPath expressions to result in a new valid XPath expression?

Is there a way to correctly concatenate three arbitrary XPath expressions to result in a new valid XPath expression?
Update: The OP has indicated in a comment that the three expressions select text nodes.
In this case using the union operator (|) seems most appropriate.
Is there a way to correctly
concatenate three arbitrary XPath
expressions to result in a new valid
XPath expression?
There are many possible ways to do this and some of these may benefit from knowing the return type of the evaluation.
One of the combinator that always "works" (although maynot always be meaningful) is:
concat(Expr1, Expr2, Expr3)
Other examples:
number(Expr1) + number(Expr2) + number(Expr3)
boolean(Expr1) or boolean(Expr2) or boolean(Expr3)
In case the expressions are guaranteed to select a node-set, then this expression (the union of the node-sets) would also combine them:
Expr1 | Expr2 | Expr3
In XPath 2.0 this expression should always work (concatenation to a sequence of items):
Expr1 , Expr2 , Expr3
or this one:
if(boolean(Expr1))
then Expr2
else Expr3
Sure. If they are disjoint, then you place them together separated with an "or" statement. If they are additive, then you can just do a (.net) Path.Combine() on them.

xpath expression for regex-like matching?

I want to search div id in an html doc with certain pattern.
I want to match this pattern in regex:
foo_([[:digit:]]{1.8})
using xpath. What is the xpath equivalent for the above pattern?
I'm stuck with //div[#id="foo_ and then what? If someone could continue a legal expression for it.
EDIT
Sorry, I think I have to elaborate more. Actually it's not foo_, it's post_message_
Btw, I use mechanize/nokogiri ( ruby )
Here's the snippet :
html_doc = Nokogiri::HTML(open(myfile))
message_div = html_doc.xpath('//div[substring(#id,13) = "post_message_" and substring-after(#id, "post_message_") => 0 and substring-after(#id, "post_message_") <= 99999999]')
Still failed. Error message:
Couldn't evaluate expression '//div[substring(#id,13) = "post_message_" and substring-after(#id, "post_message_") => 0 and substring-after(#id, "post_message_") <= 99999999]' (Nokogiri::XML::XPath::SyntaxError)
How about this (updated):
XPath 1.0:
"//div[substring-before(#id, '_') = 'foo'
and substring-after(#id, '_') >= 0
and substring-after(#id, '_') <= 99999999]"
Edit #2: The OP made a change to the question. The following, even more reduced XPath 1.0 expression works for me:
"//div[substring(#id, 1, 13) = 'post_message_'
and substring(#id, 14) >= 0
and substring(#id, 14) <= 99999999]"
XPath 2.0 has a convenient matches() function:
"//div[matches(#id, '^foo_\d{1,8}$')]"
Apart from the better portability, I would expect the numerical expression (XPath 1.0 style) to perform better than the regex test, though this would only become noticeable when processing large data sets.
Original version of the answer:
"//div[substring-before(#id, '_') = 'foo'
and number(substring-after(#id, '_')) = substring-after(#id, '_')
and number(substring-after(#id, '_')) >= 0
and number(substring-after(#id, '_')) <= 99999999]"
The use of the number() function is unnecessary, because the mathematical comparison operators coerce their arguments to numbers implicitly, any non-numbers will become NaN and the greater than/less than tests will fail.
I also removed the encoding of the angle brackets, since this is an XML requirement, not an XPath requirement.
As already pointed out, in XPath 2.0 it would be good to use its standard regex capabilities with a function like the matches() function.
One possible XPath 1.0 solution:
//div[starts-with(#id, 'post_message_')
and
string-length(#id) = 21
and
translate(substring-after(#id, 'post_message_'),
'0123456789',
''
)
=
''
]
Do note the following:
The use of the standard XPath function starts-with().
The use of the standard XPath function string-length().
The use of the standard XPath function substring-after().
The use of the standard XPath function translate().
Or use xpath function matches(string,pattern).
<xsl:if test="matches(name(.),'foo_')">
Unfortunately it's not regex, but it might be enough unless you have other foo_ tags you don't need, then I Guess you can add a few more "if" checks to cull them out.
Nikkou makes this very easy and readable:
doc.search('div').attr_matches('id', /post_message_\d{1,8}/)

Resources