Come selezionare il seguente tag di pari livello / xml utilizzando xpath


102

Ho un file HTML (da Newegg) e il loro HTML è organizzato come di seguito. Tutti i dati nella tabella delle specifiche sono " desc " mentre i titoli di ogni sezione sono in " nome " . Di seguito sono riportati due esempi di dati dalle pagine di 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>

Alla fine mi piacerebbe avere una classe per una CPU (che è già impostata) che consiste in un tipo di marca, serie, core e socket per memorizzare ciascuno dei dati. Questo è l'unico modo in cui riesco a pensare di fare questo:

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

E facendo questo per il resto dei valori. Come potrei realizzare il prossimo fratello e c'è un modo più semplice per farlo?

Risposte:


205

Come potrei realizzare il prossimo fratello e c'è un modo più semplice per farlo?

Puoi usare :

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

ma preferisco usare direttamente :

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

Ciò presuppone che :

  1. Il nodo di contesto, rispetto al quale viene valutata l'espressione XPath, è il genitore di tutti gli trelementi, non mostrato nella domanda.

  2. Ogni trelemento ne ha solo uno tdcon classattributo valorizzato 'name'e solo uno tdcon classattributo valorizzato 'desc'.


Nota che devi stare attento nell'usare la classe. Quando gli elementi della tua classe "nome" hanno un'altra classe allo stesso tempo, td[@class='name']si romperà. Vedi questa domanda per i dettagli.
gm2008

@ gm2008, sì, nel caso ci sia più di una classe nel valore dell'attributo @class, il predicato da utilizzare è: contains(concat(' ', @class, ' '), ' name ') . Ma in questa domanda gli attributi @class hanno solo valori singoli.
Dimitre Novatchev

Rispetto a un elemento:./following-sibling::td
John Gietzen

2
@JohnGietzen, Re: "Relative to an element" - Vuoi dire se il nodo di contesto è l'elemento che ci interessa. In questo caso puoi omettere ./. Inoltre, se si desidera selezionare il fratello immediatamente successivo, utilizzare:, following-sibling::td[1]altrimenti, se sono presenti più fratelli successivi, verranno selezionati tutti.
Dimitre Novatchev

12

Prova l' following-siblingasse ( following-sibling::td).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.