Сохранить структуру страницы HTML, удалив все текстовые узлы - PullRequest
1 голос
/ 25 декабря 2010

Я хочу удалить весь текст со страницы html, который я загружаю с помощью nokogiri.Например, если страница имеет следующее:

<body><script>var x = 10;</script><div>Hello</div><div><h1>Hi</h1></div></body>

Я хочу обработать ее с помощью Nokogiri и вернуть html, как показано ниже, после удаления текста следующим образом:

<body><script>var x = 10;</script><div></div><div><h1></h1></div></body>

(Тоудалить текущий текст h1, текст между элементами div, текст в элементах p и т. д., но сохранить теги. Кроме того, не удаляйте текст в тегах сценария.)

1 Ответ

3 голосов
/ 27 декабря 2010
require 'nokogiri'
html = "<body><script>var x = 10;</script><div>Hello</div><div><h1>Hi</h1></div></body>"
hdoc = Nokogiri::HTML(html)
hdoc.xpath( '//*[text()]' ).each do |el|
  el.content='' unless el.name=="script"
end

puts hdoc
#=> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
#=> <html><body>
#=> <script>var x = 10;</script><div></div>
#=> <div><h1></h1></div>
#=> </body></html>

Предупреждение : Поскольку вы не указали, как обращаться с делом, подобным <div>foo<h1>bar</h1></div>, вышеприведенное может или не может сделать то, что вы ожидаете.Кроме того, следующее может соответствовать вашим потребностям:

hdoc.xpath( '//text()' ).each do |el|
  el.remove unless el.parent.name=="script"
end

Обновление

Вот более элегантное решение, использующее один xpath для выбора всех текстовых узлов, не являющихся частью элемента <script>.Я добавил больше текстовых узлов, чтобы показать, как он их обрабатывает.

require 'nokogiri'
hdoc = Nokogiri::HTML <<ENDHTML
  <body>
  <script>var x = 10;</script>
  <div>Hello</div>
  <div>foo<h1>Hi</h1>bar</div>
  </body>
ENDHTML
hdoc.xpath( '//text()[not(parent::script)]' ).each{ |text| text.remove }
puts hdoc
#=> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
#=> <html><body>
#=> <script>var x = 10;</script><div></div>
#=> <div><h1></h1></div>
#=> </body></html>

Для Ruby 1.9 мясо проще:

hdoc.xpath( '//text()[not(parent::script)]' ).each(&:remove)
...