Reputation: 20984
I'm trying to count the number of distinct currencies in which a website displays prices.
The website's home page allows a user to select a currency from a drop-down list.
I'm trying to find an XPath expression that will count the distinct currencies in the drop-down list.
The list looks like this:
The first four currencies in the list are the currencies most often selected by users.
A complete list of currencies ordered by currency code is also displayed. The complete list contains duplicates of the first four currencies.
The 'popular' list and the 'complete' list are seperated visually by putting a disabled blank option in the drop-down list.
The HTML on the home page to create the list looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<select id="selCurrency" tabindex="122">
<option value="GBP" selected="selected">Select your currency</option>
<option value="GBP">GBP - £</option>
<option value="EUR">EUR - €</option>
<option value="PLN">PLN - zł</option>
<option value="USD">USD - $</option>
<option value="" disabled="disabled"/>
<option value="AED">AED - د.إ.</option>
<option value="AFN">AFN</option>
<option value="ARS">ARS - $</option>
<option value="AUD">AUD - $</option>
<option value="BDT">BDT</option>
<option value="BGN">BGN - лв.</option>
<option value="BOB">BOB - Bs.</option>
<!-- ... -->
</select>
For brevity I've removed the elements that are not visible in the screenshot.
The idea of my solution is to select just all the nodes that come after the blank separator and count them up.
This XPath expression selects just the separator:
//*[@id="selCurrency"]/option[@value=""]
According to the w3schools page on XPath axes, I can use the following-sibling axis to select all siblings after the current node.
Following the examples, I tried the following expression:
//*[@id="selCurrency"]/following-sibling::option[@value=""]
But this either returns nothing, or is illegal syntax. I'm not sure which.
How do I select all the nodes of the complete currency list and then count them up?
Upvotes: 2
Views: 1036
Reputation: 20984
JLRishe already answered the presenting question.
Buried in the question text was a more general description of the problem:
find an XPath expression that will count the distinct currencies in the drop-down list.
JLRishe's answer solves this problem but relies on the ordering of the elements. For someone used to working with sets, that just feels too fragile. The query would produce a misleading result if the interface designer removed the separator row, or chose to stop duplicating the 'popular' elements in the 'complete' list.
With Dimitre Novatchev's help, I came up with
count(/select/option/@value[not(. = '') and not(. = ../following-sibling::option/@value)])
It filters out the separator value and counts the distinct values that remain. When applied to my example, the output is
7
I believe this is a more robust solution to the problem I wanted to solve.
Upvotes: 0
Reputation: 101748
You need to combine your two attempts to get the right items:
//*[@id="selCurrency"]/option[@value=""]/following-sibling::option
If you then want to use XPath to count these, this would be the formula to count them:
count(//*[@id="selCurrency"]/option[@value=""]/following-sibling::option)
Upvotes: 3