Есть несколько все неправильно. Во-первых, вы просите Nokogiri разобрать что-то, что выглядит вроде как HTML, но нет. Nokogiri достаточно умен, чтобы знать разницу:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<head>
<title><* page.title *></title>
</head>
<body>
<h1><* recipe.name *></h1>
<* food name *>
<* food.name *>
<* more values *>
<p><* value *></p>
<* ENDEACH *>
<* ENDEACH *>
</body>
</html>
EOT
puts doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html>
# >> <head>
# >> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
# >> <title></title>
# >> </head>
# >> <body>
# >> <h1></h1>
# >>
# >>
# >>
# >> <p></p>
# >>
# >>
# >> </body>
# >> </html>
Обратите внимание на куски на выходе? Вот что Nokogiri должен сказать о HTML:
doc.errors
# => [#<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>,
# #<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>,
# #<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>,
# #<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>,
# #<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>,
# #<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>,
# #<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>,
# #<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>]
Таким образом, вы не можете ожидать, Nokogiri для обработки шаблона, если этот шаблон не является действительной HTML.
После зачистки недопустимых тегов и упрощения HTML, вот следующий вопрос:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<h1>foo</h1>
</body>
</html>
EOT
h1 = doc.search('h1')
h1.class # => Nokogiri::XML::NodeSet
h1.respond_to?(:content=) # => false
Обратите внимание, что при использовании search
возвращает набор узлов, который не понимает content=
. search
, а также css
и xpath
возвращает узел NodeSet. Вы могли бы перебирать возвращаемый NodeSet и работать с отдельными узлами, но, как и пытаться установить один и тот же контент в связку узлов в NodeSet, это не логично, поэтому Nokogiri не реализует его.
Вместо:
h1 = doc.at('h1')
h1.class # => Nokogiri::XML::Element
h1.respond_to?(:content=) # => true
h1.content = 'hello'
at
, at_css
и at_xpath
эквивалентны использованию search('some selector').first
, поэтому они возвращаются только узел.
Глядя на DOM сейчас:
puts doc.to_html
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html>
# >> <body>
# >> <h1>hello</h1>
# >> </body>
# >> </html>
Nokogiri * возможно * вернуть NodeSet на запрос, в зависимости от используемого метода. 'search',' css' и 'xpath' возвращают NodeSet. 'at',' at_css' и 'at_xpath' возвращают узел. –