【问题标题】:How to parse XML with nokogiri without losing HTML entities?如何在不丢失 HTML 实体的情况下使用 nokogiri 解析 XML?
【发布时间】:2014-10-07 17:33:14
【问题描述】:

如果您查看后面部分的输出,ruby 正在删除所有 html 实体。如何在不丢失 HTML 实体的情况下使用 nokogiri 解析 XML?

--- BEFORE ---

<blog:entryFull>
&lt;p&gt;&lt;iframe src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>

--- AFTER --- 

<blog:entryFull>
piframe src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946amp;show_artwork=true" width="100%" height="166" frameborder="no" scrolling="no"/iframe/p</blog:entryFull>
  </blog:example>

代码如下:

f = File.open(item)

contents = ""
f.each {|line|
  contents << line
}

puts "--- BEFORE ---"
puts contents
puts "--- AFTER ---"

doc = Nokogiri::XML::DocumentFragment.parse(contents) 
puts doc
f.close 

【问题讨论】:

  • puts doc 将尝试对文档进行字符串化,这不是您想要的。您必须告诉 Nokogiri 您希望如何查看文档/节点,如 HTML、XHTML 或 XML。更多信息在the Nokogiri::XML::Node documentation
  • 我有一个相关的问题:puts Nokogiri::XML::DocumentFragment.parse( "&lt;pre&gt;&amp;lt;div&gt;foo&amp;lt;/div&gt;&lt;/pre&gt;" ) 给了&lt;pre&gt;&amp;lt;div&amp;gt;foo&amp;lt;/div&amp;gt;&lt;/pre&gt;puts Nokogiri::XML::DocumentFragment.parse( "&amp;nbsp;&lt;pre&gt;&amp;lt;div&gt;foo&amp;lt;/div&gt;&lt;/pre&gt;" ) 给了"&lt;pre&gt;div&amp;gt;foo/div&amp;gt;&lt;/pre&gt;"

标签: html ruby nokogiri


【解决方案1】:

您的测试文件可能包含一些无效的 HTML 实体。

nokogiri.rb:

require 'nokogiri'

puts "--- INVALID ---"
invalid_xml = <<-XML
<blog:entryFull>invalid M&Ms</blog:entryFull><!-- invalid M and M's -->
<blog:entryFull>
&lt;p&gt;&lt;iframe src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>
XML

doc = Nokogiri::XML::DocumentFragment.parse(invalid_xml)
puts doc

puts "--- VALID ---"
valid_xml = <<-XML
<blog:entryFull>valid M&amp;Ms</blog:entryFull><!-- valid M and M's -->
<blog:entryFull>
&lt;p&gt;&lt;iframe src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>
XML

doc = Nokogiri::XML::DocumentFragment.parse(valid_xml)
puts doc

结果:

$ ruby nokogiri.rb
--- INVALID ---
<blog:entryFull>invalid M</blog:entryFull><!-- invalid M and M's -->
<blog:entryFull>
piframe src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946amp;show_artwork=true" width="100%" height="166" frameborder="no" scrolling="no"/iframe/p</blog:entryFull>
--- VALID ---
<blog:entryFull>valid M&amp;Ms</blog:entryFull><!-- valid M and M's -->
<blog:entryFull>
&lt;p&gt;&lt;iframe src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>

所以,

  1. 修复输入 XML
  2. 使用 STRICT ParseOptions

严格解析示例:

invalid_xml = <<-XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <blog:entryFull>invalid M&Ms</blog:entryFull>
  <blog:entryFull>
  &lt;p&gt;&lt;iframe src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>
</root>
XML

begin
  doc = Nokogiri::XML(invalid_xml) do |configure|
    configure.strict # strict parsing
  end
  puts doc
rescue => e
  puts 'INVALID XML'
end

【讨论】:

    【解决方案2】:

    Qambar,我无法重现您的问题。但是,鉴于这些文件/输入,我能够产生您想要的输出:

    test.xml

    <blog:entryFull> &lt;p&gt;&lt;iframe src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true%22" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>
    

    nokogiri.rb

    require 'nokogiri'
    
    f = File.open("./test.html")
    
    contents = ""
    f.each {|line|
      contents << line
    }
    
    puts "--- BEFORE ---"
    puts contents
    puts "--- AFTER ---"
    
    doc = Nokogiri::XML::DocumentFragment.parse(contents) 
    puts doc.inner_html
    f.close
    

    控制台

    Development/Code » ruby nokogiri.rb
    --- BEFORE ---
    <blog:entryFull> &lt;p&gt;&lt;iframe src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true%22" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>
    --- AFTER ---
    <blog:entryFull> &lt;p&gt;&lt;iframe src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F39858946&amp;amp;show_artwork=true%22" width="100%" height="166" frameborder="no" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt;</blog:entryFull>
    

    【讨论】:

    • test.html 文件不正确。它应该有一个包含转义 HTML 的 xml 标记,就像我在问题 ' <p><iframe src="w.soundcloud.com/player/…" width="100%" height="166" frameborder=" no" scrolling="no"></iframe></p> '
    • 我有超过 10k 个包含许多 XML 标签的文件,其中一个是包含完整 HTML 的文件。
    • 我修改了测试文件以包含您指定的内容,并且在之前/之后仍然返回相同的内容。不知道这里发生了什么:/
    • 我正在使用 ruby​​ 1.9.3p545(2014-02-24 修订版 45159)[x86_64-darwin13.1.0],您使用的是哪个版本?
    【解决方案3】:

    我所做的解决方法是通过正则表达式获取 xml 标记,然后使用 html 实体转换 html 实体。然后用 nokogiri html 解析器解析它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 2013-01-22
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多