Cómo seleccionar la siguiente etiqueta de hermano / xml usando xpath

102

Tengo un archivo HTML (de Newegg) y su HTML está organizado como se muestra a continuación. Todos los datos en su tabla de especificaciones son " desc ", mientras que los títulos de cada sección están en " nombre " . A continuación se muestran dos ejemplos de datos de las páginas de 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>

Al final, me gustaría tener una clase para una CPU (que ya está configurada) que consta de un tipo de Marca, Serie, Núcleos y Socket para almacenar cada uno de los datos. Esta es la única forma en que puedo pensar para hacer esto:

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

Y haciendo esto para el resto de valores. ¿Cómo podría lograr el siguiente hermano y hay una forma más fácil de hacerlo?

Corey Farwell
fuente

Respuestas:

205

¿Cómo podría lograr el siguiente hermano y hay una forma más fácil de hacerlo?

Puede utilizar :

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

pero prefiero usar directamente :

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

Esto supone que :

  1. El nodo de contexto, contra el cual se evalúa la expresión XPath, es el padre de todos los trelementos, no se muestra en su pregunta.

  2. Cada trelemento tiene solo uno tdcon classatributo valorado 'name'y solo uno tdcon classatributo valorado 'desc'.

Dimitre Novatchev
fuente
Tenga en cuenta que debe tener cuidado al usar class. Cuando los elementos de su clase 'nombre' tengan cualquier otra clase al mismo tiempo, td[@class='name']se romperán. Consulte esta pregunta para obtener más detalles.
GM2008
@ gm2008, Sí, en caso de que haya más de una clase en el valor del atributo @class, el predicado de uso es: contains(concat(' ', @class, ' '), ' name ') . Pero en esta pregunta, los atributos @class tienen solo valores únicos.
Dimitre Novatchev
Relativo a un elemento:./following-sibling::td
John Gietzen
2
@JohnGietzen, Re: "Relativo a un elemento" - Quieres decir si el nodo de contexto es el elemento que nos interesa. En este caso puedes omitir ./. Además, si desea seleccionar el hermano siguiente inmediato, utilice:, de lo following-sibling::td[1]contrario, si hay más de un hermano siguiente, se seleccionarán todos.
Dimitre Novatchev
12

Pruebe el following-siblingeje ( following-sibling::td).

Philipp
fuente