如何通过Ruby中的RELAX NG验证XML?

时间:2009-05-27 00:51:35

标签: xml ruby relaxng

REXML模块似乎支持RELAX NG validation,但文档没有关于使用框架验证部分的任何实际信息。

如何使用RELAX NG架构验证XML文档?代码段最有帮助。 TIA!

2 个答案:

答案 0 :(得分:6)

好吧,我有一个程序构建但结果不好。

我的结论如下:

  1. rexml relaxng模式解析可能不起作用。代码说明它不完整
  2. rexml pull解析可能有效,但很难说
  3. 以上两者均未记录
  4. 您应该使用真正的XML库,例如libxml
  5. 这是我的测试程序: test.rb

    require 'rexml/validation/relaxng.rb'
    require 'rexml/parsers/pullparser.rb'
    
    # USAGE: ruby test.rb XML-FILE
    xml = ARGV[0]
    
    # schema must be a Relax NG XML (NOT compact / .rnc)
    schema = File.new( "example.rng" )
    validator = REXML::Validation::RelaxNG.new( schema )
    
    # The structure the validator made, which should be a complex structure but isn't
    validator.dump
    
    xmlfile = File.new( xml )
    parser = REXML::Parsers::PullParser.new( xmlfile )
    while parser.has_next?
      # Returns an PullEvent
      e = parser.pull
      # puts "Event ", e.inspect
      validator.validate(e)
    end
    

    我制作了一些玩具示例XML文件和RNG文件,然后在OSX 10.5.x上试用了它 (打破长线以使其可读):

    $ /usr/bin/ruby test.rb good.xml 
    < S.1 #{doc}, :end_document(  ) >
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rexml/
      validation/validation.rb:24:in `validate': Validation error.  Expected:
      :start_element( doc ) from < S.1 #:start_element( doc ), {head}, {body},
      :end_element(  ), :end_document(  ) >  but got "doc"(  )
      (REXML::Validation::ValidationException)
            from test.rb:20
    

    (我和1.9一样)

    所以,非常失败。

    (我可以更多地优化测试程序以使用add_listener,但它似乎不值得)

答案 1 :(得分:6)

我已经成功使用Nokogiri(从libxml-ruby gem切换后,因为它每次都使用v1.1.3进行了段错误,尽管更改日志表明某些Windows段错误问题已经解决)。

这是我正在使用的代码:

首先,安装Nokogiri,如果您遇到问题,请查看installation tutorial

gem install nokogiri

如果在Rails上运行,请在"Rails.root/config/enviroment.rb“中配置gem,例如:

config.gem 'nokogiri'

相反,如果运行Ruby,则只需require "nokogiri

要根据预定义的RelaxNG架构验证XML文档(我们假设这些文件存储在'public'中),请使用以下代码段:

schema_path = "public/mySchema.rng"    # Or any valid path to a .RNG File
doc_path    = "public/myInstance.xml"  # Or any valid path to a .XML File

schema = Nokogiri::XML::RelaxNG(File.open(schema_path))

instance = Nokogiri::XML(File.open(doc_path))
errors = schema.validate(instance)

is_valid = errors.empty?

希望这有帮助!