背景:我正在使用Ruby的Nokogiri gem来解析一个XML文件。我的问题是,当一个字符串包含>
时(这是>
的HTML编码),SAX解析器返回一个不完整的结果。例如:
<element>PART1PART2</element> #=> returns "PART1PART2"
<element>PART3>PART4</element> #=> returns "PART3"
我的解析器长这样:
require 'nokogiri'
class MySample < Nokogiri::XML::SAX::Document
def characters(string)
puts string
end
end
# Create a new parser
parser = Nokogiri::XML::SAX::Parser.new(MySample.new)
# Feed the parser some XML
parser.parse_file(ARGV[0])
研究:如果一个字符串包含>
,那么Nokogiri会认为这是字符串的结尾。但是,在字符串中有一个>
被认为是格式不良好的XML。然而,我的XML格式是正确的,但Nokogiri认为>
标记了字符串的结尾。这意味着Nokogiri在解析字符串之前解释了HTML(将>
转换为>
)。
问题:Nokogiri为什么要解释>
的HTML,并如何确保它解析整个字符串?
1年更新(供参考)
自从我第一次发布这个问题以来已经过去了一年多,此时我还没有找到对原始问题的明确答案。因此,我想为将来遇到这篇文章的任何人提供一些更新。请注意,我严格是指SAX解析,而不是DOM解析。
主要观点:
原始问题涉及到Nokogiri v1.6.1。最新版本(撰写本文时)是v1.6.6,但问题仍未解决。
然而,有一种解决这个问题的方法(请参见下面matt的评论),但如果不是所有字符串都格式相同(例如,一个字符串包含
>
一次,另一个字符串包含两次>
等),实现将会很棘手。我简要测试了另一个名为Ox的Ruby解析器,并发现它没有与Nokogiri相同的问题。确实,它可以正确处理包含
>
的字符串。此外,它还可以处理包含>
的字符串。作为奖励,它似乎比Nokogiri运行得更快(但也不是没有缺点)。
底线:
如果您遇到类似Nokogiri的问题,那么建议尝试使用Ox作为可能的替代方案。我不会争辩哪一个gem更好(这不是它的目的)。但是,我可以证明Ox在处理包含>
和/或>
的字符串的能力方面是值得信赖的。
characters
方法“可能会在给定一个连续的字符字符串时被调用多次”,在这种情况下(至少对我来说),它被调用了三次——一次是PART3
,一次是实体(>
被传递进去),一次是PART4
,所以看起来 Nokogiri(或 libxml)正在围绕实体将字符串分割开。你只看第一次调用时传入的内容吗?你需要缓存多次调用characters
来形成完整的字符串。 - matt>
时,它可以正常工作,但我的字符串没有。我让它能够工作了,但它非常丑陋,所以我希望关闭 HTML 解释以使事情更清洁。 - seane