2012-08-16 15 views
7

C'è un modo pulito per ottenere il contenuto dei nodi di testo con Nokogiri? In questo momento sto usandoContenuti nodo di testo Nokogiri

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

che sembra davvero prolisso per ottenere solo testo.

risposta

12

Volete solo il testo?

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

Forse non si desidera tutto lo spazio e il rumore. Se si desidera che solo i nodi di testo contenenti un carattere di parola,

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

Edit: Sembra che si voleva solo il contenuto del testo di un singolo nodo:

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

Accetto questa risposta, non perché è ciò che voglio, ma perché contiene ciò che voglio: il metodo testuale. Grazie! – cbmanica

+0

Solo un seguito: se vuoi trovare tutti i nodi di testo non vuoti e stai usando Rails, allora hai i metodi 'presente?' E 'vuoto?'. Ognuno di questi è equivalente: 'doc.search ('// text()'). Map (&: text) .delete_if &: blank?' Or 'doc.search ('// text()'). Map (&: testo) .keep_if &: presente? ' –

7

Basta guardare per i nodi di testo:

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 

quali uscite:

<!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> 

BTW, il tuo esempio di codice non funziona. at_xpath("//whatever").first è ridondante e fallirà. at_xpath troverà solo la prima occorrenza, restituendo un nodo. first è superfluo a quel punto, se funzionasse, ma non lo sarà perché il nodo non ha un metodo first.


ho <data><foo>bar</foo></bar>, come ottenere il testo "bar" senza fare doc.xpath_at("//data/foo").children.first.content?

Supponendo doc contiene il DOM analizzato:

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

ottenere la prima occorrenza:

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

Ottenere tutte le occorrenze e prendere la prima:

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

Uh, scusa, volevo dire children.first. soddisfare. Il tuo esempio non è esattamente quello che voglio, però - diciamo che ho bar, come ottengo il testo della "barra" senza fare doc.xpath_at ("// data/foo") .children.first. soddisfare? – cbmanica

+0

È * davvero * importante essere chiari su quello che vuoi. Non possiamo aiutarti diversamente. Guarda il contenuto aggiunto. –

+0

Pensavo di esserlo - pensavo che xpath_at rendesse abbastanza chiaro che conoscevo esattamente i nodi che stavo cercando e stavo semplicemente ottenendo i loro contenuti in modo stupido. – cbmanica

Problemi correlati