Как выбрать следующий тег sibling / xml с помощью xpath

103

У меня есть файл HTML (от Newegg), и их HTML организован, как показано ниже. Все данные в их таблице спецификаций представлены как « desc », а заголовки каждого раздела - « name». 'Ниже приведены два примера данных со страниц 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>

В конце концов, я хотел бы иметь класс для ЦП (который уже настроен), который состоит из типа Brand, Series, Cores и Socket для хранения каждого из данных. Это единственный способ, который я могу придумать для этого:

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

И проделаем то же самое с остальными ценностями. Как бы я мог сделать это и есть ли более простой способ сделать это?

Кори Фарвелл
источник

Ответы:

205

Как бы я мог сделать это и есть ли более простой способ сделать это?

Вы можете использовать :

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

но я бы предпочел использовать напрямую :

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

Это предполагает, что :

  1. Узел контекста, по которому вычисляется выражение XPath, является родительским для всех trэлементов - не показан в вашем вопросе.

  2. У каждого trэлемента есть только один tdс classоцененным атрибутом 'name'и только один tdс classоцененным атрибутом 'desc'.

Димитр Новачев
источник
Обратите внимание, что вы должны быть осторожны при использовании class. Когда ваши элементы класса name имеют одновременно любой другой класс, td[@class='name']он сломается. См. Этот вопрос для подробностей.
GM2008
@ gm2008, Да, в случае , если есть более чем один класс в значении атрибута @class, предикат для использования является: contains(concat(' ', @class, ' '), ' name ') . Но в этом вопросе атрибуты @class имеют только одиночные значения.
Dimitre Novatchev
Относительно элемента:./following-sibling::td
Джон Гитцен
2
@JohnGietzen, Re: «Относительно элемента» - вы имеете в виду, если контекстный узел является тем элементом, который нас интересует. В этом случае вы можете пропустить ./. Кроме того, если вы хотите выбрать ближайшего следующего брата, используйте:, в following-sibling::td[1]противном случае, если следующих братьев и сестер несколько, будут выбраны все.
Dimitre Novatchev
12

Попробуйте following-siblingось ( following-sibling::td).

Филипп
источник