¿Cómo puedo hacer que todos los elementos sigan una vez, como:

<div id="exemple">
  <h2 class="target">foo</h2>
  <p>bla bla</p>
  <ul>
    <li>bar1</li>
    <li>bar2</li>
    <li>bar3</li>
  </ul>
  <h4>baz</h4> 
  <ul>
     <li>lot</li>
  </ul>
  <div>of</div>
  <p>possible</p>
  <p>tags</p>
  <a href="#">after</a>
</div>

Necesito detectar <h2 class="target"> y pasar todas las etiquetas a la siguiente <h4> e ignorar <h4> Y todas las etiquetas siguientes (si <h4> no existe, tiene que obtener todas las etiquetas al final de parent [aquí: end of <div>])

El contenido es dinámico e impredecible La única regla es: sabemos que hay un objetivo y hay un (o fin de elemento). Necesito obtener todas las etiquetas entre ambos y excluir todas las demás.

Con este ejemplo, necesito obtener el siguiente HTML:

<h2 class="target">foo</h2>
<p>bla bla</p>
<ul>
  <li>bar1</li>
  <li>bar2</li>
  <li>bar3</li>
</ul>

Para que pueda obtener: target = page.at('#exemple .target') Sé el método next_sibling, pero ¿cómo puedo probar el tipo de etiqueta del nodo actual?

Pienso en algo así para recorrer el árbol de nodos:

html = ''
while not target.is_a? 'h4'
  html << target.inner_html
  target = target.next_sibling

¿Cómo puedo hacer esto?

1
Matrix 12 jul. 2017 a las 13:51

2 respuestas

La mejor respuesta

Puede restar los que no desea de su conjunto de nodos:

h2 = page.at('h2')
(h2.search('~ *') - h2.search('~ h4','~ h4 ~ *')).each do |el|
    # el is not a h4 and does not follow a h4
end

Tal vez tenga más sentido usar xpath, pero puedo hacerlo sin buscar en Google.

Tu idea de iterar al próximo hermano también puede funcionar:

el = page.at('h2 ~ *')
while el && el.name != 'h4'
    # do something with el
    el = el.at('+ *')
end
2
pguardiario 12 jul. 2017 a las 23:59

Parece que desea devolver el elemento h2 y sus siguientes hermanos. No tengo claro si desea conservar o descartar el h4; si desea mantenerlo, el XPath sería:

//h2[@class="target"] | //h2[@class="target"]/following-sibling::*

Si necesita excluir la h4:

//h2[@class="target"] | //h2[@class="target"]/following-sibling::*[not(self::h4)]

Editar : si necesita excluir una h4 y cualquier cosa más allá:

//h2[@class="target"] | //h2[@class="target"]/following-sibling::*[not(self::h4) | not(preceding-sibling::h4)]
1
Mark Thomas 13 jul. 2017 a las 13:50