Вот некоторые вещи, чтобы отметить:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<all>
<houses>
<reg info='<root><h level="2" i="1"> something </h><root>'
other="test"
something
</reg>
</houses>
</all>
EOT
doc.errors # => [#<Nokogiri::XML::SyntaxError: Unescaped '<' not allowed in attributes values>, #<Nokogiri::XML::SyntaxError: attributes construct error>, #<Nokogiri::XML::SyntaxError: Couldn't find end of Start Tag reg line 3>, #<Nokogiri::XML::SyntaxError: Opening and ending tag mismatch: root line 3 and reg>, #<Nokogiri::XML::SyntaxError: Opening and ending tag mismatch: root line 3 and houses>, #<Nokogiri::XML::SyntaxError: Opening and ending tag mismatch: houses line 2 and all>, #<Nokogiri::XML::SyntaxError: Premature end of data in tag all line 1>]
doc.at('reg')['info'] # => ""
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <all>
# >> <houses>
# >> <reg info=""/><root><h level="2" i="1"> something </h><root>'
# >> other="test"
# >> something
# >> </root>
# >> </root>
# >> </houses>
# >> </all>
Синтаксический XML должен обычно использовать Nokogiri::XML
в XML является строгой спецификацией. Эта разметка неверна, и Nokogiri будет правильно отмечать ошибки, и, поскольку она искажена, она попытается исправить ее и продолжить синтаксический анализ.
Использование Nokogiri::HTML
ослабляет поводья и позволяет парсеру быть более снисходительным к тому, что он видит; HTML, как известно, плохо написана так Nokogiri старается быть более сговорчивыми:
doc = Nokogiri::HTML(<<EOT)
<all>
<houses>
<reg info='<root><h level="2" i="1"> something </h><root>'
other="test"
something
</reg>
</houses>
</all>
EOT
doc.errors # => [#<Nokogiri::XML::SyntaxError: Tag all invalid>, #<Nokogiri::XML::SyntaxError: Tag houses invalid>, #<Nokogiri::XML::SyntaxError: error parsing attribute name>, #<Nokogiri::XML::SyntaxError: Tag reg invalid>]
doc.at('reg')['info'] # => "<root><h level=\"2\" i=\"1\"> something </h><root>"
puts doc.to_xml
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html><body>
# >> <all>
# >> <houses>
# >> <reg info='<root><h level="2" i="1"> something </h><root>' other="test" something>
# >> </reg></houses>
# >> </all>
# >> </body></html>
Обратите внимание, как Nokogiri Сейчас:
- правильно HTML закодированы содержание
info
- корректно извлекает и декодирует контент для
info
.
- завернул XML в теги HTML
<html><body>
из-за разбора содержимого как HTML.
Для извлечения неподвижная XML требует шелушение назад пару слоев:
puts doc.at('all').to_xml
# >> <all>
# >> <houses>
# >> <reg info="<root><h level="2" i="1"> something </h><root>" other="test" something="">
# >> </reg></houses>
# >> </all>
Я не уверен, если поведение Nokogiri изменилось с тех пор вопрос был первоначально просил, но текущее поведение в v.1.6. 7.2 правильно обрабатывает декодирование, не используя CGI.
Обычно использование парсера HTML для анализа XML было бы неправильным, но в этом случае это помогает, поскольку разбор HTML более мягкий. См. Мой ответ на текущее поведение Нокогири. – 2016-06-03 20:14:22