我们将为2.4MB XML文件推荐哪个Ruby XML库?
我有一个2.4 MB的XML文件,是Microsoft Project的导出文件(嘿,我是这里的受害者!),请我从中提取某些详细信息以进行重新演示。忽略请求的智能或者其他方面,从Ruby的角度来看,我应该首先尝试哪个库?
我知道以下内容(无特定顺序):
- REXML
- Chilkat Ruby XML库
- hpricot XML
- 的libXML
我更喜欢打包为Ruby gem的东西,我怀疑Chilkat库不是。
性能不是主要问题,我不希望它每天需要运行多次(更有可能一周一次)。我对与XML相关的东西一样容易使用的东西感兴趣。
编辑:我尝试了宝石:
距离国家一英里,hpricot最容易。例如,要提取此XML中SaveVersion标记的内容(保存在名为" test.xml"的文件中)
<?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 metal 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)
我已经爱上了它,即使它还不完美。
解决方案
Hpricot可能是最适合工具-它易于使用,应该可以毫无问题地处理2mg文件。
Speedwise libxml应该是最好的。几个月前,我将libxml2绑定用于python(那时rb-libxml是过时的)。串流介面最适合我
(Ruby宝石中的LibXML :: XML :: Reader)。它允许在下载文件时对其进行处理,比SAX更加用户友好,并且允许我在超过一分钟的时间内将数据从30mb xml文件从互联网加载到MySQL数据库。
Nokogiri使用干净的Rubyish API包装libxml2和libxslt,该API支持名称空间,XPath和CSS3查询。也快。
http://nokogiri.org/