Browse files

Merge branch 'release/0.3.3'

  • Loading branch information...
2 parents d3f76ed + a448bb0 commit 9b4e20c9629d74898e6e5ec1e741c9d0f3e5d41f @benlangfeld committed Dec 16, 2011
View
4 CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.3.3
+ * Allow `SSML::Element.import` and `GRXML::Element.import` to take a string as well as a Nokogiri::XML::Node
+ * Allow importing GRXML/SSML documents via their respective modules (eg `RubySpeech::GRXML.import '<grammar ... />'`)
+
# 0.3.2
* Fix inheriting an `SSML::Speak`'s language. Previously an imported `<speak/>` would end up with a `lang` attribute in addition to `xml:lang`, and `xml:lang` would have the default value (`en-US`). This required a Niceogiri dependency update.
View
1 lib/ruby_speech.rb
@@ -10,6 +10,7 @@ module RubySpeech
autoload :Version
+ autoload :GenericElement
autoload :SSML
autoload :GRXML
autoload :XML
View
111 lib/ruby_speech/generic_element.rb
@@ -0,0 +1,111 @@
+require 'active_support/core_ext/class/attribute'
+
+module RubySpeech
+ module GenericElement
+
+ def self.included(klass)
+ klass.class_attribute :registered_ns, :registered_name
+ klass.extend ClassMethods
+ end
+
+ module ClassMethods
+ @@registrations = {}
+
+ # 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 register(name)
+ self.registered_name = name.to_s
+ self.registered_ns = 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 class_from_registration(name)
+ @@registrations[[name.to_s, 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 import(node)
+ node = Nokogiri::XML.parse(node, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root unless node.is_a?(Nokogiri::XML::Node)
+ return node.content if node.is_a?(Nokogiri::XML::Text)
+ klass = class_from_registration(node.element_name)
+ if klass && klass != self
+ klass.import node
+ else
+ new.inherit node
+ end
+ end
+
+ def new(element_name, atts = {}, &block)
+ blk_proc = lambda 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
+
+ case RUBY_VERSION.split('.')[0,2].join.to_i
+ when 18
+ super(element_name).tap do |n|
+ blk_proc[n]
+ end
+ else
+ super(element_name) do |n|
+ blk_proc[n]
+ end
+ end
+ end
+ end
+
+ def children
+ super.map { |c| self.class.import c }
+ end
+
+ def embed(other)
+ case other
+ when String
+ self << encode_special_chars(other)
+ when self.class.root_element
+ other.children.each do |child|
+ self << child
+ end
+ when self.class.module::Element
+ self << other
+ else
+ raise ArgumentError, "Can only embed a String or an SSML element"
+ end
+ end
+
+ def method_missing(method_name, *args, &block)
+ const_name = method_name.to_s.sub('ssml', '').titleize.gsub(' ', '')
+ const = self.class.module.const_get const_name
+ if const && self.class::VALID_CHILD_TYPES.include?(const)
+ if const == String
+ self << encode_special_chars(args.first)
+ else
+ self << const.new(*args, &block)
+ end
+ else
+ super
+ end
+ end
+
+ def eql?(o, *args)
+ super o, :content, :children, *args
+ end
+ end # Element
+end # RubySpeech
View
4 lib/ruby_speech/grxml.rb
@@ -21,5 +21,9 @@ def self.draw(attributes = {}, &block)
grammar << block_return if block_return.is_a?(String)
end
end
+
+ def self.import(other)
+ Element.import other
+ end
end # GRXML
end # RubySpeech
View
111 lib/ruby_speech/grxml/element.rb
@@ -3,116 +3,19 @@
module RubySpeech
module GRXML
class Element < Niceogiri::XML::Node
- @@registrations = {}
-
- class_attribute :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 = GRXML_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, GRXML_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)
- return node.content if node.is_a?(Nokogiri::XML::Text)
- klass = class_from_registration(node.element_name)
- 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)
- blk_proc = lambda 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
-
- case RUBY_VERSION.split('.')[0,2].join.to_i
- when 18
- super(element_name).tap do |n|
- blk_proc[n]
- end
- else
- super(element_name) do |n|
- blk_proc[n]
- end
- end
+ def self.namespace
+ GRXML_NAMESPACE
end
- def children
- super.map { |c| Element.import c }
+ def self.root_element
+ Grammar
end
- def embed(other)
- case other
- when String
- self << encode_special_chars(other)
- when Grammar
- other.children.each do |child|
- self << child
- end
- when Element
- self << other
- else
- raise ArgumentError, "Can only embed a String or an GRXML element"
- end
+ def self.module
+ GRXML
end
- def method_missing(method_name, *args, &block)
- const_name = method_name.to_s.sub('ssml', '').titleize.gsub(' ', '')
- const = GRXML.const_get const_name
- if const && self.class::VALID_CHILD_TYPES.include?(const)
- if const == String
- self << encode_special_chars(args.first)
- else
- self << const.new(*args, &block)
- end
- else
- super
- end
- end
-
- def eql?(o, *args)
- super o, :content, :children, *args
- end
+ include GenericElement
end # Element
end # GRXML
end # RubySpeech
View
4 lib/ruby_speech/ssml.rb
@@ -21,5 +21,9 @@ def self.draw(&block)
speak << block_return if block_return.is_a?(String)
end
end
+
+ def self.import(other)
+ Element.import other
+ end
end # SSML
end # RubySpeech
View
99 lib/ruby_speech/ssml/element.rb
@@ -3,104 +3,19 @@
module RubySpeech
module SSML
class Element < Niceogiri::XML::Node
- @@registrations = {}
-
- class_attribute :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)
- return node.content if node.is_a?(Nokogiri::XML::Text)
- klass = class_from_registration(node.element_name)
- if klass && klass != self
- klass.import node
- else
- new.inherit node
- end
+ def self.namespace
+ SSML_NAMESPACE
end
- def self.new(element_name, atts = {}, &block)
- blk_proc = lambda 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
-
- case RUBY_VERSION.split('.')[0,2].join.to_i
- when 18
- super(element_name).tap do |n|
- blk_proc[n]
- end
- else
- super(element_name) do |n|
- blk_proc[n]
- end
- end
- end
-
- def children
- super.map { |c| Element.import c }
+ def self.root_element
+ Speak
end
- def embed(other)
- case other
- when String
- self << encode_special_chars(other)
- when Speak
- other.children.each do |child|
- self << child
- end
- when Element
- self << other
- else
- raise ArgumentError, "Can only embed a String or an SSML element"
- end
+ def self.module
+ SSML
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
- self << encode_special_chars(args.first)
- else
- self << const.new(*args, &block)
- end
- else
- super
- end
- end
-
- def eql?(o, *args)
- super o, :content, :children, *args
- end
+ include GenericElement
end # Element
end # SSML
end # RubySpeech
View
2 lib/ruby_speech/version.rb
@@ -1,3 +1,3 @@
module RubySpeech
- VERSION = "0.3.2"
+ VERSION = "0.3.3"
end
View
2 spec/ruby_speech/grxml_spec.rb
@@ -229,7 +229,7 @@ module RubySpeech
GRXML::Grammar.new.tap { |doc| doc << rule }.to_s
end
- let(:import) { GRXML::Element.import parse_xml(document).root }
+ let(:import) { GRXML.import document }
subject { import }
View
2 spec/ruby_speech/ssml_spec.rb
@@ -238,7 +238,7 @@ module RubySpeech
SSML::Speak.new.tap { |doc| doc << voice }.to_s
end
- let(:import) { SSML::Element.import parse_xml(document).root }
+ let(:import) { SSML.import document }
subject { import }

0 comments on commit 9b4e20c

Please sign in to comment.