How to use like in XPath? - xpath

I have a page that searches with filters. I have this code for example,
xmlTempResultSearch = xmlResidentListDisplay.selectNodes("//PeopleList/Row[#LastName != '"+txtSearch.value+"']");
xmlTempResultSearch.removeAll();
This selects the data that is not equal to the LastName inputted on the txtSearch textbox and then removes them from the result set so that its filtered to equal the last name on the txtSearch textbox.
My problem with this code is that it should be equal (=) to the txtSearch.value, what I want is that I want the result set LIKE the txtSearch.value. What happens on my page is that when I type 'santos' on the txtSearch textbox, its result set is all those last names with 'santos'. But when I type 'sant', nothing appears. I want the same result set with 'santos' because it all contains 'sant'

You can use all of the XPath (1.0) string functions. If you have XPath 2.0 available, then you can even use RegEx.
contains()
starts-with()
substring()
substring-before()
substring-after()
concat()
translate()
string-length()
There is no **ends-with() in XPath 1.0, but it can easily be expressed with this XPath 1.0 expression**:
substring($s, string-length($s) - string-length($t) +1) = $t
is true() exactly when the string $s ends with the string $t.

You can use start-with function and not function. Reference:
http://www.w3schools.com/xpath/xpath_functions.asp
xmlTempResultSearch = xmlResidentListDisplay.selectNodes("//PeopleList/Row[not(starts-with(#LastName,'"+ txtSearch.value +"'))]");

you can use contains() function of XPath:
xmlTempResultSearch = xmlResidentListDisplay.selectNodes("//PeopleList/Row[not(contains(#LastName,'"+txtSearch.value+"'))]");

Related

How to convert string to Xpath in Xquery function (BaseX)

I am writing Xquery function for BaseX which gets one of arguments as name of the element node. This name is then used in Xpath, but in general I cannot convert string to element.
This is how the method looks like
declare function prefix:getElementWithValue($root as document-node()?, $elem as xs:string?, $minVal as xs:float?, $maxVal as xs:float?)
as element()*
{
let $e := element {$elem} {""}
for $x in $root//SUBELEM
return if ($x//$e/#ATTRIB>=$minVal and $x//$e/#ATTRIB<=$maxVal) then ($x)
};
and the call
return prefix:getElementWithValue($db, "SomeElem", 10.0, 10.0)
and I am getting empty response from that. If I replace the $x//$e with $x//SomeElem it returns proper response. From the QueryPlan I see that the $e is treated as literal value. XPATH is not $x//SomeElem/#ATTRIB but $x//$e/#ATTRIB
So my question is how to covert string to type that can be used in XPATH?
XQuery does not have a standard function to evaluate a dynamically-constructed XPath expression.
Many XQuery processors offer some kind of extension function that does this, however. For example, BaseX offers query:eval():
https://docs.basex.org/wiki/XQuery_Module#xquery:eval
Note that variables in XQuery represent values, not fragments of expression text. Your expression $x//$e/#ATTRIB is equivalent to $x//"SomeElem"/#ATTRIB, which is quite different from $x//SomeElem/#ATTRIB.
If you know that $elem will always be an element name, then you can write $x//*[name()=$e]/#ATTRIB. But take care over namespaces.

Is it possible in XPATH to find an element by attribute value, not by name?

For example I have an XML element:
<input id="optSmsCode" type="tel" name="otp" placeholder="SMS-code">
Suppose I know that somewhere there must be an attribute with otp value, but I don’t know in what attribute it can be, respectively, is it possible to have an XPath expression of type like this:
.//input[(contains(*, "otp")) or (contains(*, "ode"))]
Try it like this and see if it works:
one = '//input/#*[(contains(.,"otp") or contains(.,"ode"))]/..'
print(driver.find_elements_by_xpath(one))
Edit:
The contains() function has a required cardinality of first argument of either one or zero. In plain(ish) English, it means you can check only one element at a time to see if it contains the target string.
So, the expression above goes through each attribute of input separately (/#*), checks if the attribute value of that specific attribute contains within it the target string and - if target is found - goes up to the parent of that attribute (/..) which, in the case of an attribute, is the node itself (input).
This XPath expression selects all <input> elements that have some attribute, whose string value contains "otp" or "ode". Notice that there is no need to "go up to the parent ..."
//input[#*[contains(., 'otp') or contains(., 'ode')]]
If we know that "otp" or "ode" must be the whole value of the attribute (not just a substring of the value), then this expression is stricter and more efficient to evaluate:
//input[#*[. ='otp' or . = 'ode']]
In this latter case ("otp" or "ode" are the whole value of the attribute), if we have to compare against many values then an XPath expression of the above form will quickly become too long. There is a way to simplify such long expression and do just a single comparison:
//input[#*[contains('|s1|s2|s3|s4|s5|', concat('|', ., '|'))]]
The above expression selects all input elements in the document, that have at least one attribute whose value is one of the strings "s1", "s2", "s3", "s4" or "s5".

Conditional XPath on multiple elements

I am trying to use xpath to set an exchange property from the value of one element, depending on what the value is in another element...
So in my case i want an xpath to identify the PartyID where the RoleCode = 60. And another xpath expression to find the PartyID for where the RoleCode = Z60.
I would have used [1] etc but the send cannot guarantee the order the segments will be in.
Help is much appreciated!
<RegisteredProductCollection>
<RegisteredProduct>
<Status>1</Status>
<AddressLine2>test</AddressLine2>
<AddressLine1>37</AddressLine1>
<RegisteredProductPartyInformation>
<RegisteredProductPartyInformation>
<PartyID>9000028253</PartyID>
<RoleCode>60</RoleCode>
</RegisteredProductPartyInformation>
<RegisteredProductPartyInformation>
<PartyID>1288219</PartyID>
<RoleCode>Z60</RoleCode>
</RegisteredProductPartyInformation>
</RegisteredProductPartyInformation>
<PostalCode>3200</PostalCode>
<Country>NZ</Country>
<ProductID>G02411</ProductID>
<SerialID>1234124124</SerialID>
<City>test</City>
<ReferenceDate>20200514000000</ReferenceDate>
<District>wai</District>
</RegisteredProduct>
</RegisteredProductCollection>
You can use these XPath-1.0 expressions:
//RegisteredProductPartyInformation[RoleCode='60']/PartyID
and
//RegisteredProductPartyInformation[RoleCode='Z60']/PartyID
Change the ' to " if necessary.

XPath Get value inside query string

I use this XPath
//#getparam
to get this list of URL
/blabla/bla.php?id=100001&target=lala&new=lulu
/blabla/bla.php?id=100002&target=lala&new=lulu
/blabla/bla.php?id=100003&target=lala&new=lulu
I want to get list of IDs, and try this XPath
substring-before(substring-after(//#getparam, "?id="), "&")
but it only returns first ID. How to get all IDs only using XPath?
If you're using XPath 2.0, the following will do the trick:
//#getparam/substring-before(substring-after(., "?id="), "&")
If you're using XPath 1.0, there is no single expression to return the desired result set. You can iterate over each result of //#getParam and apply the functions.

Selenium Webdriver + Ruby regex: Can I use regex with find_element?

I am trying to click an element that changes per each order like so
edit_div_123
edit_div_124
edit_div_xxx
xxx = any three numbers
I have tried using regex like so:
#driver.find_element(:css, "#edit_order_#{\d*} > div.submit > button[name=\"commit\"]").click
#driver.find_element(:xpath, "//*[(#id = "edit_order_#{\d*}")]//button").click
Is this possible? Any other ways of doing this?
You cannot use Regexp, like the other answers have indicated.
Instead, you can use a nifty CSS Selector trick:
#driver.find_element(:css, "[id^=\"edit_order_\"] > div.submit > button[name=\"commit\"]").click
Using:
^= indicates to find the element with the value beginning with your criteria.
*= says the criteria should be found anywhere within the element's value
$= indicates to find the element with with your criteria at the end of the value.
~= allows you to find the element based on a single criteria when the actual value has multiple space-seperated list of values.
Take a look at http://net.tutsplus.com/tutorials/html-css-techniques/the-30-css-selectors-you-must-memorize/ for some more info on other neat CSS tricks you should add to your utility belt!
You have no provided any html fragment that you are working on. Hence my answer is just based on the limited inputs provided your question.
I don't think WebDriver APIs support regex for locating elements. However, you can achieve what you want using just plain XPath as follows:
//*[starts-with(#id, 'edit_div_')]//button
Explanation: Above xpath will try to search all <button> nodes present under all elements whose id attribute starts with string edit_div_
In short, you can use starts-with() xpath function in order to match element with id format as edit_div_ followed by any number of characters
No, you can not.
But you should do something like this:
function hasClass(element, className) {
var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
return re.test(element.className);
}
This worked for me
#driver.find_element(:xpath, "//a[contains(#href, 'person')]").click

Resources