Como selecionar a seguinte tag irmão / xml usando xpath

102

Eu tenho um arquivo HTML (da Newegg) e seu HTML está organizado como abaixo. Todos os dados em sua tabela de especificações são ' desc ', enquanto os títulos de cada seção estão em ' name. 'Abaixo estão dois exemplos de dados das páginas 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>

No final, gostaria de ter uma classe para uma CPU (que já está configurada) que consistisse em um tipo de Marca, Série, Núcleos e Soquete para armazenar cada um dos dados. Esta é a única maneira que consigo pensar para fazer isso:

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

E fazendo isso para o resto dos valores. Como eu realizaria o próximo e há uma maneira mais fácil de fazer isso?

Corey Farwell
fonte

Respostas:

205

Como eu realizaria o próximo e há uma maneira mais fácil de fazer isso?

Você pode usar :

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

mas prefiro usar diretamente :

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

Isso pressupõe que :

  1. O nó de contexto, em relação ao qual a expressão XPath é avaliada, é o pai de todos os trelementos - não é mostrado em sua pergunta.

  2. Cada trelemento tem apenas um tdcom classvalor de atributo 'name'e apenas um tdcom classvalor de atributo 'desc'.

Dimitre Novatchev
fonte
Observe que você deve ter cuidado ao usar a classe. Quando os elementos da sua classe 'name' tiverem qualquer outra classe ao mesmo tempo, td[@class='name']haverá falha. Veja esta pergunta para detalhes.
gm2008
@ gm2008, Sim, no caso de haver mais de uma classe no valor do atributo @class, o predicado de uso é: contains(concat(' ', @class, ' '), ' name ') . Mas, nesta questão, os atributos @class têm apenas valores únicos.
Dimitre Novatchev
Em relação a um elemento:./following-sibling::td
John Gietzen
2
@JohnGietzen, Re: "Relativo a um elemento" - Você quer dizer se o nó de contexto é o elemento no qual estamos interessados. Neste caso, você pode omitir ./. Além disso, se você quiser selecionar o irmão seguinte imediato, use:, following-sibling::td[1]caso contrário, se houver mais de um irmão seguinte, todos serão selecionados.
Dimitre Novatchev
12

Experimente o following-siblingeixo ( following-sibling::td).

Philipp
fonte