Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1314 lines (1164 sloc) 33.829 kb
require "time"
class Time
class << self
unless respond_to?(:w3cdtf)
def w3cdtf(date)
if /\A\s*
(-?\d+)-(\d\d)-(\d\d)
(?:T
(\d\d):(\d\d)(?::(\d\d))?
(\.\d+)?
(Z|[+-]\d\d:\d\d)?)?
\s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8))
datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i]
usec = 0
usec = $7.to_f * 1000000 if $7
zone = $8
if zone
off = zone_offset(zone, datetime[0])
datetime = apply_offset(*(datetime + [off]))
datetime << usec
time = Time.utc(*datetime)
time.localtime unless zone_utc?(zone)
time
else
datetime << usec
Time.local(*datetime)
end
else
raise ArgumentError.new("invalid date: #{date.inspect}")
end
end
end
end
unless method_defined?(:w3cdtf)
def w3cdtf
if usec.zero?
fraction_digits = 0
else
fraction_digits = Math.log10(usec.to_s.sub(/0*$/, '').to_i).floor + 1
end
xmlschema(fraction_digits)
end
end
end
require "English"
require "rss/utils"
require "rss/converter"
require "rss/xml-stylesheet"
module RSS
VERSION = "0.2.7"
URI = "http://purl.org/rss/1.0/"
DEBUG = false
class Error < StandardError; end
class OverlappedPrefixError < Error
attr_reader :prefix
def initialize(prefix)
@prefix = prefix
end
end
class InvalidRSSError < Error; end
class MissingTagError < InvalidRSSError
attr_reader :tag, :parent
def initialize(tag, parent)
@tag, @parent = tag, parent
super("tag <#{tag}> is missing in tag <#{parent}>")
end
end
class TooMuchTagError < InvalidRSSError
attr_reader :tag, :parent
def initialize(tag, parent)
@tag, @parent = tag, parent
super("tag <#{tag}> is too much in tag <#{parent}>")
end
end
class MissingAttributeError < InvalidRSSError
attr_reader :tag, :attribute
def initialize(tag, attribute)
@tag, @attribute = tag, attribute
super("attribute <#{attribute}> is missing in tag <#{tag}>")
end
end
class UnknownTagError < InvalidRSSError
attr_reader :tag, :uri
def initialize(tag, uri)
@tag, @uri = tag, uri
super("tag <#{tag}> is unknown in namespace specified by uri <#{uri}>")
end
end
class NotExpectedTagError < InvalidRSSError
attr_reader :tag, :uri, :parent
def initialize(tag, uri, parent)
@tag, @uri, @parent = tag, uri, parent
super("tag <{#{uri}}#{tag}> is not expected in tag <#{parent}>")
end
end
# For backward compatibility :X
NotExceptedTagError = NotExpectedTagError
class NotAvailableValueError < InvalidRSSError
attr_reader :tag, :value, :attribute
def initialize(tag, value, attribute=nil)
@tag, @value, @attribute = tag, value, attribute
message = "value <#{value}> of "
message << "attribute <#{attribute}> of " if attribute
message << "tag <#{tag}> is not available."
super(message)
end
end
class UnknownConversionMethodError < Error
attr_reader :to, :from
def initialize(to, from)
@to = to
@from = from
super("can't convert to #{to} from #{from}.")
end
end
# for backward compatibility
UnknownConvertMethod = UnknownConversionMethodError
class ConversionError < Error
attr_reader :string, :to, :from
def initialize(string, to, from)
@string = string
@to = to
@from = from
super("can't convert #{@string} to #{to} from #{from}.")
end
end
class NotSetError < Error
attr_reader :name, :variables
def initialize(name, variables)
@name = name
@variables = variables
super("required variables of #{@name} are not set: #{@variables.join(', ')}")
end
end
class UnsupportedMakerVersionError < Error
attr_reader :version
def initialize(version)
@version = version
super("Maker doesn't support version: #{@version}")
end
end
module BaseModel
include Utils
def install_have_child_element(tag_name, uri, occurs, name=nil, type=nil)
name ||= tag_name
add_need_initialize_variable(name)
install_model(tag_name, uri, occurs, name)
writer_type, reader_type = type
def_corresponded_attr_writer name, writer_type
def_corresponded_attr_reader name, reader_type
install_element(name) do |n, elem_name|
<<-EOC
if @#{n}
"\#{@#{n}.to_s(need_convert, indent)}"
else
''
end
EOC
end
end
alias_method(:install_have_attribute_element, :install_have_child_element)
def install_have_children_element(tag_name, uri, occurs, name=nil, plural_name=nil)
name ||= tag_name
plural_name ||= "#{name}s"
add_have_children_element(name, plural_name)
add_plural_form(name, plural_name)
install_model(tag_name, uri, occurs, plural_name, true)
def_children_accessor(name, plural_name)
install_element(name, "s") do |n, elem_name|
<<-EOC
rv = []
@#{n}.each do |x|
value = "\#{x.to_s(need_convert, indent)}"
rv << value if /\\A\\s*\\z/ !~ value
end
rv.join("\n")
EOC
end
end
def install_text_element(tag_name, uri, occurs, name=nil, type=nil,
disp_name=nil)
name ||= tag_name
disp_name ||= name
self::ELEMENTS << name unless self::ELEMENTS.include?(name)
add_need_initialize_variable(name)
install_model(tag_name, uri, occurs, name)
def_corresponded_attr_writer(name, type, disp_name)
def_corresponded_attr_reader(name, type || :convert)
install_element(name) do |n, elem_name|
<<-EOC
if respond_to?(:#{n}_content)
content = #{n}_content
else
content = @#{n}
end
if content
rv = "\#{indent}<#{elem_name}>"
value = html_escape(content)
if need_convert
rv << convert(value)
else
rv << value
end
rv << "</#{elem_name}>"
rv
else
''
end
EOC
end
end
def install_date_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil)
name ||= tag_name
type ||= :w3cdtf
disp_name ||= name
self::ELEMENTS << name
add_need_initialize_variable(name)
install_model(tag_name, uri, occurs, name)
# accessor
convert_attr_reader name
date_writer(name, type, disp_name)
install_element(name) do |n, elem_name|
<<-EOC
if @#{n}
rv = "\#{indent}<#{elem_name}>"
value = html_escape(@#{n}.#{type})
if need_convert
rv << convert(value)
else
rv << value
end
rv << "</#{elem_name}>"
rv
else
''
end
EOC
end
end
private
def install_element(name, postfix="")
elem_name = name.sub('_', ':')
method_name = "#{name}_element#{postfix}"
add_to_element_method(method_name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{method_name}(need_convert=true, indent='')
#{yield(name, elem_name)}
end
private :#{method_name}
EOC
end
def inherit_convert_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{attr}_without_inherit
convert(@#{attr})
end
def #{attr}
if @#{attr}
#{attr}_without_inherit
elsif @parent
@parent.#{attr}
else
nil
end
end
EOC
end
end
def uri_convert_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{attr}_without_base
convert(@#{attr})
end
def #{attr}
value = #{attr}_without_base
return nil if value.nil?
if /\\A[a-z][a-z0-9+.\\-]*:/i =~ value
value
else
"\#{base}\#{value}"
end
end
EOC
end
end
def convert_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{attr}
convert(@#{attr})
end
EOC
end
end
def yes_clean_other_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader(:#{attr})
def #{attr}?
YesCleanOther.parse(@#{attr})
end
EOC
end
end
def yes_other_attr_reader(*attrs)
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader(:#{attr})
def #{attr}?
Utils::YesOther.parse(@#{attr})
end
EOC
end
end
def csv_attr_reader(*attrs)
separator = nil
if attrs.last.is_a?(Hash)
options = attrs.pop
separator = options[:separator]
end
separator ||= ", "
attrs.each do |attr|
attr = attr.id2name if attr.kind_of?(Integer)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
attr_reader(:#{attr})
def #{attr}_content
if @#{attr}.nil?
@#{attr}
else
@#{attr}.join(#{separator.dump})
end
end
EOC
end
end
def date_writer(name, type, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if new_value.nil?
@#{name} = new_value
elsif new_value.kind_of?(Time)
@#{name} = new_value.dup
else
if @do_validate
begin
@#{name} = Time.__send__('#{type}', new_value)
rescue ArgumentError
raise NotAvailableValueError.new('#{disp_name}', new_value)
end
else
@#{name} = nil
if /\\A\\s*\\z/ !~ new_value.to_s
begin
unless Date._parse(new_value, false).empty?
@#{name} = Time.parse(new_value)
end
rescue ArgumentError
end
end
end
end
# Is it need?
if @#{name}
class << @#{name}
undef_method(:to_s)
alias_method(:to_s, :#{type})
end
end
end
EOC
end
def integer_writer(name, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if new_value.nil?
@#{name} = new_value
else
if @do_validate
begin
@#{name} = Integer(new_value)
rescue ArgumentError
raise NotAvailableValueError.new('#{disp_name}', new_value)
end
else
@#{name} = new_value.to_i
end
end
end
EOC
end
def positive_integer_writer(name, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if new_value.nil?
@#{name} = new_value
else
if @do_validate
begin
tmp = Integer(new_value)
raise ArgumentError if tmp <= 0
@#{name} = tmp
rescue ArgumentError
raise NotAvailableValueError.new('#{disp_name}', new_value)
end
else
@#{name} = new_value.to_i
end
end
end
EOC
end
def boolean_writer(name, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if new_value.nil?
@#{name} = new_value
else
if @do_validate and
![true, false, "true", "false"].include?(new_value)
raise NotAvailableValueError.new('#{disp_name}', new_value)
end
if [true, false].include?(new_value)
@#{name} = new_value
else
@#{name} = new_value == "true"
end
end
end
EOC
end
def text_type_writer(name, disp_name=name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if @do_validate and
!["text", "html", "xhtml", nil].include?(new_value)
raise NotAvailableValueError.new('#{disp_name}', new_value)
end
@#{name} = new_value
end
EOC
end
def content_writer(name, disp_name=name)
klass_name = "self.class::#{Utils.to_class_name(name)}"
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{name}=(new_value)
if new_value.is_a?(#{klass_name})
@#{name} = new_value
else
@#{name} = #{klass_name}.new
@#{name}.content = new_value
end
end
EOC
end
def yes_clean_other_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(value)
value = (value ? "yes" : "no") if [true, false].include?(value)
@#{name} = value
end
EOC
end
def yes_other_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(new_value)
if [true, false].include?(new_value)
new_value = new_value ? "yes" : "no"
end
@#{name} = new_value
end
EOC
end
def csv_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(new_value)
@#{name} = Utils::CSV.parse(new_value)
end
EOC
end
def csv_integer_writer(name, disp_name=name)
module_eval(<<-EOC, __FILE__, __LINE__ + 1)
def #{name}=(new_value)
@#{name} = Utils::CSV.parse(new_value) {|v| Integer(v)}
end
EOC
end
def def_children_accessor(accessor_name, plural_name)
module_eval(<<-EOC, *get_file_and_line_from_caller(2))
def #{plural_name}
@#{accessor_name}
end
def #{accessor_name}(*args)
if args.empty?
@#{accessor_name}.first
else
@#{accessor_name}[*args]
end
end
def #{accessor_name}=(*args)
receiver = self.class.name
warn("Warning:\#{caller.first.sub(/:in `.*'\z/, '')}: " \
"Don't use `\#{receiver}\##{accessor_name} = XXX'/" \
"`\#{receiver}\#set_#{accessor_name}(XXX)'. " \
"Those APIs are not sense of Ruby. " \
"Use `\#{receiver}\##{plural_name} << XXX' instead of them.")
if args.size == 1
@#{accessor_name}.push(args[0])
else
@#{accessor_name}.__send__("[]=", *args)
end
end
alias_method(:set_#{accessor_name}, :#{accessor_name}=)
EOC
end
end
module SetupMaker
def setup_maker(maker)
target = maker_target(maker)
unless target.nil?
setup_maker_attributes(target)
setup_maker_element(target)
setup_maker_elements(target)
end
end
private
def maker_target(maker)
nil
end
def setup_maker_attributes(target)
end
def setup_maker_element(target)
self.class.need_initialize_variables.each do |var|
value = __send__(var)
next if value.nil?
if value.respond_to?("setup_maker") and
!not_need_to_call_setup_maker_variables.include?(var)
value.setup_maker(target)
else
setter = "#{var}="
if target.respond_to?(setter)
target.__send__(setter, value)
end
end
end
end
def not_need_to_call_setup_maker_variables
[]
end
def setup_maker_elements(parent)
self.class.have_children_elements.each do |name, plural_name|
if parent.respond_to?(plural_name)
target = parent.__send__(plural_name)
__send__(plural_name).each do |elem|
elem.setup_maker(target)
end
end
end
end
end
class Element
extend BaseModel
include Utils
extend Utils::InheritedReader
include SetupMaker
INDENT = " "
MUST_CALL_VALIDATORS = {}
MODELS = []
GET_ATTRIBUTES = []
HAVE_CHILDREN_ELEMENTS = []
TO_ELEMENT_METHODS = []
NEED_INITIALIZE_VARIABLES = []
PLURAL_FORMS = {}
class << self
def must_call_validators
inherited_hash_reader("MUST_CALL_VALIDATORS")
end
def models
inherited_array_reader("MODELS")
end
def get_attributes
inherited_array_reader("GET_ATTRIBUTES")
end
def have_children_elements
inherited_array_reader("HAVE_CHILDREN_ELEMENTS")
end
def to_element_methods
inherited_array_reader("TO_ELEMENT_METHODS")
end
def need_initialize_variables
inherited_array_reader("NEED_INITIALIZE_VARIABLES")
end
def plural_forms
inherited_hash_reader("PLURAL_FORMS")
end
def inherited_base
::RSS::Element
end
def inherited(klass)
klass.const_set("MUST_CALL_VALIDATORS", {})
klass.const_set("MODELS", [])
klass.const_set("GET_ATTRIBUTES", [])
klass.const_set("HAVE_CHILDREN_ELEMENTS", [])
klass.const_set("TO_ELEMENT_METHODS", [])
klass.const_set("NEED_INITIALIZE_VARIABLES", [])
klass.const_set("PLURAL_FORMS", {})
tag_name = klass.name.split(/::/).last
tag_name[0, 1] = tag_name[0, 1].downcase
klass.instance_variable_set("@tag_name", tag_name)
klass.instance_variable_set("@have_content", false)
end
def install_must_call_validator(prefix, uri)
self::MUST_CALL_VALIDATORS[uri] = prefix
end
def install_model(tag, uri, occurs=nil, getter=nil, plural=false)
getter ||= tag
if m = self::MODELS.find {|t, u, o, g, p| t == tag and u == uri}
m[2] = occurs
else
self::MODELS << [tag, uri, occurs, getter, plural]
end
end
def install_get_attribute(name, uri, required=true,
type=nil, disp_name=nil,
element_name=nil)
disp_name ||= name
element_name ||= name
writer_type, reader_type = type
def_corresponded_attr_writer name, writer_type, disp_name
def_corresponded_attr_reader name, reader_type
if type == :boolean and /^is/ =~ name
alias_method "#{$POSTMATCH}?", name
end
self::GET_ATTRIBUTES << [name, uri, required, element_name]
add_need_initialize_variable(disp_name)
end
def def_corresponded_attr_writer(name, type=nil, disp_name=nil)
disp_name ||= name
case type
when :integer
integer_writer name, disp_name
when :positive_integer
positive_integer_writer name, disp_name
when :boolean
boolean_writer name, disp_name
when :w3cdtf, :rfc822, :rfc2822
date_writer name, type, disp_name
when :text_type
text_type_writer name, disp_name
when :content
content_writer name, disp_name
when :yes_clean_other
yes_clean_other_writer name, disp_name
when :yes_other
yes_other_writer name, disp_name
when :csv
csv_writer name
when :csv_integer
csv_integer_writer name
else
attr_writer name
end
end
def def_corresponded_attr_reader(name, type=nil)
case type
when :inherit
inherit_convert_attr_reader name
when :uri
uri_convert_attr_reader name
when :yes_clean_other
yes_clean_other_attr_reader name
when :yes_other
yes_other_attr_reader name
when :csv
csv_attr_reader name
when :csv_integer
csv_attr_reader name, :separator => ","
else
convert_attr_reader name
end
end
def content_setup(type=nil, disp_name=nil)
writer_type, reader_type = type
def_corresponded_attr_writer :content, writer_type, disp_name
def_corresponded_attr_reader :content, reader_type
@have_content = true
end
def have_content?
@have_content
end
def add_have_children_element(variable_name, plural_name)
self::HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name]
end
def add_to_element_method(method_name)
self::TO_ELEMENT_METHODS << method_name
end
def add_need_initialize_variable(variable_name)
self::NEED_INITIALIZE_VARIABLES << variable_name
end
def add_plural_form(singular, plural)
self::PLURAL_FORMS[singular] = plural
end
def required_prefix
nil
end
def required_uri
""
end
def need_parent?
false
end
def install_ns(prefix, uri)
if self::NSPOOL.has_key?(prefix)
raise OverlappedPrefixError.new(prefix)
end
self::NSPOOL[prefix] = uri
end
def tag_name
@tag_name
end
end
attr_accessor :parent, :do_validate
def initialize(do_validate=true, attrs=nil)
@parent = nil
@converter = nil
if attrs.nil? and (do_validate.is_a?(Hash) or do_validate.is_a?(Array))
do_validate, attrs = true, do_validate
end
@do_validate = do_validate
initialize_variables(attrs || {})
end
def tag_name
self.class.tag_name
end
def full_name
tag_name
end
def converter=(converter)
@converter = converter
targets = children.dup
self.class.have_children_elements.each do |variable_name, plural_name|
targets.concat(__send__(plural_name))
end
targets.each do |target|
target.converter = converter unless target.nil?
end
end
def convert(value)
if @converter
@converter.convert(value)
else
value
end
end
def valid?(ignore_unknown_element=true)
validate(ignore_unknown_element)
true
rescue RSS::Error
false
end
def validate(ignore_unknown_element=true)
do_validate = @do_validate
@do_validate = true
validate_attribute
__validate(ignore_unknown_element)
ensure
@do_validate = do_validate
end
def validate_for_stream(tags, ignore_unknown_element=true)
validate_attribute
__validate(ignore_unknown_element, tags, false)
end
def to_s(need_convert=true, indent='')
if self.class.have_content?
return "" if !empty_content? and !content_is_set?
rv = tag(indent) do |next_indent|
if empty_content?
""
else
xmled_content
end
end
else
rv = tag(indent) do |next_indent|
self.class.to_element_methods.collect do |method_name|
__send__(method_name, false, next_indent)
end
end
end
rv = convert(rv) if need_convert
rv
end
def have_xml_content?
false
end
def need_base64_encode?
false
end
def set_next_element(tag_name, next_element)
klass = next_element.class
prefix = ""
prefix << "#{klass.required_prefix}_" if klass.required_prefix
key = "#{prefix}#{tag_name.gsub(/-/, '_')}"
if self.class.plural_forms.has_key?(key)
ary = __send__("#{self.class.plural_forms[key]}")
ary << next_element
else
__send__("#{key}=", next_element)
end
end
protected
def have_required_elements?
self.class::MODELS.all? do |tag, uri, occurs, getter|
if occurs.nil? or occurs == "+"
child = __send__(getter)
if child.is_a?(Array)
children = child
children.any? {|c| c.have_required_elements?}
else
!child.to_s.empty?
end
else
true
end
end
end
private
def initialize_variables(attrs)
normalized_attrs = {}
attrs.each do |key, value|
normalized_attrs[key.to_s] = value
end
self.class.need_initialize_variables.each do |variable_name|
value = normalized_attrs[variable_name.to_s]
if value
__send__("#{variable_name}=", value)
else
instance_variable_set("@#{variable_name}", nil)
end
end
initialize_have_children_elements
@content = normalized_attrs["content"] if self.class.have_content?
end
def initialize_have_children_elements
self.class.have_children_elements.each do |variable_name, plural_name|
instance_variable_set("@#{variable_name}", [])
end
end
def tag(indent, additional_attrs={}, &block)
next_indent = indent + INDENT
attrs = collect_attrs
return "" if attrs.nil?
return "" unless have_required_elements?
attrs.update(additional_attrs)
start_tag = make_start_tag(indent, next_indent, attrs.dup)
if block
content = block.call(next_indent)
else
content = []
end
if content.is_a?(String)
content = [content]
start_tag << ">"
end_tag = "</#{full_name}>"
else
content = content.reject{|x| x.empty?}
if content.empty?
return "" if attrs.empty?
end_tag = "/>"
else
start_tag << ">\n"
end_tag = "\n#{indent}</#{full_name}>"
end
end
start_tag + content.join("\n") + end_tag
end
def make_start_tag(indent, next_indent, attrs)
start_tag = ["#{indent}<#{full_name}"]
unless attrs.empty?
start_tag << attrs.collect do |key, value|
%Q[#{h key}="#{h value}"]
end.join("\n#{next_indent}")
end
start_tag.join(" ")
end
def collect_attrs
attrs = {}
_attrs.each do |name, required, alias_name|
value = __send__(alias_name || name)
return nil if required and value.nil?
next if value.nil?
return nil if attrs.has_key?(name)
attrs[name] = value
end
attrs
end
def tag_name_with_prefix(prefix)
"#{prefix}:#{tag_name}"
end
# For backward compatibility
def calc_indent
''
end
def children
rv = []
self.class.models.each do |name, uri, occurs, getter|
value = __send__(getter)
next if value.nil?
value = [value] unless value.is_a?(Array)
value.each do |v|
rv << v if v.is_a?(Element)
end
end
rv
end
def _tags
rv = []
self.class.models.each do |name, uri, occurs, getter, plural|
value = __send__(getter)
next if value.nil?
if plural and value.is_a?(Array)
rv.concat([[uri, name]] * value.size)
else
rv << [uri, name]
end
end
rv
end
def _attrs
self.class.get_attributes.collect do |name, uri, required, element_name|
[element_name, required, name]
end
end
def __validate(ignore_unknown_element, tags=_tags, recursive=true)
if recursive
children.compact.each do |child|
child.validate
end
end
must_call_validators = self.class.must_call_validators
tags = tag_filter(tags.dup)
p tags if DEBUG
must_call_validators.each do |uri, prefix|
_validate(ignore_unknown_element, tags[uri], uri)
meth = "#{prefix}_validate"
if !prefix.empty? and respond_to?(meth, true)
__send__(meth, ignore_unknown_element, tags[uri], uri)
end
end
end
def validate_attribute
_attrs.each do |a_name, required, alias_name|
value = instance_variable_get("@#{alias_name || a_name}")
if required and value.nil?
raise MissingAttributeError.new(tag_name, a_name)
end
__send__("#{alias_name || a_name}=", value)
end
end
def _validate(ignore_unknown_element, tags, uri, models=self.class.models)
count = 1
do_redo = false
not_shift = false
tag = nil
models = models.find_all {|model| model[1] == uri}
element_names = models.collect {|model| model[0]}
if tags
tags_size = tags.size
tags = tags.sort_by {|x| element_names.index(x) || tags_size}
end
_tags = tags.dup if tags
models.each_with_index do |model, i|
name, model_uri, occurs, getter = model
if DEBUG
p "before"
p tags
p model
end
if not_shift
not_shift = false
elsif tags
tag = tags.shift
end
if DEBUG
p "mid"
p count
end
case occurs
when '?'
if count > 2
raise TooMuchTagError.new(name, tag_name)
else
if name == tag
do_redo = true
else
not_shift = true
end
end
when '*'
if name == tag
do_redo = true
else
not_shift = true
end
when '+'
if name == tag
do_redo = true
else
if count > 1
not_shift = true
else
raise MissingTagError.new(name, tag_name)
end
end
else
if name == tag
if models[i+1] and models[i+1][0] != name and
tags and tags.first == name
raise TooMuchTagError.new(name, tag_name)
end
else
raise MissingTagError.new(name, tag_name)
end
end
if DEBUG
p "after"
p not_shift
p do_redo
p tag
end
if do_redo
do_redo = false
count += 1
redo
else
count = 1
end
end
if !ignore_unknown_element and !tags.nil? and !tags.empty?
raise NotExpectedTagError.new(tags.first, uri, tag_name)
end
end
def tag_filter(tags)
rv = {}
tags.each do |tag|
rv[tag[0]] = [] unless rv.has_key?(tag[0])
rv[tag[0]].push(tag[1])
end
rv
end
def empty_content?
false
end
def content_is_set?
if have_xml_content?
__send__(self.class.xml_getter)
else
content
end
end
def xmled_content
if have_xml_content?
__send__(self.class.xml_getter).to_s
else
_content = content
_content = [_content].pack("m").delete("\n") if need_base64_encode?
h(_content)
end
end
end
module RootElementMixin
include XMLStyleSheetMixin
attr_reader :output_encoding
attr_reader :feed_type, :feed_subtype, :feed_version
attr_accessor :version, :encoding, :standalone
def initialize(feed_version, version=nil, encoding=nil, standalone=nil)
super()
@feed_type = nil
@feed_subtype = nil
@feed_version = feed_version
@version = version || '1.0'
@encoding = encoding
@standalone = standalone
@output_encoding = nil
end
def feed_info
[@feed_type, @feed_version, @feed_subtype]
end
def output_encoding=(enc)
@output_encoding = enc
self.converter = Converter.new(@output_encoding, @encoding)
end
def setup_maker(maker)
maker.version = version
maker.encoding = encoding
maker.standalone = standalone
xml_stylesheets.each do |xss|
xss.setup_maker(maker)
end
super
end
def to_feed(type, &block)
Maker.make(type) do |maker|
setup_maker(maker)
block.call(maker) if block
end
end
def to_rss(type, &block)
to_feed("rss#{type}", &block)
end
def to_atom(type, &block)
to_feed("atom:#{type}", &block)
end
def to_xml(type=nil, &block)
if type.nil? or same_feed_type?(type)
to_s
else
to_feed(type, &block).to_s
end
end
private
def same_feed_type?(type)
if /^(atom|rss)?(\d+\.\d+)?(?::(.+))?$/i =~ type
feed_type = ($1 || @feed_type).downcase
feed_version = $2 || @feed_version
feed_subtype = $3 || @feed_subtype
[feed_type, feed_version, feed_subtype] == feed_info
else
false
end
end
def tag(indent, attrs={}, &block)
rv = super(indent, ns_declarations.merge(attrs), &block)
return rv if rv.empty?
"#{xmldecl}#{xml_stylesheet_pi}#{rv}"
end
def xmldecl
rv = %Q[<?xml version="#{@version}"]
if @output_encoding or @encoding
rv << %Q[ encoding="#{@output_encoding or @encoding}"]
end
rv << %Q[ standalone="yes"] if @standalone
rv << "?>\n"
rv
end
def ns_declarations
decls = {}
self.class::NSPOOL.collect do |prefix, uri|
prefix = ":#{prefix}" unless prefix.empty?
decls["xmlns#{prefix}"] = uri
end
decls
end
def maker_target(target)
target
end
end
end
Jump to Line
Something went wrong with that request. Please try again.