Jak wybrać następujący tag sibling / xml za pomocą xpath

102

Mam plik HTML (z Newegg), a ich kod HTML jest zorganizowany jak poniżej. Wszystkie dane w tabeli danych technicznych jest ich „ desc ”, podczas gdy tytuły są w każdej sekcji " nazwy. Poniżej znajdują się dwa przykłady danych ze stron 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>

Na koniec chciałbym mieć klasę dla procesora (który jest już skonfigurowany), która składa się z marki, serii, rdzeni i typu gniazda do przechowywania wszystkich danych. To jedyny sposób, jaki przychodzi mi do głowy, aby to zrobić:

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

I robię to dla pozostałych wartości. W jaki sposób mógłbym dokonać powiązania i czy jest na to łatwiejszy sposób?

Corey Farwell
źródło

Odpowiedzi:

205

W jaki sposób mógłbym dokonać powiązania i czy jest na to łatwiejszy sposób?

Możesz użyć :

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

ale wolałbym użyć bezpośrednio :

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

Zakłada się, że :

  1. Węzeł kontekstu, względem którego oceniane jest wyrażenie XPath, jest rodzicem wszystkich trelementów - nie pokazany w pytaniu.

  2. Każdy trelement ma tylko jeden tdz classwartością atrybutu 'name'i tylko jeden tdz classwartością atrybutu 'desc'.

Dimitre Novatchev
źródło
Zauważ, że musisz uważać przy używaniu class. Kiedy elementy twojej klasy „name” będą miały jednocześnie jakąkolwiek inną klasę, td[@class='name']ulegną uszkodzeniu. Zobacz to pytanie, aby uzyskać szczegółowe informacje.
gm2008
@ gm2008 Tak, w przypadku, gdy istnieje więcej niż jedna klasa w wartości atrybutu @class, orzecznikiem do wykorzystania wynosi: contains(concat(' ', @class, ' '), ' name ') . Ale w tym pytaniu atrybuty @class mają tylko pojedyncze wartości.
Dimitre Novatchev
W odniesieniu do elementu:./following-sibling::td
John Gietzen
2
@JohnGietzen, Re: "Względem elementu" - Masz na myśli, jeśli węzeł kontekstu jest elementem, który nas interesuje. W tym przypadku możesz pominąć ./. Ponadto, jeśli chcesz wybrać najbliższe rodzeństwo, użyj:, w following-sibling::td[1]przeciwnym razie, jeśli jest więcej niż jedno następujące rodzeństwo, wszystkie zostaną wybrane.
Dimitre Novatchev
12

Wypróbuj following-siblingoś ( following-sibling::td).

Philipp
źródło