2012-08-16 14 views
7

¿Hay alguna forma clara de obtener los contenidos de los nodos de texto con Nokogiri? En este momento estoy usandoContenido del nodo de texto Nokogiri

some_node.at_xpath("//whatever").first.content 

que parece muy detallado para obtener solo texto.

Respuesta

12

Quiere solo el texto?

doc.search('//text()').map(&:text) 

Quizás no desee todos los espacios en blanco y el ruido. Si desea que sólo los nodos de texto que contienen un carácter de palabra,

doc.search('//text()').map(&:text).delete_if{|x| x !~ /\w/} 

Editar: Al parecer, sólo quería el contenido de texto de un solo nodo:

some_node.at_xpath("//whatever").text 
+0

Estoy aceptando esta respuesta, no porque sea lo que quiero, sino porque contiene lo que quiero, el método de texto. ¡Gracias! – cbmanica

+0

Solo un seguimiento: si quiere encontrar todos los nodos de texto no en blanco y está utilizando Rails, entonces tiene los métodos 'present?' Y 'blank?'. Cada uno de estos son equivalentes: 'doc.search ('// text()') map (&: text) .delete_if &: blank?' O 'doc.search ('// text()') map (&: texto) .keep_if &: presente? ' –

7

Sólo tienes que buscar los nodos de texto:

require 'nokogiri' 

doc = Nokogiri::HTML(<<EOT) 
<html> 
<body> 
<p>This is a text node </p> 
<p> This is another text node</p> 
</body> 
</html> 
EOT 

doc.search('//text()').each do |t| 
    t.replace(t.content.strip) 
end 

puts doc.to_html 

que da salida:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html><body> 
<p>This is a text node</p> 
<p>This is another text node</p> 
</body></html> 

Por cierto, el ejemplo de código no funciona. at_xpath("//whatever").first es redundante y fallará. at_xpath encontrará solo la primera aparición, devolviendo un Nodo. first es superfluo en ese punto, si funcionara, pero no lo hará porque Node no tiene un método first.


tengo <data><foo>bar</foo></bar>, la forma en que me dan en el texto "barra" sin hacer doc.xpath_at("//data/foo").children.first.content?

Suponiendo doc contiene el DOM analizado:

doc.to_xml # => "<?xml version=\"1.0\"?>\n<data>\n <foo>bar</foo>\n</data>\n" 

conseguir la primera ocurrencia:

doc.at('foo').text  # => "bar" 
doc.at('//foo').text  # => "bar" 
doc.at('/data/foo').text # => "bar" 

conseguir todas las ocurrencias y tomar la primera de ellas:

doc.search('foo').first.text  # => "bar" 
doc.search('//foo').first.text # => "bar" 
doc.search('data foo').first.text # => "bar" 
+0

Uh, perdón, quise decir children.first. contenido. Sin embargo, su ejemplo no es exactamente lo que quiero, digamos que tengo barra, cómo obtengo el texto de la "barra" sin hacer doc.xpath_at ("// data/foo") .children.first. ¿contenido? – cbmanica

+0

Es * realmente * importante tener en claro lo que quiere. No podemos ayudarte de otra manera. Ver el contenido agregado –

+0

Pensé que era ... Creía que xpath_at dejaba muy claro que sabía exactamente los nodos que estaba buscando y que estaba obteniendo sus contenidos de una manera estúpida. – cbmanica

Cuestiones relacionadas