你会推荐哪个Ruby XML库来处理一个2.4MB的XML文件?

16

我有一个2.4 MB的XML文件,是从Microsoft Project导出的(嘿,我是受害者!)其中我被要求提取某些详细信息以供再表示。忽略请求的智能性或其他方面,从Ruby的角度来看,我应该首先尝试哪个库?

我知道以下几个库(没有特定顺序):

我更喜欢作为Ruby gem打包的东西,我认为Chilkat库不是。

性能不是主要问题-我不希望这个程序需要每天运行超过一次(一周一次更可能)。我更感兴趣的是像所有与XML相关的内容一样易于使用的东西。

编辑:我尝试了gemified版本:

hpricot是最容易的选择。例如,要从名为“test.xml”的文件中提取此XML中SaveVersion标记的内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Project xmlns="http://schemas.microsoft.com/project">
    <SaveVersion>12</SaveVersion>
</Project>

大致如下:

doc = Hpricot.XML(open('test.xml'))
version = (doc/:Project/:SaveVersion).first.inner_html

相对于命名空间,hpricot似乎并不太关心,在这个例子中是没问题的:只有一个命名空间,但如果是复杂文档就可能会有问题。由于hpricot非常慢,我认为这将是一个自行解决的问题。

libxml-ruby快了一个数量级,理解命名空间(我花了好几个小时才弄明白),在XML方面更加接近原生——XPath查询和其他相关操作都在其中。如果像我一样,只在极端情况下打开XML文档,那么这不一定是好事。Helper模块在提供如何有效处理默认命名空间的示例方面大有帮助。这大致是我最终采用的方法(我并不宣称它有多美观、正确或有价值,只是我现在所在的状态):

xml_parser = XML::Parser.new
xml_parser.string = File.read(path)
doc = xml_parser.parse
@root = doc.root
@scopes = { :in_node => '', :in_root => '/', :in_doc => '//' }
@ns_prefix = 'p'
@ns = "#{@ns_prefix}:#{@root.namespace[0].href}"
version = @root.find_first(xpath_qry("Project/SaveVersion", :in_root), @ns).content.to_i

def xpath_qry(tags, scope = :in_node)
  "#{@scopes[scope]}" + tags.split(/\//).collect{ |tag| "#{@ns_prefix}:#{tag}"}.join('/')
end

我仍在权衡利弊:libxml因其额外的严谨性,hpricot因_why代码的简洁风格。

再次编辑,稍晚些时候:我发现了HappyMapper('gem install happymapper'),这是一个非常有前途的工具,虽然还处于早期阶段。它是声明式的并且大多数情况下都有效,尽管我发现了一些我尚未修复的边缘案例。它让你做像这样的事情,解析我的Google Reader OPML:

module OPML
  class Outline
    include HappyMapper
    tag 'outline'
    attribute :title, String
    attribute :text, String
    attribute :type, String
    attribute :xmlUrl, String
    attribute :htmlUrl, String
    has_many :outlines, Outline
  end
end

xml_string = File.read("google-reader-subscriptions.xml")

sections = OPML::Outline.parse(xml_string)

即使它还不完美,我已经喜欢上了它。


1
哦不!一个 2.4 mb 的 XML 文件!太可怕了! - user1228
好的,我认为如果是2.4 GB,答案可能会不同... ;) - Mike Woodhouse
2个回答

4
Nokogiri是一个用Ruby编写的库,它包装了libxml2和libxslt,提供了干净、符合Ruby语言风格的API,支持命名空间、XPath和CSS3查询。而且它还非常快速。 http://nokogiri.org/

请注意,由于底层依赖关系,它仅支持XPATH 1.0。 - Alptigin Jalayr

3

Hpricot可能是最适合您的工具--它易于使用,应该可以处理2mg文件而没有问题。

就速度而言,libxml应该是最好的。我几个月前使用了Python的libxml2绑定(当时rb-libxml已经过时)。流接口对我来说效果最好(在ruby gem中为LibXML::XML::Reader)。它允许在文件下载时处理文件,比SAX更加用户友好,并且使我能够在一分钟多一点的时间内从互联网上的30mb xml文件中加载数据到MySQL数据库中。


5
最近我会推荐使用Nokogiri而不是Hpricot。在我的经验中,它更加稳定,并且具有非常完整的功能和良好的维护。 - the Tin Man
1
是的,我同意,Nokogiri 是当前的首选。 - dimus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接