Home > Back-end >  Confirm preceding and following sibling in XPATH
Confirm preceding and following sibling in XPATH

Time:10-04

I've got the below statement to check that 2 conditions exist in a an element:

 if len(driver.find_elements(By.XPATH, "//span[text()='$400.00']/../following-sibling::div/a[text()='Buy']")) > 0:
   elem = driver.find_element(By.XPATH, "//span[text()='$400.00']/../following-sibling::div/a[text()='Buy']")

I've tried a few variations, including "preceding sibling::span[text()='x'", but can't seem to get the syntax correct or if I'm going about it the right way.

HTML is below. the current find_elements(By.XPATH...) correctly finds the "Total" and "Buy" class, I would like to add $20.00 in the "price" class as a condition also.

    <ul>
       <li class="List">
           <div class="List-Content row">
               <div class="Price">"$20.00"</div>
               <div class="Quantity">10</div>
               <div class="Change">0%</div>
               <div class="Total">
                   <span>$400.00</span>
               </div>
               <div class="Buy">
                   <a class="Button">Buy</a>
               </div>
           </div>
        </li>
    </ul>

CodePudding user response:

Using built in ElementTree

import xml.etree.ElementTree as ET


html = '''<li class="List">
   <div class="List-Content row">
       <div class="Price">"$20.00"</div>
       <div class="Quantity">10</div>
       <div class="Change">0%</div>
       <div class="Total"><span>$400.00</span></div>
       <div class="Buy"><a class="Button">Buy</a></div>
   </div>
   <div class="List-Content row">
       <div class="Price">"$27.00"</div>
       <div class="Quantity">10</div>
       <div class="Change">0%</div>
       <div class="Total"><span>$400.00</span></div>
       <div class="Buy"><a class="Button">Buy</a></div>
   </div>
</li>'''

items = {'Total':'$400.00','Buy':'Buy','Price':'"$20.00"'}

root = ET.fromstring(html)
first_level_divs = root.findall('div')
for first_level_div in first_level_divs:
    results = {}
    for k,v in items.items():
        div = first_level_div.find(f'.div[@class="{k}"]')
        one_level_down = len(list(div)) > 0
        results[k] = list(div)[0].text if one_level_down else div.text
    if results == items:
        print('found')
    else:
        print('not found')
    results = {}

output

found
not found 

CodePudding user response:

Given this HTML snippet

<ul>
   <li class="List">
       <div class="List-Content row">
           <div class="Price">"$20.00"</div>
           <div class="Quantity">10</div>
           <div class="Change">0%</div>
           <div class="Total"><span>$400.00</span></div>
           <div class="Buy"><a class="Button">Buy</a></div>
       </div>
    </li>
</ul>

I would use this XPath:

buy_buttons = driver.find_elements(By.XPATH, """//div[
    contains(@class, 'List-Content')
    and div[@class = 'Price'] = '$20.00'
    and div[@class = 'Total'] = '$400.00'
]//a[. = 'Buy']""")

for buy_button in buy_buttons:
   print(buy_button)

The for loop replaces your if len(buy_buttons) > 0 check. It won't run when there are no results, so the if is superfluous.

  • Related