在Selenium中简化复杂的XPath表达式

时间:2018-04-12 00:43:05

标签: java html selenium selenium-webdriver xpath

我有以下HTML代码段:

<div class="a-row a-spacing-micro">
<div class="a-column a-span4 a-spacing-none a-spacing-top-mini address-column">
<div id="ya-myab-display-address-block-2" class="a-box a-spacing-none normal-desktop-address-tile">
<div class="a-box-inner a-padding-none">
<div class="a-section address-section-no-default">
<div class="a-row a-spacing-small">
<ul class="a-unordered-list a-noStyle a-vertical">
<li>
<span class="a-list-item">
<h5 id="address-ui-widgets-FullName" class="id-addr-ux-search-text a-text-bold">XXX XXXXX</h5>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-AddressLineOne" class="id-addr-ux-search-text">DDD XXXX XX</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-CityXXatePoXXalCode" class="id-addr-ux-search-text">XXXXXXXX, XX DDDDD-DDDD</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-Country" class="id-addr-ux-search-text">United States</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-PhoneNumber" class="id-addr-ux-search-text">Phone number: DDDDDDDDDD</span>
</span>
</li>
</ul>
<script>P.when('A', 'ready').execute(function(A) {   var $ = A.$;   var localizedXXrings = A.XXate('address-ui-widgets-XXore-map-text-id');   $(".address-ui-widgets-map-link").click(function(event) {     event.preventDefault();     window.open(this.href, localizedXXrings["address_ui_widgets_XXore_address_map_header"], "width=600,height=450");   }) }); </script>
</div>
</div>
</div>
</div>
<div id="ya-myab-edit-address-desktop-row-2" class="a-row edit-address-desktop-link">
<a id="ya-myab-address-edit-btn-2" class="a-link-normal" href="/a/addresses/edit?ref=ya_address_book_edit_button&addressID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">Edit            </a>
   |  
<a id="ya-myab-address-delete-btn-2" class="a-link-normal" href="#">
<span class="a-declarative" data-a-modal="{"name":"deleteAddressModal-2","width":"400","header":"Confirm Deletion"}" data-action="a-modal">Delete</span>
<div id="a-popover-deleteAddressModal-2" class="a-popover-preload">
<div class="a-section">
<div class="a-row a-spacing-small">
<ul class="a-unordered-list a-noStyle a-vertical">
<li>
<span class="a-list-item">
<h5 id="address-ui-widgets-FullName" class="id-addr-ux-search-text a-text-bold">XXX XXXXX</h5>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-AddressLineOne" class="id-addr-ux-search-text">DDD XXXX XX</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-CityXXatePoXXalCode" class="id-addr-ux-search-text">XXXXXXXX, XX DDDDD-DDDD</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-Country" class="id-addr-ux-search-text">United States</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-PhoneNumber" class="id-addr-ux-search-text">Phone number: 3472631425</span>
</span>
</li>
</ul>
<script>P.when('A', 'ready').execute(function(A) {   var $ = A.$;   var localizedXXrings = A.XXate('address-ui-widgets-XXore-map-text-id');   $(".address-ui-widgets-map-link").click(function(event) {     event.preventDefault();     window.open(this.href, localizedXXrings["address_ui_widgets_XXore_address_map_header"], "width=600,height=450");   }) }); </script>
</div>
<div class="a-row a-spacing-small">
<span class="a-size-small a-color-tertiary">
<span class="a-text-bold">Please note: </span>
Deleting this address will not delete any pending orders being shipped to this address. To ensure uninterrupted fulfillment of future orders, please update any wishliXXs, subscribe and save settings and periodical subscriptions using this address.
</span>
</div>
<div class="a-row a-spacing-none">
<hr class="a-divider-normal"/>
</div>
<div class="a-row">
<div class="a-column a-span6">
<div class="a-row">
<div class="a-column a-span3"/>
<div class="a-column a-span8">
<span id="deleteAddressModal-2-cancel-btn" class="a-button a-button-span12">
<span class="a-button-inner">
<button id="deleteAddressModal-2-cancel-btn-announce" class="a-button-text" type="button">No</button>
</span>
</span>
</div>
</div>
</div>
<div class="a-column a-span6 a-span-laXX">
<div class="a-row">
<div class="a-column a-span1"/>
<div class="a-column a-span8">
<form class="a-spacing-none" action="/a/addresses/delete" method="poXX">
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="addressID"/>
<input type="hidden" value="false" name="isXXoreAddress"/>
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXX" name="csrfToken"/>
<span id="deleteAddressModal-2-submit-btn" class="a-button a-button-span12 a-button-primary">
<span class="a-button-inner">
<input class="a-button-input" type="submit" aria-labelledby="deleteAddressModal-2-submit-btn-announce"/>
<span id="deleteAddressModal-2-submit-btn-announce" class="a-button-text" aria-hidden="true">Yes</span>
</span>
</span>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
<form class="set-address-default" action="/a/addresses/set-default-address?ref=ya_address_book_set_default_button" method="poXX">
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXX" name="csrfToken"/>
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="addressID"/>
                  |  
<a id="ya-myab-set-default-shipping-btn-2" class="a-link-normal" href="#">Set as Default</a>
</form>
</div>
</div>
<div class="a-column a-span4 a-spacing-none a-spacing-top-mini address-column">
<div id="ya-myab-display-address-block-3" class="a-box a-spacing-none normal-desktop-address-tile">
<div class="a-box-inner a-padding-none">
<div class="a-section address-section-no-default">
<div class="a-row a-spacing-small">
<ul class="a-unordered-list a-noStyle a-vertical">
<li>
<span class="a-list-item">
<h5 id="address-ui-widgets-FullName" class="id-addr-ux-search-text a-text-bold">XXXXXXX XXXXX</h5>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-AddressLineOne" class="id-addr-ux-search-text">DDD XXXX XX</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-CityXXatePoXXalCode" class="id-addr-ux-search-text">XXXXXXXX, XX DDDDD</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-Country" class="id-addr-ux-search-text">United States</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-PhoneNumber" class="id-addr-ux-search-text">Phone number: 3472631425</span>
</span>
</li>
</ul>
<script>P.when('A', 'ready').execute(function(A) {   var $ = A.$;   var localizedXXrings = A.XXate('address-ui-widgets-XXore-map-text-id');   $(".address-ui-widgets-map-link").click(function(event) {     event.preventDefault();     window.open(this.href, localizedXXrings["address_ui_widgets_XXore_address_map_header"], "width=600,height=450");   }) }); </script>
</div>
</div>
</div>
</div>
<div id="ya-myab-edit-address-desktop-row-3" class="a-row edit-address-desktop-link">
<a id="ya-myab-address-edit-btn-3" class="a-link-normal" href="/a/addresses/edit?ref=ya_address_book_edit_button&addressID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">Edit            </a>
   |  
<a id="ya-myab-address-delete-btn-3" class="a-link-normal" href="#">
<span class="a-declarative" data-a-modal="{"name":"deleteAddressModal-3","width":"400","header":"Confirm Deletion"}" data-action="a-modal">Delete</span>
<div id="a-popover-deleteAddressModal-3" class="a-popover-preload">
<div class="a-section">
<div class="a-row a-spacing-small">
<ul class="a-unordered-list a-noStyle a-vertical">
<li>
<span class="a-list-item">
<h5 id="address-ui-widgets-FullName" class="id-addr-ux-search-text a-text-bold">XXXXXXX XXXXX</h5>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-AddressLineOne" class="id-addr-ux-search-text">DDD XXXX XX</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-CityXXatePoXXalCode" class="id-addr-ux-search-text">XXXXXXXX, XX DDDDD</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-Country" class="id-addr-ux-search-text">United States</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-PhoneNumber" class="id-addr-ux-search-text">Phone number: DDDDDDDDDD</span>
</span>
</li>
</ul>
<script>P.when('A', 'ready').execute(function(A) {   var $ = A.$;   var localizedXXrings = A.XXate('address-ui-widgets-XXore-map-text-id');   $(".address-ui-widgets-map-link").click(function(event) {     event.preventDefault();     window.open(this.href, localizedXXrings["address_ui_widgets_XXore_address_map_header"], "width=600,height=450");   }) }); </script>
</div>
<div class="a-row a-spacing-small">
<span class="a-size-small a-color-tertiary">
<span class="a-text-bold">Please note: </span>
Deleting this address will not delete any pending orders being shipped to this address. To ensure uninterrupted fulfillment of future orders, please update any wishliXXs, subscribe and save settings and periodical subscriptions using this address.
</span>
</div>
<div class="a-row a-spacing-none">
<hr class="a-divider-normal"/>
</div>
<div class="a-row">
<div class="a-column a-span6">
<div class="a-row">
<div class="a-column a-span3"/>
<div class="a-column a-span8">
<span id="deleteAddressModal-3-cancel-btn" class="a-button a-button-span12">
<span class="a-button-inner">
<button id="deleteAddressModal-3-cancel-btn-announce" class="a-button-text" type="button">No</button>
</span>
</span>
</div>
</div>
</div>
<div class="a-column a-span6 a-span-laXX">
<div class="a-row">
<div class="a-column a-span1"/>
<div class="a-column a-span8">
<form class="a-spacing-none" action="/a/addresses/delete" method="poXX">
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="addressID"/>
<input type="hidden" value="false" name="isXXoreAddress"/>
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXX" name="csrfToken"/>
<span id="deleteAddressModal-3-submit-btn" class="a-button a-button-span12 a-button-primary">
<span class="a-button-inner">
<input class="a-button-input" type="submit" aria-labelledby="deleteAddressModal-3-submit-btn-announce"/>
<span id="deleteAddressModal-3-submit-btn-announce" class="a-button-text" aria-hidden="true">Yes</span>
</span>
</span>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
<form class="set-address-default" action="/a/addresses/set-default-address?ref=ya_address_book_set_default_button" method="poXX">
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXX" name="csrfToken"/>
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="addressID"/>
                  |  
<a id="ya-myab-set-default-shipping-btn-3" class="a-link-normal" href="#">Set as Default</a>
</form>
</div>
</div>
<div class="a-column a-span4 a-spacing-none a-spacing-top-mini address-column a-span-laXX">
<div id="ya-myab-display-address-block-4" class="a-box a-spacing-none normal-desktop-address-tile">
<div class="a-box-inner a-padding-none">
<div class="a-section address-section-no-default">
<div class="a-row a-spacing-small">
<ul class="a-unordered-list a-noStyle a-vertical">
<li>
<span class="a-list-item">
<h5 id="address-ui-widgets-FullName" class="id-addr-ux-search-text a-text-bold">XXXXXXX XXXXX</h5>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-AddressLineOne" class="id-addr-ux-search-text">DDD XXXX XX</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-CityXXatePoXXalCode" class="id-addr-ux-search-text">XXXXXXXX, XX DDDDD</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-Country" class="id-addr-ux-search-text">United States</span>
</span>
</li>
</ul>
<script>P.when('A', 'ready').execute(function(A) {   var $ = A.$;   var localizedXXrings = A.XXate('address-ui-widgets-XXore-map-text-id');   $(".address-ui-widgets-map-link").click(function(event) {     event.preventDefault();     window.open(this.href, localizedXXrings["address_ui_widgets_XXore_address_map_header"], "width=600,height=450");   }) }); </script>
</div>
</div>
</div>
</div>
<div id="ya-myab-edit-address-desktop-row-4" class="a-row edit-address-desktop-link">
<a id="ya-myab-address-edit-btn-4" class="a-link-normal" href="/a/addresses/edit?ref=ya_address_book_edit_button&addressID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">Edit            </a>
   |  
<a id="ya-myab-address-delete-btn-4" class="a-link-normal" href="#">
<span class="a-declarative" data-a-modal="{"name":"deleteAddressModal-4","width":"400","header":"Confirm Deletion"}" data-action="a-modal">Delete</span>
<div id="a-popover-deleteAddressModal-4" class="a-popover-preload">
<div class="a-section">
<div class="a-row a-spacing-small">
<ul class="a-unordered-list a-noStyle a-vertical">
<li>
<span class="a-list-item">
<h5 id="address-ui-widgets-FullName" class="id-addr-ux-search-text a-text-bold">XXXXXXX XXXXX</h5>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-AddressLineOne" class="id-addr-ux-search-text">DDD XXXX XX</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-CityXXatePoXXalCode" class="id-addr-ux-search-text">XXXXXXXX, XX DDDDD</span>
</span>
</li>
<li>
<span class="a-list-item">
<span id="address-ui-widgets-Country" class="id-addr-ux-search-text">United States</span>
</span>
</li>
</ul>
<script>P.when('A', 'ready').execute(function(A) {   var $ = A.$;   var localizedXXrings = A.XXate('address-ui-widgets-XXore-map-text-id');   $(".address-ui-widgets-map-link").click(function(event) {     event.preventDefault();     window.open(this.href, localizedXXrings["address_ui_widgets_XXore_address_map_header"], "width=600,height=450");   }) }); </script>
</div>
<div class="a-row a-spacing-small">
<span class="a-size-small a-color-tertiary">
<span class="a-text-bold">Please note: </span>
Deleting this address will not delete any pending orders being shipped to this address. To ensure uninterrupted fulfillment of future orders, please update any wishliXXs, subscribe and save settings and periodical subscriptions using this address.
</span>
</div>
<div class="a-row a-spacing-none">
<hr class="a-divider-normal"/>
</div>
<div class="a-row">
<div class="a-column a-span6">
<div class="a-row">
<div class="a-column a-span3"/>
<div class="a-column a-span8">
<span id="deleteAddressModal-4-cancel-btn" class="a-button a-button-span12">
<span class="a-button-inner">
<button id="deleteAddressModal-4-cancel-btn-announce" class="a-button-text" type="button">No</button>
</span>
</span>
</div>
</div>
</div>
<div class="a-column a-span6 a-span-laXX">
<div class="a-row">
<div class="a-column a-span1"/>
<div class="a-column a-span8">
<form class="a-spacing-none" action="/a/addresses/delete" method="poXX">
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="addressID"/>
<input type="hidden" value="false" name="isXXoreAddress"/>
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXX" name="csrfToken"/>
<span id="deleteAddressModal-4-submit-btn" class="a-button a-button-span12 a-button-primary">
<span class="a-button-inner">
<input class="a-button-input" type="submit" aria-labelledby="deleteAddressModal-4-submit-btn-announce"/>
<span id="deleteAddressModal-4-submit-btn-announce" class="a-button-text" aria-hidden="true">Yes</span>
</span>
</span>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
<form class="set-address-default" action="/a/addresses/set-default-address?ref=ya_address_book_set_default_button" method="poXX">
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXX" name="csrfToken"/>
<input type="hidden" value="XXXXXXXXXXXXXXXXXXXXXXX" name="addressID"/>
                  |  
<a id="ya-myab-set-default-shipping-btn-4" class="a-link-normal" href="#">Set as Default</a>
</form>
</div>
</div>
</div>

大致对应于以下布局/设计:

enter image description here

如上图所示,每个框都包含一个名称和地址,并带有“编辑”,“删除”或“设为默认值”选项。

仅提供地址或名称 - 如何点击&#34;设为默认值&#34;对应的地址(或名称)?

到目前为止,唯一可用的XPath基于链接几个/parent::*/表达式,如下所示。

.//*[contains (text(),'123 XYZ AVE')]/parent::*/parent::*/parent::*/parent::*/parent::*/parent::*/parent::*/parent::*/form/input (selects based on address)

.//*[contains (text(),'NAME')]/parent::*/parent::*/parent::*/parent::*/parent::*/parent::*/parent::*/parent::*/form/input (selects based on name)

之前的表达式所做的是它们告诉Selenium找到名称或地址(.//*[contains (text(),'NAME')]),然后向上/向后移动几个级别,直到到达包含所有子元素的元素(包括编辑,删除和设置为默认选项),然后找到值为/form/input的元素。

虽然这有效,但如果父元素的任何的结构/数量发生变化,它会非常庞大​​且难以操作并且容易中断。

如何简化此表达式,以便给定地址或名称(假设所有地址/名称都是唯一的)我可以识别并单击相关的&#34;设为默认值&#34;选项没有爬上层次结构?

谢谢!

2 个答案:

答案 0 :(得分:2)

首先找到整个地址部分属于一个人的姓名,然后在该部分中找到Edit/Delete/Set as Default按钮:

private WebElement findAddressSection(customerName) {
    String xpathExp = "//div[contains(@class, 'a-column a-span4')]" +
           "[div//h5[text()='"+ customerName+"']]";

    return driver.findElement(By.xpath(xpathExp));
}

public void clickAddressEditBtn(customerName) {
    WebElement section = findAddressSection(customerName);

    section.findElement(By.cssSelector("a[id*='ya-myab-address-edit-btn']"))
           .click();
}

public void clickAddressDeleteBtn(customerName) {
    WebElement section = findAddressSection(customerName);

    section.findElement(By.cssSelector("a[id*='ya-myab-address-delete-btn']"))
           .click();
}

public void clickAddressSetDefaultBtn(customerName) {
    WebElement section = findAddressSection(customerName);

    section.findElement(By.cssSelector("a[id*='ya-myab-set-default-shipping-btn']"))
           .click();
}

答案 1 :(得分:0)

示例HTML包含多个错误(重复的ID等),但下面的xpath应该有助于获取值

'//*[contains(.,"abcdert")]/descendant::form/input'