I am trying to use XPath 1.0 to select the maximum double value in an XML document. I understand that XPath 1.0 doesn't support the Max function that would make this extremely easy, but the system I'm using only supports XPath 1.0 functions.
I'm not able to post the entire file due to length, but here is a sample of the document I'm scanning: https://codebeautify.org/xmlviewer/cbc93c7e.
I've tried this XPath Expression:
/site/forecast/datum[not(primary < preceding-sibling::datum/primary) and not (primary < following-sibling::datum/primary)]
But no matter what, it returns the wrong datum. It always returns:
<datum>
<valid timezone="UTC">2019-04-04T06:00:00-00:00</valid>
<primary name="Stage" units="ft">9.80</primary>
<secondary name="Flow" units="cfs">3010.00</secondary>
<pedts>HGIFE</pedts>
</datum>
I expect it to return the element with the maximum "primary stage" value like:
<datum>
<valid timezone="UTC">2019-03-28T18:00:00-00:00</valid>
<primary name="Stage" units="ft">13.10</primary>
<secondary name="Flow" units="cfs">13400.00</secondary>
<pedts>HGIFE</pedts>
</datum>
I understand it will return all those with the 13.10 primary stage, but that's okay. I'll select the first one it returns if I can just get it to that point.
Do note that you might have more than one maximum. Use:
/site/forecast/datum[not(primary < ../datum/primary)][1]
This select the element
<datum>
<valid timezone="UTC">2019-03-28T18:00:00-00:00</valid>
<primary name="Stage" units="ft">13.10</primary>
<secondary name="Flow" units="cfs">13400.00</secondary>
<pedts>HGIFE</pedts>
</datum>
Test it in http://www.xpathtester.com/xpath/4256aac47f4f0efc36e23a2f16183d90
Related
I'm working on Xpath/Xquery to return values of multiple child nodes based on a sibling node value in a single query. My XML looks like this
<FilterResults>
<FilterResult>
<ID>535</ID>
<Analysis>
<Name>ZZZZ</Name>
<Identifier>asdfg</Identifier>
<Result>High</Result>
<Score>0</Score>
</Analysis>
<Analysis>
<Name>XXXX</Name>
<Identifier>qwerty</Identifier>
<Result>Medium</Result>
<Score>0</Score>
</Analysis>
</FilterResult>
<FilterResult>
<ID>745</ID>
<Analysis>
<Name>XXXX</Name>
<Identifier>xyz</Identifier>
<Result>Critical</Result>
<Score>0</Score>
</Analysis>
<Analysis>
<Name>YYYY</Name>
<Identifier>qwerty</Identifier>
<Result>Medium</Result>
<Score>0</Score>
</Analysis>
</FilterResult>
</FilterResults>
I need to get values of Score and Identifier based on Name value. I'm currently trying with below query but not working as desired
fn:string-join((
for $Identifier in fn:distinct-values(FilterResults/FilterResult/Analysis[Name="XXXX"])
return fn:string-join((//Identifier,//Score),'-')),',')
The output i'm looking for is this
qwerty-0,xyz-0
Your question suggests some fundamental misunderstandings about XQuery, generally. It's hard to explain everything in a single answer, but 1) that is not how distinct-values works (it returns string values, not nodes), and 2) the double slash selections in your return statement are returning everything because they are not constrained by anything. The XPath you use inside the distinct-values call is very close, however.
Instead of calling distinct-values, you can assign the Analysis results of that XPath to a variable, iterate over them, and generate concatenated strings. Then use string-join to comma separate the full sequence. Note that in the return statement, the variable $a is used to concat only one pair of values at a time.
string-join(
let $analyses := FilterResults/FilterResult/Analysis[Name="XXXX"]
for $a in $analyses
return $a/concat(Identifier, '-', Score),
',')
=> qwerty-0,xyz-0
I would like to select a attribute and the text() value of a node in one query, e.g. I have
<Tag1 #myattr='test'>MyText</Tag1>
and I am interested in getting "test" and "MyText" with one query.
The obvious
//Tag1/#myattr | //Tag1/text()
fails due to the fact, that Unions are only allowed over node-sets.
Any ideas?
I think, given XPath 2.0, you want a sequence of string values which you get with //Tag1/(#myattr, .)/string(). If you want a single string then use //Tag1/string-join((#myattr, .), ' ').
BTW, your path //Tag1/#myattr | //Tag1/text() would select a sequence containing an attribute value and a text node. I don't see how that would fail.
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+"'))]");
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
I would like to find the value of an element matched on id attribute for which I only have the ref - the bit with #, the anchor.
I am looking for the value of partyId:
< party id="partyA" >
< partyId >THEID< /partyId >
but to get there I only have the href from the following
< MyData >
< MyReference href="#partyA" />
Strip the # sign does not look good to me.
Any hints?
Because you haven't provided complete XML documents, I have to use // -- a practice I strongly recommend to avoid.
Suppose that
$vDataRef
is defined as
//MyData/MyReference/#href
and its string value is "#partyA", then one possible XPath expression that selects the wanted node is:
//party[#id=substring($vDataRef,2)]
In case the XML document has a DTD in which the id attribute of party is defined to be of type ID, then it is more convenient and efficient to use the standard XPath function id():
id(substring($vDataRef,2))
Assuming you have your ID as a variable already (lets say $myId), then try using:
//party[contains($myId, #id)]
The contains() function will look to see on each matching node whether or not the partyId attibute is in the value that you pass in.
Alternatively (as that could be considered 'ropey'), you can try:
//party[#id=substring($myId, 2, 1 div 0)]
the substring() function should be a little more precise.