lib/csl/schema.rb in csl-1.0.0.pre1 vs lib/csl/schema.rb in csl-1.0.0.pre2
- old
+ new
@@ -2,11 +2,11 @@
class Schema
@version = '1.0.1'.freeze
@namespace = 'http://purl.org/net/xbiblio/csl'.freeze
- @preamble = '<?xml version="1.0" encoding="utf-8"?>'.freeze
+ @preamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".freeze
@types = %w{ article article-journal article-magazine article-newspaper
bill book broadcast chapter entry entry-dictionary entry-encyclopedia
figure graphic interview legal_case legislation manuscript map
motion_picture musical_score pamphlet paper-conference patent
@@ -72,27 +72,44 @@
quotes
},
:periods => %w{
strip-periods
},
- :textcase => %w{
- lowercase uppercase capitalize-first capitalize-all title sentence
- },
:name => %w{
name-form name-delimiter and delimiter-precedes-et-al initialize-with
- delimiter-precedes-last et-al-min etal-use-first et-al-subsequent-min
- et-al-subsequent-use-first et-al-use-last
+ delimiter-precedes-last et-al-min et-al-use-first et-al-subsequent-min
+ et-al-subsequent-use-first et-al-use-last name-as-sort-order
+ sort-separator initialize
},
:names => %w{
names-delimiter
}
})
@attributes.each_value { |v| v.map!(&:to_sym).freeze }
@attributes.freeze
+ @file = File.expand_path('../../../vendor/schema/csl.rng', __FILE__)
+ @validators = {
+ :nokogiri => lambda { |schema, style|
+ schema.validate(Nokogiri::XML(style)).map { |e| [e.line, e.message] }
+ },
+
+ :default => lambda { |schema, style|
+ raise ValidationError, "please `gem install nokogiri' for validation support"
+ }
+ }
+
+ begin
+ require 'nokogiri'
+ @validator = @validators[:nokogiri]
+ @schema = Nokogiri::XML::RelaxNG(File.open(@file))
+ rescue LoadError
+ @validator = @validators[:default]
+ end
+
class << self
attr_accessor :version, :namespace, :types, :variables, :categories,
:attributes, :preamble
@@ -100,10 +117,80 @@
def attr(*arguments)
attributes.values_at(*arguments).flatten(1)
end
+ # Validates the passed-in style or list of styles. The style argument(s)
+ # can either be a {Style} object, a style's file handle, XML content
+ # or a valid location (wildcards are supported). The method returns
+ # a list of validation errors; the passed-in style is valid if the
+ # method returns an empty list.
+ #
+ # @example
+ # CSL::Schema.validate(CSL::Style.load(:apa))
+ #
+ # CSL::Schema.validate('my-styles/style.csl')
+ # CSL::Schema.validate('my-styles/*.csl')
+ # CSL::Schema.validate('http://www.example.org/style.csl')
+ #
+ # @param style [Node,String,IO,Array] the style (or a list of styles)
+ # to validate.
+ #
+ # @raise [ArgumentError] if the passed-in argument is not a Style or
+ # a valid style location.
+ # @raise [ValidationError] if the validation process fails
+ #
+ # @return [<<Fixnum,String>>] a list of validation errors
+ def validate(node)
+ case
+ when node.is_a?(Node)
+ validator[schema, node.to_xml]
+ when node.respond_to?(:read)
+ validator[schema, node.read]
+ when node.is_a?(Enumerable) && !node.is_a?(String)
+ node.map { |n| validate(n) }.flatten(1)
+ when node.respond_to?(:to_s)
+ node = node.to_s
+
+ case
+ when node =~ /^\s*</
+ validator[schema, node]
+ when File.exists?(node)
+ validator[schema, File.open(node, 'r:UTF-8')]
+ else
+ glob = Dir.glob(node)
+
+ if glob.empty?
+ validator[schema, Kernel.open(node)]
+ else
+ glob.map { |n| validator[schema, File.open(n, 'r:UTF-8')] }.flatten(1)
+ end
+ end
+ else
+ raise ArgumentError, "failed to validate #{node.inspect}: not a CSL node"
+ end
+ end
+
+ # Whether or not the passed-in style (or list of styles) is valid.
+ #
+ # @see validate
+ #
+ # @param style [Style,String,IO,Array] the style (or a list of styles)
+ # to validate.
+ #
+ # @raise [ArgumentError] if the passed-in argument is not a Style or
+ # a valid style location.
+ # @raise [ValidationError] if the validation process fails
+ #
+ # @return [Boolean] whether or not the passed-in style (or styles)
+ # is valid.
+ def valid?(style)
+ validate(style).empty?
+ end
+
+ private
+
+ attr_reader :validators, :validator, :schema
end
- end
-
+ end
end
\ No newline at end of file