Как удалить узел изображения с заданным атрибутом src?

Мне нужно удалить изображение с помощью give src

img_src = "http://domain/img.jpg"
@doc.xpath("//img[@src='#{img_src}']")[0].remove

Не работает. Пробовал еще вот так

@doc.xpath("//img[@src='#{img_src}']") {|x| x.remove}

Тоже не работает. Любые идеи о том, что я делаю неправильно?

Я понял. Это была глупая ошибка. Все ваши решения были правильными.


person Arty    schedule 05.12.2010    source источник
comment
Что здесь означает не работает? Вы получаете ошибку? Нет ошибки, но документ не изменился? Вы проверили, можете ли вы найти правильный элемент, прежде чем пытаться его удалить?   -  person Phrogz    schedule 05.12.2010
comment
Было бы полезно увидеть более полный пример того, как вы анализируете файл.   -  person the Tin Man    schedule 05.12.2010
comment
@Greg, @Phrogz, я обновил тему полным примером и некоторыми подробностями. Спасибо за вашу помощь.   -  person Arty    schedule 07.12.2010
comment
Ладно, я понял. Глупая ошибка, как я и думал.   -  person Arty    schedule 07.12.2010
comment
НП. Рад, что ты смог разобраться.   -  person the Tin Man    schedule 07.12.2010


Ответы (2)


Nokogiri имеет два разных режима парсера: один для XML и один для HTML. XML строг, а HTML очень расслаблен, потому что HTML не всегда хорошо себя ведет.

doc = Nokogiri::XML('<xml><a>1</a></xml>')

or

doc = Nokogiri::HTML('<html><body>foo</body></html>')

Вот как я обычно анализирую файл HTML:

require 'nokogiri'
require 'open-uri'

doc = Nokogiri::HTML(open('http://www.example.com'))
print doc.to_html
# >> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
[...]

Чтобы удалить тег, вам нужно сначала найти его, а затем remove. После анализа документа HTML или XML у нас будет документ Nokogiri::HTML или Nokogiri::XML соответственно, и в этот момент то, что мы называли «тегами», теперь называется «узлами». Nokogiri может найти наборы узлов, то есть узлы, соответствующие запросу, или отдельный узел, который будет первым совпадением при поиске.

Это будет искать первый узел, соответствующий src="a.png", используя метод доступа CSS, который обычно проще/чище, чем XPath. Nokogiri очень хорошо понимает как XPath, так и CSS, и на веб-сайте упоминаются некоторые преимущества CSS:

require 'nokogiri'
require 'open-uri'

html = '<html><body><img src="a.png" /><img src="b.png" /></body></html>'

doc = Nokogiri::HTML(html)
doc.at('img[@src="a.png"]').remove
print doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html><body><img src="b.png"></body></html>

Чтобы найти все узлы, соответствующие аксессору, вы можете заменить doc.at('img[@src="a.png"]').remove на:

doc.search('img[@src="a.png"]').each { |n| n.remove }

Также стоит прочитать руководства.

person the Tin Man    schedule 05.12.2010

Работает на меня:

require 'nokogiri'
xml = <<ENDXML
  <root>
    <img src="http://foo/foo.jpg" />
    <img src="http://bar/bar.jpg" />
  </root>
ENDXML

doc = Nokogiri::XML xml
img_src = "http://foo/foo.jpg"

doc.at_xpath("//img[@src='#{img_src}']").remove

puts doc
#=> <?xml version="1.0"?>
#=> <root>
#=> 
#=> <img src="http://bar/bar.jpg"/>
#=> </root>
person Phrogz    schedule 05.12.2010
comment
У меня не работает :( Есть ли разница, если я открою документ как HTML? (на самом деле это HTML-страница) - person Arty; 05.12.2010
comment
@Arty Какие версии Ruby и Nokogiri? - person Phrogz; 05.12.2010
comment
Что значит открыть документ? Nokogiri может попытаться выяснить, является ли документ HTML или XML, но это не слишком умный способ принятия решения. Лучше сообщить ему тип документа, используя Nokogiri::XML() или Nokogiri::HTML() для анализа содержимого. - person the Tin Man; 05.12.2010
comment
@Arty Некоторые вещи в Nokogiri меняются в зависимости от того, используете ли вы XML или HTML, но для меня узел также удаляется с помощью HTML. У меня Ruby 1.9.2 и Nokogiri 1.4.4 на OS X. - person Phrogz; 05.12.2010
comment
@Phrogz Я использую ruby ​​​​1.8.7 и nokogiri (1.4.4, 1.4.2). - person Arty; 07.12.2010
comment
@ Грег, спасибо за подробное объяснение, я пытался повторить то же самое, но узел все еще не удален. Я могу найти его и изменить любой атрибут, который захочу, но когда я использую для него .remove - это просто не работает. Это заставляет меня думать, что, вероятно, это какая-то глупая ошибка, если вы все дали мне одни и те же примеры, они должны были работать. - person Arty; 07.12.2010
comment
@Greg, и да, я открываю документ в режиме HTML - person Arty; 07.12.2010
comment
@Arty Как видно из этой пасты, приведенное выше отлично работает для меня с использованием 1.8.7, 1.4.4 и HTML режим. - person Phrogz; 07.12.2010