2012-02-06 4 views
6

Voici quelque chose de vraiment simple (du moins je suppose), je n'ai pas la moindre idée.xpath obtiens la dernière partie du précédent-frère

Je dois analyser un grand document XML pour obtenir un noeud spécifique, identifié par l'une de ses valeurs de sous-noeud. C'est facile jusqu'ici. Mais quand j'essaie d'analyser relativement vers le haut de ce nœud, en sélectionnant les frères et soeurs de son ancêtre en utilisant un prédicat, je reçois une liste de nœuds, à partir de là je dois redescendre.

En théorie, c'est une table, avec 5 colonnes et deux rangées (dans l'exemple ci-dessous). Je reçois juste l'élément id d'un champ, et j'ai besoin de trouver le nom donné dans le premier champ de la rangée. Le premier champ est toujours de type 'Link' et a un nom de sous-noeud avec du texte - ce qui est la chose à obtenir. En d'autres termes, je dois passer de n'importe quel nœud avec <id>XXX_X</i> à la cellule précédente suivante avec un contrôle xsi:type='Label' et un nœud de nom. Du noeud <id>MyItemId_1</> je dois obtenir le deuxième frère précédent, du noeud <id>MyItemId_4</id> je dois obtenir le 5ème frère précédent.

C'est un morceau échantillon xml:

<cell> 
    <control xsi:type="Label"> 
     <id>1234</id> 
     <name>MyOtherItemName</name> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyOtherItemId_0</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyOtherItemId_1</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyOtherItemId_2</id> 
     <name>552</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyOtherItemId_3</id> 
     <name>432</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyOtherItemId_4</id> 
     <name>33</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>1234</id> 
     <name>MyItemName</name> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyItemId_0</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyItemId_1</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyItemId_2</id> 
     <name>552</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyItemId_3</id> 
     <name>432</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyItemId_4</id> 
     <name>33</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 

Je reçois l'article que je dois obtenir cette XPath:

//cell[control[type='Link']]/control[type='Link' and selected='false' and id='MyItemId_3']/id 

qui sélectionne l'ID du contrôle de la cellule, à savoir la 4ème colonne dans la deuxième rangée, de la table rendue.

A partir de ce nœud que j'essaie de passer à la première cellule de la ligne en suivant ce chemin:

../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]]/control[name[node()]]/name 

Cela me donne les deux cellules correctes de la première colonne du tableau.

<name>MyOtherItemName</name> 
* * * * * * * * * * 
<name>MyItemName</name> 

Maintenant, ça me brise le dos, car je ne peux pas me le rendre juste le dernier des deux sélectionnés.

J'ai essayé ceci:

../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]][1]/control[name[node()]]/name 

qui est une sélection preceding-sibling avec un prédicat exactement le genre de frères et sœurs que je recherche pour, mais il semble que je ne peux pas combiner ce prédicat avec un [1] sélecteur . Au lieu de sélectionner le premier frère désiré "MyItemName", il sélectionne le premier frère de tous les précédents "MyOtherItemName".

J'ai besoin d'aide, j'espère que quelqu'un ici a une idée et peut me localiser dans la bonne direction.

Exactement ce que je mis en place pour obtenir ce travail consiste à copier le fichier XML en http://www.bit-101.com/xpath/ et travailler avec les xpathes chaînées sur pour simuler ce que le logiciel doit faire:

//cell[control[type='Link']]/control[type='Link' and selected='false' and id='MyItemId_3']/id/../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]]/control[name[node()]]/name 
+0

Vous essayez donc de sélectionner MyItemName? Comment est la première cellule de la rangée? Ça ne ressemble certainement pas à ça. –

+0

Je l'ai perdu quelque part entre la table 5 colonnes et le premier champ de type Link. Pensez-vous que vous pouvez reformuler vos exigences sans l'analogie de la table? –

+0

D'accord avec @ quarante-deux. Il est souvent bon de montrer ce que vous avez essayé, alors je vous remercie pour ce travail, mais dans ce cas, le-ce-que j'ai essayé obscurcit vos exigences d'origine. Vous avez oublié de nous dire exactement et précisément ce que vous essayiez de faire en premier lieu. –

Répondre

11

Je ne comprends pas quel est le problème est exactement, mais les frères et sœurs précédents sont triés du noeud lui-même vers le début du document, c'est-à-dire dans l'autre sens que dans le document. Pour obtenir le frère précédent le plus proche, utilisez preceding-sibling[1], pour obtenir le plus éloigné (c'est-à-dire le premier dans l'ordre du document), utilisez preceding-sibling[last()].

+0

c'est exact, mais comment puis-je utiliser la sélection du premier frère seulement parmi les frères et sœurs précédents qui correspondent au prédicat? using PREFICATE [PREDICATE] [1] ne fonctionne pas - ne renvoie aucun noeud –

+3

Utilisez 'previous-sibling :: * [PREDICATE] [1]' (fonctionne pour moi). – choroba

+0

s'il vous plaît essayez-le avec bit-101/xpath, cela ne fonctionnera pas, si vous mélangez prédicat avec sélecteur. –

1

Après avoir lu votre mise à jour, ne serait pas ce travail:

//cell[control/id="MyItemId_4"]/preceding-sibling::cell[control[@xsi:type='Label'] and not(control/name='')][1] 

Je suis un peu incertain au sujet du nœud nom: Vous voulez tester l'existence d'un texte dans le nœud de nom ou tout simplement l'existence du noeud de nom lui-même?

+0

cela ne fonctionne pas si je l'essaie avec http://www.bit-101.com/xpath/. tout simplement rien n'est sélectionné. La première partie, avant le précédent-frère travaille dans cet exemple. –

+0

J'ai besoin de tester le nom du noeud pour exister et avoir du texte. –

+0

Je viens de l'essayer dans le bit-101. Cela fonctionne pour moi et sélectionne la cellule avec le nom "MyOtherItemName" –

1

YourWebElement.FindElement (By.XPath ("previous-sibling :: * [1]"));

Ici 1 indique juste le frère au-dessus du nœud sélectionné et ensuite vous pouvez faire une récursion afin d'obtenir tous les frères et sœurs précédents de bas en haut.

Questions connexes