J'écris un test de sélénium. Et voici l'expression xpath que j'utilise pour faire correspondre tous les boutons 'Modifier' d'une table de données.
//img[@title='Modify']
Ma question est la suivante: comment puis-je visiter les ensembles de nœuds correspondants par index? J'ai essayé avec
//img[@title='Modify'][i]
et
//img[@title='Modify' and position() = i]
Mais ni l'un ni l'autre ne fonctionne. J'ai aussi essayé avec le vérificateur XPath (une extension firefox). Il y a un total de 13 correspondances trouvées, alors je ne sais absolument pas comment je vais sélectionner l'une d'entre elles .. Ou XPath prend-il en charge la sélection spécifiée de nœuds qui ne sont pas sous le même nœud parent?
Ceci est une FAQ:
//someName[3]
signifie: tous les someName
éléments du document, qui sont le troisième someName
enfant de leur parent - ces éléments peuvent être nombreux.
Ce que vous voulez, c'est exactement le 3ème élément someName
:
(//someName)[3]
Explication: le []
a une priorité plus élevée que //
. Rappelez-vous toujours de mettre des expressions du type //someName
entre parenthèses lorsque vous devez spécifier le nième nœud de la liste de nœuds sélectionnée.
Il n'y a pas de i
dans XPath.
Soit vous utilisez des nombres littéraux: //img[@title='Modify'][1]
Ou vous construisez la chaîne d'expression dynamiquement: '//img[@title='Modify']['+i+']'
(Mais gardez à l'esprit que les expressions XPath dynamiques ne fonctionnent pas à partir de inside XSLT).
Ou XPath prend-il en charge la sélection spécifiée de nœuds qui ne sont pas sous le même nœud parent?
Oui: (//img[@title='Modify'])[13]
Ce //img[@title='Modify'][i]
Signifie "tout <img>
Ayant pour titre" Modify "et un élément enfant nommé <i>
."
//img[@title='Modify'][i]
est l'abréviation de
/descendant-or-self::node()/img[@title='Modify'][i]
retourne donc le ième nœud sous le même nœud parent.
Tu veux
/descendant-or-self::img[@title='Modify'][i]
Il n'y a pas i
dans xpath n'est pas tout à fait vrai. Vous pouvez toujours utiliser la count()
pour rechercher l'index.
Considérez la page suivante
<html>
<head>
<style>
table, td, th {
border: 1px solid black;
font-size: 15px;
font-family: Trebuchet MS, sans-serif;
}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
text-align: left;
padding: 8px;
}
tr:nth-child(even){background-color: #f2f2f2}
th {
background-color: #4CAF50;
color: white;
}
</style>
<table>
<thead>
<tr>
<th>Heading 1</th>
<th>Heading 2</th>
<th>Heading 3</th>
<th>Heading 4</th>
<th>Heading 5</th>
<th>Heading 6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data row 1 col 1</td>
<td>Data row 1 col 2</td>
<td>Data row 1 col 3</td>
<td>Data row 1 col 4</td>
<td>Data row 1 col 5</td>
<td>Data row 1 col 6</td>
</tr>
<tr>
<td>Data row 2 col 1</td>
<td>Data row 2 col 2</td>
<td>Data row 2 col 3</td>
<td>Data row 2 col 4</td>
<td>Data row 2 col 5</td>
<td>Data row 2 col 6</td>
</tr>
<tr>
<td>Data row 3 col 1</td>
<td>Data row 3 col 2</td>
<td>Data row 3 col 3</td>
<td>Data row 3 col 4</td>
<td>Data row 3 col 5</td>
<td>Data row 3 col 6</td>
</tr>
<tr>
<td>Data row 4 col 1</td>
<td>Data row 4 col 2</td>
<td>Data row 4 col 3</td>
<td>Data row 4 col 4</td>
<td>Data row 4 col 5</td>
<td>Data row 4 col 6</td>
</tr>
<tr>
<td>Data row 5 col 1</td>
<td>Data row 5 col 2</td>
<td>Data row 5 col 3</td>
<td>Data row 5 col 4</td>
<td>Data row 5 col 5</td>
<td>Data row 5 col 6</td>
</tr>
<tr>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
</tr>
</tbody>
</table>
</br>
<table>
<thead>
<tr>
<th>Heading 7</th>
<th>Heading 8</th>
<th>Heading 9</th>
<th>Heading 10</th>
<th>Heading 11</th>
<th>Heading 12</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data row 1 col 1</td>
<td>Data row 1 col 2</td>
<td>Data row 1 col 3</td>
<td>Data row 1 col 4</td>
<td>Data row 1 col 5</td>
<td>Data row 1 col 6</td>
</tr>
<tr>
<td>Data row 2 col 1</td>
<td>Data row 2 col 2</td>
<td>Data row 2 col 3</td>
<td>Data row 2 col 4</td>
<td>Data row 2 col 5</td>
<td>Data row 2 col 6</td>
</tr>
<tr>
<td>Data row 3 col 1</td>
<td>Data row 3 col 2</td>
<td>Data row 3 col 3</td>
<td>Data row 3 col 4</td>
<td>Data row 3 col 5</td>
<td>Data row 3 col 6</td>
</tr>
<tr>
<td>Data row 4 col 1</td>
<td>Data row 4 col 2</td>
<td>Data row 4 col 3</td>
<td>Data row 4 col 4</td>
<td>Data row 4 col 5</td>
<td>Data row 4 col 6</td>
</tr>
<tr>
<td>Data row 5 col 1</td>
<td>Data row 5 col 2</td>
<td>Data row 5 col 3</td>
<td>Data row 5 col 4</td>
<td>Data row 5 col 5</td>
<td>Data row 5 col 6</td>
</tr>
<tr>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
<td><button>Modify</button></td>
</tr>
</tbody>
</table>
</head>
</html>
La page comporte 2 tables et 6 colonnes avec chacune un nom de colonne unique et 6 lignes avec des données variables. La dernière ligne contient le bouton Modify
dans les deux tables.
En supposant que l'utilisateur doit sélectionner le 4ème bouton Modify
de la première table en fonction de l'en-tête
Utilisez le xpath //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button
L'opérateur count()
est très utile dans de telles situations.
Logique:
Modify
à l’aide de //th[.='Heading 4']
count(//tr/th[.='Heading 4']/preceding-sibling::th)+1
Note: L'index commence à
0
Récupère les lignes de l'en-tête correspondant en utilisant //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]
Obtenez le bouton Modify
de la liste de noeuds extraite en utilisant //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button
(// * [@ attribut = 'valeur']) [index] pour trouver la cible de l'élément pendant que vous en trouvez plusieurs correspondances
Voici la solution pour la variable d'index
Disons que vous avez trouvé 5 éléments avec le même localisateur et que vous souhaitez effectuer une action sur chaque élément en fournissant un numéro d'index (ici, la variable est utilisée pour l'index en tant que "i")
for(int i=1; i<=5; i++)
{
string xPathWithVariable = "(//div[@class='className'])" + "[" + i + "]";
driver.FindElement(By.XPath(xPathWithVariable)).Click();
}
Il faut XPath:
(//div[@class='className'])[1]
(//div[@class='className'])[2]
(//div[@class='className'])[3]
(//div[@class='className'])[4]
(//div[@class='className'])[5]