I want to select an input, based of its label. I found below xpath, which returns 3 inputs, even though two of returned inputs have different labels. I want to understand why it works like that and how to improve it to return correct (one) input element. Here is the xpath:
//input[@id=(//label[.='Max Driving Time_h']/@for)]
And yes, I know I can get the proper input with xpath like this:
//label[.='Max Driving Time_h']/ancestor::div/input
I would just like to understand, what's wrong with the first xpath ;) Thank you in advance!
Here is the HTML code to try...
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<div >
<mat-tab-body role="tabpanel" id="mat-tab-content-4-0" aria-labelledby="mat-tab-label-4-0">
<div cdkscrollable="" style="transform: none;">
<!---->
<div fxlayout="column" fxlayoutalign="space-between start" style="padding-top: 10px; flex-direction: column; box-sizing: border-box; display: flex; place-content: flex-start space-between; align-items: flex-start;" >
<dsg-input-duration >
<div flex-wrap="nowrap" style="display: inline-block; margin-right: 15px;" >
<div fxlayout="column" fxlayoutalign="start start" style="flex-direction: column; box-sizing: border-box; display: flex; place-content: flex-start; align-items: flex-start;">
<div >Max Driving Time</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<mat-form-field floatlabel="always" >
<div >
<div >
<!----><!---->
<div >
<input matinput="" formcontrolname="hours" id="h" name="h" type="number" min="0" autocomplete="really-off" aria-invalid="false" aria-required="false" max="23">
<span >
<label id="mat-form-field-label-179" for="h" aria-owns="h">
<!---->
<mat-label style="visibility: hidden !important;" >Max Driving Time_h</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div ><span ></span></div>
<!---->
<div >
<!---->
<div style="opacity: 1; transform: translateY(0%);">
<!---->
<div ></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="h" >h</label>
<mat-form-field >
<div >
<div >
<!----><!---->
<div >
<input matinput="" formcontrolname="minutes" id="m" name="m" type="number" min="0" max="59" autocomplete="really-off" aria-invalid="false" aria-required="false">
<span >
<label id="mat-form-field-label-181" for="m" aria-owns="m">
<!---->
<mat-label style="visibility: hidden !important; display: none;" >Max Driving Time_m</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div ><span ></span></div>
<!---->
<div >
<!---->
<div style="opacity: 1; transform: translateY(0%);">
<!---->
<div ></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="m" >m</label><!----><!---->
</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<div fxlayout="column" style="flex-direction: column; box-sizing: border-box; display: flex;">
<!----><!----><!----><!----><!----><!----><!----><!----><!---->
</div>
</div>
</div>
</div>
</dsg-input-duration>
<dsg-input-duration >
<div flex-wrap="nowrap" style="display: inline-block; margin-right: 15px;" >
<div fxlayout="column" fxlayoutalign="start start" style="flex-direction: column; box-sizing: border-box; display: flex; place-content: flex-start; align-items: flex-start;">
<div >Max Elapsed Time</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<mat-form-field floatlabel="always" >
<div >
<div >
<!----><!---->
<div >
<input matinput="" formcontrolname="hours" id="h" name="h" type="number" min="0" autocomplete="really-off" aria-invalid="false" aria-required="false" max="23">
<span >
<label id="mat-form-field-label-183" for="h" aria-owns="h">
<!---->
<mat-label style="visibility: hidden !important;" >Max Elapsed Time_h</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div ><span ></span></div>
<!---->
<div >
<!---->
<div style="opacity: 1; transform: translateY(0%);">
<!---->
<div ></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="h" >h</label>
<mat-form-field >
<div >
<div >
<!----><!---->
<div >
<input matinput="" formcontrolname="minutes" id="m" name="m" type="number" min="0" max="59" autocomplete="really-off" aria-invalid="false" aria-required="false">
<span >
<label id="mat-form-field-label-185" for="m" aria-owns="m">
<!---->
<mat-label style="visibility: hidden !important; display: none;" >Max Elapsed Time_m</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div ><span ></span></div>
<!---->
<div >
<!---->
<div style="opacity: 1; transform: translateY(0%);">
<!---->
<div ></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="m" >m</label><!----><!---->
</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<div fxlayout="column" style="flex-direction: column; box-sizing: border-box; display: flex;">
<!----><!----><!----><!----><!----><!----><!----><!----><!---->
</div>
</div>
</div>
</div>
</dsg-input-duration>
<dsg-input-duration >
<div flex-wrap="nowrap" style="display: inline-block; margin-right: 15px;" >
<div fxlayout="column" fxlayoutalign="start start" style="flex-direction: column; box-sizing: border-box; display: flex; place-content: flex-start; align-items: flex-start;">
<div >Max Working Time</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<mat-form-field floatlabel="always" >
<div >
<div >
<!----><!---->
<div >
<input matinput="" formcontrolname="hours" id="h" name="h" type="number" min="0" autocomplete="really-off" aria-invalid="false" aria-required="false" max="23">
<span >
<label id="mat-form-field-label-187" for="h" aria-owns="h">
<!---->
<mat-label style="visibility: hidden !important;" >Max Working Time_h</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div ><span ></span></div>
<!---->
<div >
<!---->
<div style="opacity: 1; transform: translateY(0%);">
<!---->
<div ></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="h" >h</label>
<mat-form-field >
<div >
<div >
<!----><!---->
<div >
<input matinput="" formcontrolname="minutes" id="m" name="m" type="number" min="0" max="59" autocomplete="really-off" aria-invalid="false" aria-required="false">
<span >
<label id="mat-form-field-label-189" for="m" aria-owns="m">
<!---->
<mat-label style="visibility: hidden !important; display: none;" >Max Working Time_m</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div ><span ></span></div>
<!---->
<div >
<!---->
<div style="opacity: 1; transform: translateY(0%);">
<!---->
<div ></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="m" >m</label><!----><!---->
</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<div fxlayout="column" style="flex-direction: column; box-sizing: border-box; display: flex;">
<!----><!----><!----><!----><!----><!----><!----><!----><!---->
</div>
</div>
</div>
</div>
</dsg-input-duration>
<dsg-input-number controlname="maxDistance">
<div style="display: inline-block;">
<mat-form-field floatlabel="always" >
<div >
<div >
<!----><!---->
<div >
<input matinput="" type="number" autofocus="" autocomplete="off" step="" id="maxDistance" data-placeholder="" aria-invalid="false" aria-required="false" min="-Infinity" max="2147483647" maxlength="14">
<span >
<label id="mat-form-field-label-191" for="maxDistance" aria-owns="maxDistance">
<!---->
<mat-label >Max Distance [km]</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div ><span ></span></div>
<!---->
<div >
<!---->
<div style="opacity: 1; transform: translateY(0%);">
<!---->
<div ></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
</div>
</dsg-input-number>
</div>
<!---->
</div>
</mat-tab-body>
<mat-tab-body role="tabpanel" id="mat-tab-content-4-1" aria-labelledby="mat-tab-label-4-1">
<div cdkscrollable="" style="transform: translate3d(100%, 0px, 0px); min-height: 1px;">
<!---->
</div>
</mat-tab-body>
<!---->
</div>
</body>
</html>
CodePudding user response:
Try below XPath:
//input[@id=(./following::label[.='Max Driving Time_h']/@for)]
Your XPath doesn't work because it states that you need to find all input
nodes if they have the same @id
value as the @for
value of label
with text 'Max Driving Time_h'
while you need only the input
with corresponding label
(note the .
that means "context node")
CodePudding user response:
According to your sample, the following XPath //input[@id=(//label[.='Max Driving Time_h']/@for)]
doesn't work since :
"Max Driving Time_h"
text is contained inside amat-label
node, not alabel
one.@for
attribute belongs to thatlabel
node.
You can fix your XPath several ways. Don't forget to add (...)[1] to get the first result only :
(//input[@id=//mat-label[.='Max Driving Time_h']/../@for])[1]
(//input[@id=//label[./mat-label[.="Max Driving Time_h"]]/@for])[1]
That being said, to be shorter and more efficient, just use :
//input[./following::mat-label[.='Max Driving Time_h']]