What is the Correct XPath to Identify Element with Text Occuring Minimum Number of Times?

Viewed 128

I'm trying to identify an element that has certain text but I only want to identify the element if the desired text occurs a specific number of times.

For example, imagine we have the following two HTML snippets on the same page:

Snippet 1:

<span id="price">

$36.46

<span>
($0.38 /  Count)
</span>
  
</span>

Snippet 2:

<span id="price">$38.38</span>

I could identify both elements using the XPath: .//span[contains(text(),'$')] However, I only want to identify the element if it (or any descendant of span element) contain at least two instances of the character: $

In above example, it would only identify the first snippet because the second snippet only contains one instance of $, not two.

What is the correct XPath syntax to use?

2 Answers

You can use the XPath //span[count(.//text()[contains(., "$")]) >= 2]

This is a moderately complicated XPath, so to explain it some by expanding outwards:

.//text()[contains(., "$")]

Select all text elements descending from the current node whose self contains "$".

count(.//text()[contains(., "$")])

Count the number of text elements descending from the current node whose self contains "$".

//span[count(.//text()[contains(., "$")]) >= 2]

Select all span elements with two or more text descendants whose self contains "$"

As a caveat, this only works if the dollar sign is in two different text elements. If you want to include the span in this example:

<span>
    $$
    <span>
    foo
    </span>
</span>

...then you'll need a different approach:

//span[string-length(.) - string-length(translate(., "$", "")) >= 2]

This predicate compares the string length of the span to the string length of the same span with all "$" characters removed.

One usable XPath-1.0 expression is

string-length(/span[@id='price'])-string-length(translate(/span[@id='price'],'$',''))

In a predicate this could look like

//span[string-length(.)-string-length(translate(.,'$',''))>=2]

This expression selects only the elements with a count of $ >= 2

Related