How to replace HTML nodes using Nokogiri
I have an HTML file, in which, all
<div class="replace-me">
</div>
must be replaced with
<video src='my_video.mov'></video>
The code is:
doc.css("div.replace-me").each do |div|
div.replace "<video src='my_video.mov'></video>"
end
It's simple, but, unfortunately, it does't work for me. Nokogiri crashes with the following error:
开发者_StackOverflow中文版undefined method `children' for nil:NilClass
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/whiny_nil.rb:52:in `method_missing'
/Library/Ruby/Gems/1.8/gems/nokogiri-1.4.2/lib/nokogiri/html/document_fragment.rb:16:in `initialize'
/Library/Ruby/Gems/1.8/gems/nokogiri-1.4.2/lib/nokogiri/xml/node.rb:424:in `new'
/Library/Ruby/Gems/1.8/gems/nokogiri-1.4.2/lib/nokogiri/xml/node.rb:424:in `fragment'
/Library/Ruby/Gems/1.8/gems/nokogiri-1.4.2/lib/nokogiri/xml/node.rb:776:in `coerce'
/Library/Ruby/Gems/1.8/gems/nokogiri-1.4.2/lib/nokogiri/xml/node.rb:331:in `replace'
Replacing with a div
works:
doc.css("div.replace-me").each do |div|
div.replace "<div>Test</div>"
end
Is this a Nokogiri bug, or did I do something wrong?
The same issue occurs with add_child
, inner_html
and other setters for this purpose.
I will quote my comment from your previous question:
This happens because of HTML strictness (HTML has a predefined set of elements). Replace Nokogiri::HTML( self.content ) with Nokogiri::XML( self.content ) and do not forget to add a DOCTYPE declaration manually later.
If you look into the log, the part you chose with Nokogiri turns nil.
Try it this way:
doc.css(".replace-me").each do |div|
div.replace "<video src='my_video.mov'></video>"
end
Or you may need to specify which element you want to replace.
I can't duplicate the problem. Granted, the question is old, but this works:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<div class="replace-me">
</div>
EOT
It could have been a Ruby 1.8 issue, an issue with that version of Nokogiri, or something was wrong in your libXML... it's hard to say given the information in the question.
doc.at('div.replace-me').replace("<video src='my_video.mov'></video>")
doc.to_html
# => "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n" +
# "<html><body>\n" +
# "<video src=\"my_video.mov\"></video>\n" +
# "</body></html>\n"
精彩评论