我怎样才能引入nokogiri解析并返回XML文档?
-
18-09-2019 - |
题
这里的一些奇怪的示例:
#!/usr/bin/ruby
require 'rubygems'
require 'open-uri'
require 'nokogiri'
print "without read: ", Nokogiri(open('http://weblog.rubyonrails.org/')).class, "\n"
print "with read: ", Nokogiri(open('http://weblog.rubyonrails.org/').read).class, "\n"
运行此返回:
without read: Nokogiri::XML::Document
with read: Nokogiri::HTML::Document
如果没有read
返回XML,并与它是HTML?该网页被定义为“XHTML过渡”,所以起初我以为引入nokogiri一定是阅读从流OpenURI的“内容类型”,但返回'text/html'
:
(rdb:1) doc = open(('http://weblog.rubyonrails.org/'))
(rdb:1) doc.content_type
"text/html"
这是什么服务器返回。所以,现在我想弄清楚为什么引入nokogiri将返回两个不同的值。它不会出现被解析文本并使用试探法来确定内容是否为HTML或XML。
同样的事情与ATOM源发生指向该页面:
(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
(rdb:1) doc.class
Nokogiri::XML::Document
(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails').read)
(rdb:1) doc.class
Nokogiri::HTML::Document
我需要能够解析页面而不知道它是什么提前,或者HTML或饲料(RSS或ATOM)且可靠地确定哪个是。我问引入nokogiri解析无论是HTML或XML饲料文件的主体,但我看到这些不一致的结果。
我想我可以写一些测试,以确定类型,但后来我跑进的XPath没有找到元素,但常规搜索工作:
(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
(rdb:1) doc.class
Nokogiri::XML::Document
(rdb:1) doc.xpath('/feed/entry').length
0
(rdb:1) doc.search('feed entry').length
15
我想通的XPath将使用XML,但结果不看守信无论是。
这些测试都做在我的Ubuntu中,但我已经看到了我的MacBook Pro相同的行为。我很想找出我做错了什么,但我还没有看到解析和检索这给了我稳定的结果的例子。谁能告诉我我的方法错误?
解决方案
它与方法引入nokogiri的解析方法工作要做。这里的源:
# File lib/nokogiri.rb, line 55
def parse string, url = nil, encoding = nil, options = nil
doc =
if string =~ /^\s*<[^Hh>]*html/i # Probably html
Nokogiri::HTML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_HTML)
else
Nokogiri::XML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_XML)
end
yield doc if block_given?
doc
end
的关键是线if string =~ /^\s*<[^Hh>]*html/i # Probably html
。当你只是用open
,它返回一个对象,不与正则表达式的工作,因此总是返回false。在另一方面,read
返回一个字符串,因此它的可能的被视为HTML。在这种情况下,因为它是正则表达式匹配。下面是字符串的开头:
<!DOCTYPE html PUBLIC
在正则表达式匹配“!DOCTYPE”到[^Hh>]*
然后匹配的“HTML”,从而假设它是HTML。为什么有人选择了这个正则表达式来确定该文件是HTML是超越我。与此正则表达式,即开始像<definitely-not-html>
标签被认为是HTML,但<this-is-still-not-html>
被认为是XML文件。你可能最好是关闭此功能哑掉停留,直接调用Nokogiri::HTML::Document#parse
或Nokogiri::XML::Document#parse
。
其他提示
响应您的问题的这一部分:
我想我可以写一些测试, 确定类型,但后来我跑进 XPath的不是寻找元素,但 定期搜索工作:
我已经使用引入nokogiri解析的原子饲料只是遇到了这个问题。这个问题似乎倒在匿名名称空间声明:
<feed xmlns="http://www.w3.org/2005/Atom">
卸下从源XML xmlns声明将使引入nokogiri使用XPath按通常进行搜索。从Feed中移除该声明显然不是一个不错的选择,所以不是我只是删除从文档的命名空间解析之后。例如:
doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
doc.remove_namespaces!
doc.xpath('/feed/entry').length
丑我知道,但它的伎俩。