lib/ruby_speech/ssml/element.rb in ruby_speech-0.1.5 vs lib/ruby_speech/ssml/element.rb in ruby_speech-0.2.0
- old
+ new
@@ -1,16 +1,76 @@
+require 'active_support/core_ext/class/inheritable_attributes'
+
module RubySpeech
module SSML
class Element < Niceogiri::XML::Node
+ @@registrations = {}
+
+ class_inheritable_accessor :registered_ns, :registered_name
+
+ # Register a new stanza class to a name and/or namespace
+ #
+ # This registers a namespace that is used when looking
+ # up the class name of the object to instantiate when a new
+ # stanza is received
+ #
+ # @param [#to_s] name the name of the node
+ #
+ def self.register(name)
+ self.registered_name = name.to_s
+ self.registered_ns = SSML_NAMESPACE
+ @@registrations[[self.registered_name, self.registered_ns]] = self
+ end
+
+ # Find the class to use given the name and namespace of a stanza
+ #
+ # @param [#to_s] name the name to lookup
+ #
+ # @return [Class, nil] the class appropriate for the name
+ def self.class_from_registration(name)
+ @@registrations[[name.to_s, SSML_NAMESPACE]]
+ end
+
+ # Import an XML::Node to the appropriate class
+ #
+ # Looks up the class the node should be then creates it based on the
+ # elements of the XML::Node
+ # @param [XML::Node] node the node to import
+ # @return the appropriate object based on the node name and namespace
+ def self.import(node)
+ klass = class_from_registration(node.element_name)
+ event = if klass && klass != self
+ klass.import node
+ else
+ new.inherit node
+ end
+ end
+
+ # Inherit the attributes and children of an XML::Node
+ #
+ # @param [XML::Node] node the node to inherit
+ # @return [self]
+ def inherit(node)
+ inherit_attrs node.attributes
+ node.children.each do |c|
+ self << c.dup
+ end
+ self
+ end
+
def self.new(element_name, atts = {}, &block)
super(element_name) do |new_node|
atts.each_pair { |k, v| new_node.send :"#{k}=", v }
block_return = new_node.instance_eval &block if block_given?
new_node << new_node.encode_special_chars(block_return) if block_return.is_a?(String)
end
end
+ def children
+ super.reject { |c| c.is_a?(Nokogiri::XML::Text) }.map { |c| Element.import c }
+ end
+
def method_missing(method_name, *args, &block)
const_name = method_name.to_s.sub('ssml', '').titleize.gsub(' ', '')
const = SSML.const_get const_name
if const && self.class::VALID_CHILD_TYPES.include?(const)
if const == String
@@ -22,10 +82,10 @@
super
end
end
def eql?(o, *args)
- super o, :content, *args
+ super o, :content, :children, *args
end
end # Element
end # SSML
end # RubySpeech