Comment sélectionner la balise frère / xml suivante à l'aide de xpath

102

J'ai un fichier HTML (de Newegg) et leur HTML est organisé comme ci-dessous. Toutes les données de leur tableau de spécifications sont « desc » tandis que les titres de chaque section sont dans « nom » . Voici deux exemples de données provenant de pages Newegg.

<tr>
    <td class="name">Brand</td>
    <td class="desc">Intel</td>
</tr>
<tr>
    <td class="name">Series</td>
    <td class="desc">Core i5</td>
</tr>
<tr>
    <td class="name">Cores</td>
    <td class="desc">4</td>
</tr>
<tr>
    <td class="name">Socket</td>
    <td class="desc">LGA 1156</td>

<tr>
    <td class="name">Brand</td>
    <td class="desc">AMD</td>
</tr>
<tr>
    <td class="name">Series</td>
    <td class="desc">Phenom II X4</td>
</tr>
<tr>
    <td class="name">Cores</td>
    <td class="desc">4</td>
</tr>
<tr>
    <td class="name">Socket</td>
    <td class="desc">Socket AM3</td>
</tr>

En fin de compte, j'aimerais avoir une classe pour un processeur (qui est déjà configuré) qui se compose d'un type de marque, série, cœurs et socket pour stocker chacune des données. C'est le seul moyen auquel je peux penser pour y parvenir:

if(parsedDocument.xpath(tr/td[@class="name"])=='Brand'):
    CPU.brand = parsedDocument.xpath(tr/td[@class="name"]/nextsibling?).text

Et faire cela pour le reste des valeurs. Comment pourrais-je accomplir le nextsibling et existe-t-il un moyen plus simple de le faire?

Corey Farwell
la source

Réponses:

205

Comment pourrais-je accomplir le nextsibling et y a-t-il un moyen plus simple de le faire?

Vous pouvez utiliser :

tr/td[@class='name']/following-sibling::td

mais je préfère utiliser directement :

tr[td[@class='name'] ='Brand']/td[@class='desc']

Cela suppose que :

  1. Le nœud de contexte, par rapport auquel l'expression XPath est évaluée, est le parent de tous les tréléments - non affiché dans votre question.

  2. Chaque trélément n'en a qu'un tdavec un classattribut valorisé 'name'et un seul tdavec un classattribut valorisé 'desc'.

Dimitre Novatchev
la source
Notez que vous devez faire attention à l'utilisation de la classe. Lorsque vos éléments de classe «nom» ont une autre classe en même temps, td[@class='name']se cassera. Voir cette question pour plus de détails.
gm2008
@ gm2008, Oui, dans le cas où il y a plus d'une classe de la valeur de l'attribut @class, le prédicat à utiliser est: contains(concat(' ', @class, ' '), ' name ') . Mais dans cette question, les attributs @class n'ont que des valeurs uniques.
Dimitre Novatchev
Par rapport à un élément:./following-sibling::td
John Gietzen
2
@JohnGietzen, Re: "Par rapport à un élément" - Vous voulez dire Si le nœud de contexte est l'élément qui nous intéresse. Dans ce cas, vous pouvez l'omettre ./. De plus, si vous souhaitez sélectionner le frère suivant immédiat, utilisez following-sibling::td[1]:, sinon, s'il y a plus d'un frère suivant, tous seront sélectionnés.
Dimitre Novatchev
12

Essayez l' following-siblingaxe ( following-sibling::td).

Philipp
la source