Python : Regular expressions in xpaths using Selenium

Viewed 1927

I try to get the id of certain HTML tags using Python and Selenium. There is html code:

<tr id="10">
    <td colspan="5">
        <div class="card-view">       
            <span class="value">PROVIDER_628_54678931</span>
        </div>
    </td>
</tr>

<tr id="11">
    <td colspan="5">
        <div class="card-view">       
            <span class="value">PROVIDER_629_54678932</span>
        </div>
    </td>
</tr>


<tr id="12">
    <td colspan="5">
        <div class="card-view">       
            <span class="value">PROVIDER_730_54678933</span>
        </div>
    </td>
</tr>


<tr id="13">
    <td colspan="5">
        <div class="card-view">       
            <span class="value">PROVIDER_6542_54678934</span>
        </div>
    </td>
</tr>

For extract id of only one parent tag i do :

elem = browser.find_element_by_xpath("//span[contains(@class, 'value') and text()='PROVIDER_628_54678931']")
parent = elem.find_element_by_xpath('../../..')
print(parent.get_attribute("id"))

How to use regex in XPath to get parent id-s of "span" element where the text contains "PROVIDER_6XX", but not "PROVIDER_7" and PROVIDER_6542?

3 Answers

I will use contains:

//span[contains(text(),'PROVIDER_6') and contains(@class, 'value')]

I found solution here : link

def findTrunksByRegExp():
    pattern = re.compile(r"PROVIDER_6\d{2}")
    elements = browser.find_elements_by_xpath("//span[contains(@class, 'value')]")
    for element in elements:
        match = pattern.match(element.text)
        if match:
            parent = element.find_element_by_xpath('../../..')
            print(parent.get_attribute("id"))

XPath 2.0 supports regex, but Selenium support XPath 1.0 only.

You can try this workaround to get required output

//span[string-length(substring-before(substring-after(.,'PROVIDER_6'), '_')) = 2 and contains(@class, 'value')]

Explanation:

  • substring-after(.,'PROVIDER_6') return substring after "PROVIDER_6" from nodes with text representation that starts with "PROVIDER_6":

    "PROVIDER_628_54678931" --> "28_54678931"

  • substring-before(<STRING>, '_') extracts substring before "_":

    "28_54678931" --> "28"

  • string-length(<STRING>) = 2 checks if string length exactly equal to 2:

    string length of "28" is equal to 2

So in your case XPath will "ignore" "PROVIDER_730_54678933" as it doesn't start with "PROVIDER_6" and "PROVIDER_6542_54678934" as string length of "542" is equal to 3, but not 2

Related