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 class="mat-tab-body-wrapper">
<mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c344-232 mat-tab-body-active ng-star-inserted" id="mat-tab-content-4-0" aria-labelledby="mat-tab-label-4-0">
<div cdkscrollable="" class="mat-tab-body-content ng-tns-c344-232 ng-trigger ng-trigger-translateTab" 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;" class="ng-star-inserted">
<dsg-input-duration class="ng-valid ng-touched ng-dirty">
<div flex-wrap="nowrap" style="display: inline-block; margin-right: 15px;" class="ng-valid ng-untouched ng-pristine">
<div fxlayout="column" fxlayoutalign="start start" class="mainLayout" style="flex-direction: column; box-sizing: border-box; display: flex; place-content: flex-start; align-items: flex-start;">
<div class="placeHolder">Max Driving Time</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<mat-form-field floatlabel="always" class="mat-form-field durationField durationLabel ng-tns-c84-225 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-legacy mat-form-field-can-float mat-form-field-should-float mat-form-field-has-label ng-valid ng-star-inserted ng-untouched ng-pristine">
<div class="mat-form-field-wrapper ng-tns-c84-225">
<div class="mat-form-field-flex ng-tns-c84-225">
<!----><!---->
<div class="mat-form-field-infix ng-tns-c84-225">
<input matinput="" formcontrolname="hours" id="h" name="h" type="number" min="0" autocomplete="really-off" class="mat-input-element mat-form-field-autofill-control ng-tns-c84-225 ng-valid cdk-text-field-autofill-monitored ng-untouched ng-pristine" aria-invalid="false" aria-required="false" max="23">
<span class="mat-form-field-label-wrapper ng-tns-c84-225">
<label class="mat-form-field-label ng-tns-c84-225 ng-star-inserted" id="mat-form-field-label-179" for="h" aria-owns="h">
<!---->
<mat-label style="visibility: hidden !important;" class="ng-tns-c84-225 ng-star-inserted">Max Driving Time_h</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div class="mat-form-field-underline ng-tns-c84-225 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c84-225"></span></div>
<!---->
<div class="mat-form-field-subscript-wrapper ng-tns-c84-225">
<!---->
<div class="mat-form-field-hint-wrapper ng-tns-c84-225 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<!---->
<div class="mat-form-field-hint-spacer ng-tns-c84-225"></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="h" class="durationSpaceForInputs">h</label>
<mat-form-field class="mat-form-field durationField durationLabel ng-tns-c84-226 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-legacy mat-form-field-can-float mat-form-field-has-label ng-valid ng-star-inserted mat-form-field-should-float ng-untouched ng-pristine">
<div class="mat-form-field-wrapper ng-tns-c84-226">
<div class="mat-form-field-flex ng-tns-c84-226">
<!----><!---->
<div class="mat-form-field-infix ng-tns-c84-226">
<input matinput="" formcontrolname="minutes" id="m" name="m" type="number" min="0" max="59" autocomplete="really-off" class="mat-input-element mat-form-field-autofill-control ng-tns-c84-226 ng-valid cdk-text-field-autofill-monitored ng-untouched ng-pristine" aria-invalid="false" aria-required="false">
<span class="mat-form-field-label-wrapper ng-tns-c84-226">
<label class="mat-form-field-label ng-tns-c84-226 ng-star-inserted" id="mat-form-field-label-181" for="m" aria-owns="m">
<!---->
<mat-label style="visibility: hidden !important; display: none;" class="ng-tns-c84-226 ng-star-inserted">Max Driving Time_m</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div class="mat-form-field-underline ng-tns-c84-226 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c84-226"></span></div>
<!---->
<div class="mat-form-field-subscript-wrapper ng-tns-c84-226">
<!---->
<div class="mat-form-field-hint-wrapper ng-tns-c84-226 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<!---->
<div class="mat-form-field-hint-spacer ng-tns-c84-226"></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="m" class="durationSpaceForInputs">m</label><!----><!---->
</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<div fxlayout="column" class="errorMessage" style="flex-direction: column; box-sizing: border-box; display: flex;">
<!----><!----><!----><!----><!----><!----><!----><!----><!---->
</div>
</div>
</div>
</div>
</dsg-input-duration>
<dsg-input-duration class="ng-valid ng-touched ng-dirty">
<div flex-wrap="nowrap" style="display: inline-block; margin-right: 15px;" class="ng-valid ng-untouched ng-pristine">
<div fxlayout="column" fxlayoutalign="start start" class="mainLayout" style="flex-direction: column; box-sizing: border-box; display: flex; place-content: flex-start; align-items: flex-start;">
<div class="placeHolder">Max Elapsed Time</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<mat-form-field floatlabel="always" class="mat-form-field durationField durationLabel ng-tns-c84-227 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-legacy mat-form-field-can-float mat-form-field-should-float mat-form-field-has-label ng-valid ng-star-inserted ng-untouched ng-pristine">
<div class="mat-form-field-wrapper ng-tns-c84-227">
<div class="mat-form-field-flex ng-tns-c84-227">
<!----><!---->
<div class="mat-form-field-infix ng-tns-c84-227">
<input matinput="" formcontrolname="hours" id="h" name="h" type="number" min="0" autocomplete="really-off" class="mat-input-element mat-form-field-autofill-control ng-tns-c84-227 ng-valid cdk-text-field-autofill-monitored ng-untouched ng-pristine" aria-invalid="false" aria-required="false" max="23">
<span class="mat-form-field-label-wrapper ng-tns-c84-227">
<label class="mat-form-field-label ng-tns-c84-227 ng-star-inserted" id="mat-form-field-label-183" for="h" aria-owns="h">
<!---->
<mat-label style="visibility: hidden !important;" class="ng-tns-c84-227 ng-star-inserted">Max Elapsed Time_h</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div class="mat-form-field-underline ng-tns-c84-227 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c84-227"></span></div>
<!---->
<div class="mat-form-field-subscript-wrapper ng-tns-c84-227">
<!---->
<div class="mat-form-field-hint-wrapper ng-tns-c84-227 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<!---->
<div class="mat-form-field-hint-spacer ng-tns-c84-227"></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="h" class="durationSpaceForInputs">h</label>
<mat-form-field class="mat-form-field durationField durationLabel ng-tns-c84-228 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-legacy mat-form-field-can-float mat-form-field-has-label ng-valid ng-star-inserted mat-form-field-should-float ng-untouched ng-pristine">
<div class="mat-form-field-wrapper ng-tns-c84-228">
<div class="mat-form-field-flex ng-tns-c84-228">
<!----><!---->
<div class="mat-form-field-infix ng-tns-c84-228">
<input matinput="" formcontrolname="minutes" id="m" name="m" type="number" min="0" max="59" autocomplete="really-off" class="mat-input-element mat-form-field-autofill-control ng-tns-c84-228 ng-valid cdk-text-field-autofill-monitored ng-untouched ng-pristine" aria-invalid="false" aria-required="false">
<span class="mat-form-field-label-wrapper ng-tns-c84-228">
<label class="mat-form-field-label ng-tns-c84-228 ng-star-inserted" id="mat-form-field-label-185" for="m" aria-owns="m">
<!---->
<mat-label style="visibility: hidden !important; display: none;" class="ng-tns-c84-228 ng-star-inserted">Max Elapsed Time_m</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div class="mat-form-field-underline ng-tns-c84-228 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c84-228"></span></div>
<!---->
<div class="mat-form-field-subscript-wrapper ng-tns-c84-228">
<!---->
<div class="mat-form-field-hint-wrapper ng-tns-c84-228 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<!---->
<div class="mat-form-field-hint-spacer ng-tns-c84-228"></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="m" class="durationSpaceForInputs">m</label><!----><!---->
</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<div fxlayout="column" class="errorMessage" style="flex-direction: column; box-sizing: border-box; display: flex;">
<!----><!----><!----><!----><!----><!----><!----><!----><!---->
</div>
</div>
</div>
</div>
</dsg-input-duration>
<dsg-input-duration class="ng-valid ng-touched ng-dirty">
<div flex-wrap="nowrap" style="display: inline-block; margin-right: 15px;" class="ng-valid ng-untouched ng-pristine">
<div fxlayout="column" fxlayoutalign="start start" class="mainLayout" style="flex-direction: column; box-sizing: border-box; display: flex; place-content: flex-start; align-items: flex-start;">
<div class="placeHolder">Max Working Time</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<mat-form-field floatlabel="always" class="mat-form-field durationField durationLabel ng-tns-c84-229 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-legacy mat-form-field-can-float mat-form-field-should-float mat-form-field-has-label ng-valid ng-star-inserted ng-untouched ng-pristine">
<div class="mat-form-field-wrapper ng-tns-c84-229">
<div class="mat-form-field-flex ng-tns-c84-229">
<!----><!---->
<div class="mat-form-field-infix ng-tns-c84-229">
<input matinput="" formcontrolname="hours" id="h" name="h" type="number" min="0" autocomplete="really-off" class="mat-input-element mat-form-field-autofill-control ng-tns-c84-229 ng-valid cdk-text-field-autofill-monitored ng-untouched ng-pristine" aria-invalid="false" aria-required="false" max="23">
<span class="mat-form-field-label-wrapper ng-tns-c84-229">
<label class="mat-form-field-label ng-tns-c84-229 ng-star-inserted" id="mat-form-field-label-187" for="h" aria-owns="h">
<!---->
<mat-label style="visibility: hidden !important;" class="ng-tns-c84-229 ng-star-inserted">Max Working Time_h</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div class="mat-form-field-underline ng-tns-c84-229 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c84-229"></span></div>
<!---->
<div class="mat-form-field-subscript-wrapper ng-tns-c84-229">
<!---->
<div class="mat-form-field-hint-wrapper ng-tns-c84-229 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<!---->
<div class="mat-form-field-hint-spacer ng-tns-c84-229"></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="h" class="durationSpaceForInputs">h</label>
<mat-form-field class="mat-form-field durationField durationLabel ng-tns-c84-230 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-legacy mat-form-field-can-float mat-form-field-has-label ng-valid ng-star-inserted mat-form-field-should-float ng-untouched ng-pristine">
<div class="mat-form-field-wrapper ng-tns-c84-230">
<div class="mat-form-field-flex ng-tns-c84-230">
<!----><!---->
<div class="mat-form-field-infix ng-tns-c84-230">
<input matinput="" formcontrolname="minutes" id="m" name="m" type="number" min="0" max="59" autocomplete="really-off" class="mat-input-element mat-form-field-autofill-control ng-tns-c84-230 ng-valid cdk-text-field-autofill-monitored ng-untouched ng-pristine" aria-invalid="false" aria-required="false">
<span class="mat-form-field-label-wrapper ng-tns-c84-230">
<label class="mat-form-field-label ng-tns-c84-230 ng-star-inserted" id="mat-form-field-label-189" for="m" aria-owns="m">
<!---->
<mat-label style="visibility: hidden !important; display: none;" class="ng-tns-c84-230 ng-star-inserted">Max Working Time_m</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div class="mat-form-field-underline ng-tns-c84-230 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c84-230"></span></div>
<!---->
<div class="mat-form-field-subscript-wrapper ng-tns-c84-230">
<!---->
<div class="mat-form-field-hint-wrapper ng-tns-c84-230 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<!---->
<div class="mat-form-field-hint-spacer ng-tns-c84-230"></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
<label for="m" class="durationSpaceForInputs">m</label><!----><!---->
</div>
<div fxlayout="row" style="flex-direction: row; box-sizing: border-box; display: flex;">
<div fxlayout="column" class="errorMessage" style="flex-direction: column; box-sizing: border-box; display: flex;">
<!----><!----><!----><!----><!----><!----><!----><!----><!---->
</div>
</div>
</div>
</div>
</dsg-input-duration>
<dsg-input-number controlname="maxDistance">
<div class="ng-touched ng-dirty ng-valid" style="display: inline-block;">
<mat-form-field floatlabel="always" class="mat-form-field ng-tns-c84-231 mat-primary mat-form-field-type-mat-input mat-form-field-appearance-legacy mat-form-field-can-float mat-form-field-should-float mat-form-field-has-label ng-valid ng-star-inserted ng-touched ng-pristine">
<div class="mat-form-field-wrapper ng-tns-c84-231">
<div class="mat-form-field-flex ng-tns-c84-231">
<!----><!---->
<div class="mat-form-field-infix ng-tns-c84-231">
<input matinput="" type="number" class="mat-input-element mat-form-field-autofill-control ng-tns-c84-231 ng-valid cdk-text-field-autofill-monitored ng-touched ng-pristine" autofocus="" autocomplete="off" step="" id="maxDistance" data-placeholder="" aria-invalid="false" aria-required="false" min="-Infinity" max="2147483647" maxlength="14">
<span class="mat-form-field-label-wrapper ng-tns-c84-231">
<label class="mat-form-field-label ng-tns-c84-231 ng-star-inserted" id="mat-form-field-label-191" for="maxDistance" aria-owns="maxDistance">
<!---->
<mat-label class="ng-tns-c84-231 ng-star-inserted">Max Distance [km]</mat-label>
<!----><!---->
</label>
<!---->
</span>
</div>
<!---->
</div>
<div class="mat-form-field-underline ng-tns-c84-231 ng-star-inserted"><span class="mat-form-field-ripple ng-tns-c84-231"></span></div>
<!---->
<div class="mat-form-field-subscript-wrapper ng-tns-c84-231">
<!---->
<div class="mat-form-field-hint-wrapper ng-tns-c84-231 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<!---->
<div class="mat-form-field-hint-spacer ng-tns-c84-231"></div>
</div>
<!---->
</div>
</div>
</mat-form-field>
</div>
</dsg-input-number>
</div>
<!---->
</div>
</mat-tab-body>
<mat-tab-body role="tabpanel" class="mat-tab-body ng-tns-c344-233 ng-star-inserted" id="mat-tab-content-4-1" aria-labelledby="mat-tab-label-4-1">
<div cdkscrollable="" class="mat-tab-body-content ng-tns-c344-233 ng-trigger ng-trigger-translateTab" style="transform: translate3d(100%, 0px, 0px); min-height: 1px;">
<!---->
</div>
</mat-tab-body>
<!---->
</div>
</body>
</html>
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")