Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I validate XML via RELAX NG in Ruby?

Tags:

xml

ruby

relaxng

The REXML module appears to have support for RELAX NG validation, but the docs don't have any real information on using the validation portion of the framework.

How would you validate an XML document with a RELAX NG schema? A code snippet would be most helpful. TIA!

like image 568
cdleary Avatar asked May 27 '09 00:05

cdleary


1 Answers

Well, I got a program constructed but the results aren't good.

My conclusions are as follows:

  1. rexml relaxng schema parsing probably does not work. the code notes it is incomplete
  2. rexml pull parsing probably works but hard to tell
  3. both of the above are undocumented
  4. you should use a real XML library such as libxml

Here's my test program: 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

and I made some toy example XML files and RNG files and then tried it out on OSX 10.5.x (long line broken to make it readable):

$ /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

(I get the same with 1.9)

So, pretty much failure.

(I could have optimized the test program some more to use add_listener but it didn't seem worthwhile)

like image 102
dajobe Avatar answered Sep 19 '22 10:09

dajobe