ruby_speech 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ pkg/*
5
5
  spec/reports
6
6
  .yardoc
7
7
  doc
8
+ .*.swp
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # 0.3.0
2
+ * Feature (Taylor Carpenter): Added support for GRXML documents with most elements implemented.
3
+
1
4
  # 0.2.2
2
5
  * Feature: The SSML DSL now supports embedding SSML documents, elements or strings via the `embed` method. This behaves as you might expect:
3
6
 
data/README.md CHANGED
@@ -18,6 +18,7 @@ speak = RubySpeech::SSML.draw do
18
18
  end
19
19
  end
20
20
  end
21
+
21
22
  speak.to_s
22
23
  ```
23
24
 
@@ -44,6 +45,66 @@ Once your `Speak` is fully prepared and you're ready to send it off for processi
44
45
 
45
46
  You may also then need to call `to_s`.
46
47
 
48
+
49
+ Contruct a GRXML (SGR) document like this:
50
+
51
+ ```ruby
52
+ require 'ruby_speech'
53
+
54
+ grammy = RubySpeech::GRXML.draw do
55
+ self.mode = 'dtmf'
56
+ self.root = 'digits'
57
+ rule id: 'digits' do
58
+ one_of do
59
+ 0.upto(9) {|d| item { d.to_s } }
60
+ end
61
+ end
62
+
63
+ rule id: 'pin', scope: 'public' do
64
+ one_of do
65
+ item do
66
+ item repeat: '4' do
67
+ ruleref uri: '#digit'
68
+ end
69
+ "#"
70
+ end
71
+ item do
72
+ "* 9"
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ grammy.to_s
79
+ ```
80
+
81
+ which becomes
82
+
83
+ ```xml
84
+ <grammar xmlns="http://www.w3.org/2001/06/grammar" version="1.0" xml:lang="en-US" mode="dtmf" root="digits">
85
+ <rule id="digits">
86
+ <one-of>
87
+ <item>0</item>
88
+ <item>1</item>
89
+ <item>2</item>
90
+ <item>3</item>
91
+ <item>4</item>
92
+ <item>5</item>
93
+ <item>6</item>
94
+ <item>7</item>
95
+ <item>8</item>
96
+ <item>9</item>
97
+ </one-of>
98
+ </rule>
99
+ <rule id="pin" scope="public">
100
+ <one-of>
101
+ <item><item repeat="4"><ruleref uri="#digit"/></item>#</item>
102
+ <item>* 9</item>
103
+ </one-of>
104
+ </rule>
105
+ </grammar>
106
+ ```
107
+
47
108
  Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_speech/master/frames) for more
48
109
 
49
110
  ## Features:
@@ -56,6 +117,15 @@ Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_spee
56
117
  * `<break/>`
57
118
  * `<audio/>`
58
119
 
120
+ ### GRXML
121
+ * Document construction
122
+ * `<item/>`
123
+ * `<one-of/>`
124
+ * `<rule/>`
125
+ * `<ruleref/>`
126
+ * `<tag/>`
127
+ * `<token/>`
128
+
59
129
  ## TODO:
60
130
  ### SSML
61
131
  #### Document Structure
@@ -69,6 +139,11 @@ Check out the [YARD documentation](http://rdoc.info/github/benlangfeld/ruby_spee
69
139
  * `<mark/>`
70
140
  * `<desc/>`
71
141
 
142
+ ### GRXML
143
+ * `<meta/>` and `<metadata/>`
144
+ * `<example/>`
145
+ * `<lexicon/>`
146
+
72
147
 
73
148
  ## Links:
74
149
  * [Source](https://github.com/benlangfeld/ruby_speech)
@@ -0,0 +1,317 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
3
+ <xsd:annotation>
4
+ <xsd:documentation>SRGS 1.0 Core Schema (20031204)</xsd:documentation>
5
+ </xsd:annotation>
6
+ <xsd:annotation>
7
+ <xsd:documentation>
8
+ Copyright 1998-2003 W3C (MIT, ERCIM, Keio),
9
+ All Rights Reserved. Permission to use, copy, modify and
10
+ distribute the SRGS core schema and its accompanying documentation
11
+ for any purpose and without fee is hereby granted in
12
+ perpetuity, provided that the above copyright notice and this
13
+ paragraph appear in all copies. The copyright holders make no
14
+ representation about the suitability of the schema for any purpose.
15
+ It is provided "as is" without expressed or implied warranty.
16
+ </xsd:documentation>
17
+ </xsd:annotation>
18
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace"
19
+ schemaLocation="xml.xsd"/>
20
+ <!--<xsd:import namespace="http://www.w3.org/XML/1998/namespace"
21
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>-->
22
+ <xsd:annotation>
23
+ <xsd:documentation>General Datatypes</xsd:documentation>
24
+ </xsd:annotation>
25
+ <xsd:annotation>
26
+ <xsd:documentation>Grammar-specific datatypes</xsd:documentation>
27
+ </xsd:annotation>
28
+ <xsd:simpleType name="tag">
29
+ <xsd:restriction base="xsd:string"/>
30
+ </xsd:simpleType>
31
+ <xsd:simpleType name="example">
32
+ <xsd:restriction base="xsd:string"/>
33
+ </xsd:simpleType>
34
+ <xsd:simpleType name="Id.datatype">
35
+ <xsd:annotation>
36
+ <xsd:documentation>
37
+ does not expression the constraint that NULL VOID GARBAGE are illegal as rule name
38
+ </xsd:documentation>
39
+ </xsd:annotation>
40
+ <xsd:restriction base="xsd:ID">
41
+ <xsd:pattern value="[^.:\-]+"/>
42
+ </xsd:restriction>
43
+ </xsd:simpleType>
44
+ <xsd:simpleType name="Scope.datatype">
45
+ <xsd:restriction base="xsd:NMTOKEN">
46
+ <xsd:enumeration value="private"/>
47
+ <xsd:enumeration value="public"/>
48
+ </xsd:restriction>
49
+ </xsd:simpleType>
50
+ <xsd:simpleType name="Special.datatype">
51
+ <xsd:restriction base="xsd:NMTOKEN">
52
+ <xsd:enumeration value="NULL"/>
53
+ <xsd:enumeration value="VOID"/>
54
+ <xsd:enumeration value="GARBAGE"/>
55
+ </xsd:restriction>
56
+ </xsd:simpleType>
57
+ <xsd:simpleType name="Repeat-prob.datatype">
58
+ <xsd:restriction base="xsd:decimal">
59
+ <xsd:minInclusive value="0.0"/>
60
+ <xsd:maxInclusive value="1.0"/>
61
+ </xsd:restriction>
62
+ </xsd:simpleType>
63
+ <xsd:simpleType name="Repeat.datatype">
64
+ <xsd:annotation>
65
+ <xsd:documentation>
66
+ does not expression the constraint in n-m that m must be greater than n
67
+ </xsd:documentation>
68
+ </xsd:annotation>
69
+ <xsd:restriction base="xsd:string">
70
+ <xsd:pattern value="[0-9]+"/>
71
+ <xsd:pattern value="[0-9]+-([0-9]+)?"/>
72
+ <xsd:pattern value="([0-9]+)?-[0-9]+"/>
73
+ </xsd:restriction>
74
+ </xsd:simpleType>
75
+ <xsd:simpleType name="Weight.datatype">
76
+ <xsd:restriction base="xsd:string">
77
+ <xsd:pattern value="[0-9]+[.]?"/>
78
+ <xsd:pattern value="([0-9]+)?[.][0-9]+"/>
79
+ </xsd:restriction>
80
+ </xsd:simpleType>
81
+ <xsd:simpleType name="Tag-format.datatype">
82
+ <xsd:restriction base="xsd:anyURI"/>
83
+ </xsd:simpleType>
84
+ <xsd:simpleType name="Version.datatype">
85
+ <xsd:restriction base="xsd:NMTOKEN"/>
86
+ </xsd:simpleType>
87
+ <xsd:simpleType name="Root.datatype">
88
+ <xsd:annotation>
89
+ <xsd:documentation>does not expression the constraint that NULL VOID GARBAGE
90
+ are illegal as rule name</xsd:documentation>
91
+ </xsd:annotation>
92
+ <xsd:restriction base="xsd:IDREF">
93
+ <xsd:pattern value="[^.:\-]+"/>
94
+ </xsd:restriction>
95
+ </xsd:simpleType>
96
+ <xsd:simpleType name="Mode.datatype">
97
+ <xsd:restriction base="xsd:NMTOKEN">
98
+ <xsd:enumeration value="voice"/>
99
+ <xsd:enumeration value="dtmf"/>
100
+ </xsd:restriction>
101
+ </xsd:simpleType>
102
+ <xsd:simpleType name="Type.datatype">
103
+ <xsd:restriction base="xsd:string"/>
104
+ </xsd:simpleType>
105
+ <xsd:annotation>
106
+ <xsd:documentation>Grammar Attributes</xsd:documentation>
107
+ </xsd:annotation>
108
+ <xsd:attributeGroup name="Tag-format.attrib">
109
+ <xsd:annotation>
110
+ <xsd:documentation/>
111
+ </xsd:annotation>
112
+ <xsd:attribute name="tag-format" type="Tag-format.datatype"/>
113
+ </xsd:attributeGroup>
114
+ <xsd:attributeGroup name="Version.attrib">
115
+ <xsd:annotation>
116
+ <xsd:documentation/>
117
+ </xsd:annotation>
118
+ <xsd:attribute name="version" type="Version.datatype"/>
119
+ </xsd:attributeGroup>
120
+ <xsd:attributeGroup name="Mode.attrib">
121
+ <xsd:annotation>
122
+ <xsd:documentation/>
123
+ </xsd:annotation>
124
+ <xsd:attribute name="mode" type="Mode.datatype" default="voice"/>
125
+ </xsd:attributeGroup>
126
+ <xsd:attributeGroup name="Root.attrib">
127
+ <xsd:annotation>
128
+ <xsd:documentation/>
129
+ </xsd:annotation>
130
+ <xsd:attribute name="root" type="Root.datatype"/>
131
+ </xsd:attributeGroup>
132
+ <xsd:attributeGroup name="Special.attrib">
133
+ <xsd:annotation>
134
+ <xsd:documentation/>
135
+ </xsd:annotation>
136
+ <xsd:attribute name="special" type="Special.datatype"/>
137
+ </xsd:attributeGroup>
138
+ <xsd:attributeGroup name="Repeat-prob.attrib">
139
+ <xsd:annotation>
140
+ <xsd:documentation/>
141
+ </xsd:annotation>
142
+ <xsd:attribute name="repeat-prob" type="Repeat-prob.datatype"/>
143
+ </xsd:attributeGroup>
144
+ <xsd:attributeGroup name="Repeat.attrib">
145
+ <xsd:annotation>
146
+ <xsd:documentation/>
147
+ </xsd:annotation>
148
+ <xsd:attribute name="repeat" type="Repeat.datatype"/>
149
+ </xsd:attributeGroup>
150
+ <xsd:attributeGroup name="Type.attrib">
151
+ <xsd:annotation>
152
+ <xsd:documentation/>
153
+ </xsd:annotation>
154
+ <xsd:attribute name="type" type="Type.datatype"/>
155
+ </xsd:attributeGroup>
156
+ <xsd:attributeGroup name="Weight.attrib">
157
+ <xsd:annotation>
158
+ <xsd:documentation/>
159
+ </xsd:annotation>
160
+ <xsd:attribute name="weight" type="Weight.datatype"/>
161
+ </xsd:attributeGroup>
162
+ <xsd:attributeGroup name="Id.attrib">
163
+ <xsd:annotation>
164
+ <xsd:documentation/>
165
+ </xsd:annotation>
166
+ <xsd:attribute name="id" type="Id.datatype" use="required"/>
167
+ </xsd:attributeGroup>
168
+ <xsd:attributeGroup name="Scope.attrib">
169
+ <xsd:annotation>
170
+ <xsd:documentation/>
171
+ </xsd:annotation>
172
+ <xsd:attribute name="scope" type="Scope.datatype" default="private"/>
173
+ </xsd:attributeGroup>
174
+ <xsd:attributeGroup name="Token.attribs">
175
+ <xsd:annotation>
176
+ <xsd:documentation/>
177
+ </xsd:annotation>
178
+ <xsd:attribute ref="xml:lang"/>
179
+ </xsd:attributeGroup>
180
+ <xsd:attributeGroup name="One-of.attribs">
181
+ <xsd:annotation>
182
+ <xsd:documentation/>
183
+ </xsd:annotation>
184
+ <xsd:attribute ref="xml:lang"/>
185
+ </xsd:attributeGroup>
186
+ <xsd:attributeGroup name="Item.attribs">
187
+ <xsd:annotation>
188
+ <xsd:documentation/>
189
+ </xsd:annotation>
190
+ <xsd:attributeGroup ref="Repeat-prob.attrib"/>
191
+ <xsd:attributeGroup ref="Repeat.attrib"/>
192
+ <xsd:attributeGroup ref="Weight.attrib"/>
193
+ <xsd:attribute ref="xml:lang"/>
194
+ </xsd:attributeGroup>
195
+ <xsd:attributeGroup name="Grammar.attribs">
196
+ <xsd:annotation>
197
+ <xsd:documentation/>
198
+ </xsd:annotation>
199
+ <xsd:attributeGroup ref="Tag-format.attrib"/>
200
+ <xsd:attributeGroup ref="Version.attrib"/>
201
+ <xsd:attribute ref="xml:lang"/>
202
+ <xsd:attribute ref="xml:base"/>
203
+ <xsd:attributeGroup ref="Root.attrib"/>
204
+ <xsd:attributeGroup ref="Mode.attrib"/>
205
+ </xsd:attributeGroup>
206
+ <xsd:attributeGroup name="Ruleref.attribs">
207
+ <xsd:annotation>
208
+ <xsd:documentation/>
209
+ </xsd:annotation>
210
+ <xsd:attributeGroup ref="Type.attrib"/>
211
+ <xsd:attribute name="uri" type="xsd:anyURI"/>
212
+ <xsd:attributeGroup ref="Special.attrib"/>
213
+ </xsd:attributeGroup>
214
+ <xsd:attributeGroup name="Rule.attribs">
215
+ <xsd:annotation>
216
+ <xsd:documentation/>
217
+ </xsd:annotation>
218
+ <xsd:attributeGroup ref="Id.attrib"/>
219
+ <xsd:attributeGroup ref="Scope.attrib"/>
220
+ </xsd:attributeGroup>
221
+ <xsd:attributeGroup name="Lexicon.attribs">
222
+ <xsd:annotation>
223
+ <xsd:documentation/>
224
+ </xsd:annotation>
225
+ <xsd:attribute name="uri" type="xsd:anyURI" use="required"/>
226
+ <xsd:attributeGroup ref="Type.attrib"/>
227
+ </xsd:attributeGroup>
228
+ <xsd:attributeGroup name="Meta.attribs">
229
+ <xsd:annotation>
230
+ <xsd:documentation/>
231
+ </xsd:annotation>
232
+ <xsd:attribute name="name" type="xsd:NMTOKEN"/>
233
+ <xsd:attribute name="content" type="xsd:string" use="required"/>
234
+ <xsd:attribute name="http-equiv" type="xsd:NMTOKEN"/>
235
+ </xsd:attributeGroup>
236
+ <xsd:annotation>
237
+ <xsd:documentation>Content Models</xsd:documentation>
238
+ </xsd:annotation>
239
+ <xsd:group name="rule-expansion">
240
+ <xsd:choice>
241
+ <xsd:element name="token" type="token"/>
242
+ <xsd:element name="ruleref" type="ruleref"/>
243
+ <xsd:element name="item" type="item"/>
244
+ <xsd:element name="one-of" type="one-of"/>
245
+ <xsd:element name="tag" type="tag"/>
246
+ </xsd:choice>
247
+ </xsd:group>
248
+ <xsd:complexType name="ruleref">
249
+ <xsd:attributeGroup ref="Ruleref.attribs"/>
250
+ </xsd:complexType>
251
+ <xsd:complexType name="token" mixed="true">
252
+ <xsd:annotation>
253
+ <xsd:documentation>does not expression the constraint that empty content is illegal
254
+ </xsd:documentation>
255
+ </xsd:annotation>
256
+ <xsd:attributeGroup ref="Token.attribs"/>
257
+ </xsd:complexType>
258
+ <xsd:complexType name="one-of">
259
+ <xsd:sequence maxOccurs="unbounded">
260
+ <xsd:element name="item" type="item"/>
261
+ </xsd:sequence>
262
+ <xsd:attributeGroup ref="One-of.attribs"/>
263
+ </xsd:complexType>
264
+ <xsd:complexType name="item" mixed="true">
265
+ <xsd:group ref="rule-expansion" minOccurs="0" maxOccurs="unbounded"/>
266
+ <xsd:attributeGroup ref="Item.attribs"/>
267
+ </xsd:complexType>
268
+ <xsd:complexType name="rule" mixed="true">
269
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
270
+ <xsd:group ref="rule-expansion"/>
271
+ <xsd:element name="example" type="example"/>
272
+ </xsd:choice>
273
+ <xsd:attributeGroup ref="Rule.attribs"/>
274
+ </xsd:complexType>
275
+ <xsd:complexType name="lexicon">
276
+ <xsd:attributeGroup ref="Lexicon.attribs"/>
277
+ </xsd:complexType>
278
+ <xsd:complexType name="meta">
279
+ <xsd:attributeGroup ref="Meta.attribs"/>
280
+ </xsd:complexType>
281
+ <xsd:complexType name="metadata">
282
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
283
+ <xsd:any namespace="##other" processContents="lax"/>
284
+ </xsd:choice>
285
+ <xsd:anyAttribute namespace="##any" processContents="strict"/>
286
+ </xsd:complexType>
287
+
288
+ <xsd:group name="grammar.class">
289
+ <xsd:annotation>
290
+ <xsd:documentation>grammar content model</xsd:documentation>
291
+ </xsd:annotation>
292
+ <xsd:sequence>
293
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
294
+ <xsd:element name="lexicon" type="lexicon"/>
295
+ <xsd:element name="meta" type="meta"/>
296
+ <xsd:element name="metadata" type="metadata"/>
297
+ <xsd:element name="tag" type="tag"/>
298
+ </xsd:choice>
299
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
300
+ <xsd:element name="rule" type="rule"/>
301
+ </xsd:choice>
302
+ </xsd:sequence>
303
+ </xsd:group>
304
+
305
+ <xsd:complexType name="grammar">
306
+ <xsd:annotation>
307
+ <xsd:documentation>grammar type with grammar content model and attributes</xsd:documentation>
308
+ </xsd:annotation>
309
+ <xsd:group ref="grammar.class"/>
310
+ <xsd:attributeGroup ref="Grammar.attribs"/>
311
+ </xsd:complexType>
312
+
313
+ <xsd:annotation>
314
+ <xsd:documentation>Global Elements</xsd:documentation>
315
+ </xsd:annotation>
316
+ <xsd:element name="grammar" type="grammar"/>
317
+ </xsd:schema>
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+
3
+ <xsd:schema targetNamespace="http://www.w3.org/2001/06/grammar"
4
+ xmlns="http://www.w3.org/2001/06/grammar"
5
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
6
+ elementFormDefault="qualified">
7
+ <xsd:annotation>
8
+ <xsd:documentation>SRGS 1.0 Schema (20031204)</xsd:documentation>
9
+ </xsd:annotation>
10
+ <xsd:annotation>
11
+ <xsd:documentation>Copyright 1998-2003 W3C (MIT, ERCIM, Keio),
12
+ All Rights Reserved. Permission to use, copy, modify and
13
+ distribute the SRGS schema and its accompanying documentation
14
+ for any purpose and without fee is hereby granted in
15
+ perpetuity, provided that the above copyright notice and this
16
+ paragraph appear in all copies. The copyright holders make no
17
+ representation about the suitability of the schema for any purpose.
18
+ It is provided "as is" without expressed or implied warranty.
19
+ </xsd:documentation>
20
+ </xsd:annotation>
21
+
22
+ <xsd:redefine schemaLocation="grammar-core.xsd">
23
+ <xsd:annotation>
24
+ <xsd:documentation>restricted grammar type so that version attribute is mandatory</xsd:documentation>
25
+ </xsd:annotation>
26
+ <xsd:complexType name="grammar">
27
+ <xsd:complexContent>
28
+ <xsd:restriction base="grammar">
29
+ <xsd:group ref="grammar.class"/>
30
+ <xsd:attribute name="version" type="Version.datatype" use="required"/>
31
+ </xsd:restriction>
32
+ </xsd:complexContent>
33
+ </xsd:complexType>
34
+ </xsd:redefine>
35
+
36
+
37
+ </xsd:schema>
@@ -20,7 +20,10 @@ It is provided "as is" without expressed or implied warranty.
20
20
  <xsd:documentation>Importing dependent namespaces</xsd:documentation>
21
21
  </xsd:annotation>
22
22
  <xsd:import namespace="http://www.w3.org/XML/1998/namespace"
23
- schemaLocation="http://www.w3.org/2001/xml.xsd"/>
23
+ schemaLocation="xml.xsd"/>
24
+
25
+ <!--<xsd:import namespace="http://www.w3.org/XML/1998/namespace"
26
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>-->
24
27
  <xsd:annotation>
25
28
  <xsd:documentation>General Datatypes</xsd:documentation>
26
29
  </xsd:annotation>
@@ -0,0 +1,107 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+
3
+ module RubySpeech
4
+ module GRXML
5
+ class Element < Niceogiri::XML::Node
6
+ @@registrations = {}
7
+
8
+ class_attribute :registered_ns, :registered_name
9
+
10
+ # Register a new stanza class to a name and/or namespace
11
+ #
12
+ # This registers a namespace that is used when looking
13
+ # up the class name of the object to instantiate when a new
14
+ # stanza is received
15
+ #
16
+ # @param [#to_s] name the name of the node
17
+ #
18
+ def self.register(name)
19
+ self.registered_name = name.to_s
20
+ self.registered_ns = GRXML_NAMESPACE
21
+ @@registrations[[self.registered_name, self.registered_ns]] = self
22
+ end
23
+
24
+ # Find the class to use given the name and namespace of a stanza
25
+ #
26
+ # @param [#to_s] name the name to lookup
27
+ #
28
+ # @return [Class, nil] the class appropriate for the name
29
+ def self.class_from_registration(name)
30
+ @@registrations[[name.to_s, GRXML_NAMESPACE]]
31
+ end
32
+
33
+ # Import an XML::Node to the appropriate class
34
+ #
35
+ # Looks up the class the node should be then creates it based on the
36
+ # elements of the XML::Node
37
+ # @param [XML::Node] node the node to import
38
+ # @return the appropriate object based on the node name and namespace
39
+ def self.import(node)
40
+ return node.content if node.is_a?(Nokogiri::XML::Text)
41
+ klass = class_from_registration(node.element_name)
42
+ if klass && klass != self
43
+ klass.import node
44
+ else
45
+ new.inherit node
46
+ end
47
+ end
48
+
49
+ # Inherit the attributes and children of an XML::Node
50
+ #
51
+ # @param [XML::Node] node the node to inherit
52
+ # @return [self]
53
+ def inherit(node)
54
+ inherit_attrs node.attributes
55
+ node.children.each do |c|
56
+ self << c.dup
57
+ end
58
+ self
59
+ end
60
+
61
+ def self.new(element_name, atts = {}, &block)
62
+ super(element_name) do |new_node|
63
+ atts.each_pair { |k, v| new_node.send :"#{k}=", v }
64
+ block_return = new_node.instance_eval &block if block_given?
65
+ new_node << new_node.encode_special_chars(block_return) if block_return.is_a?(String)
66
+ end
67
+ end
68
+
69
+ def children
70
+ super.map { |c| Element.import c }
71
+ end
72
+
73
+ def embed(other)
74
+ case other
75
+ when String
76
+ self << encode_special_chars(other)
77
+ when Grammar
78
+ other.children.each do |child|
79
+ self << child
80
+ end
81
+ when Element
82
+ self << other
83
+ else
84
+ raise ArgumentError, "Can only embed a String or an GRXML element"
85
+ end
86
+ end
87
+
88
+ def method_missing(method_name, *args, &block)
89
+ const_name = method_name.to_s.sub('ssml', '').titleize.gsub(' ', '')
90
+ const = GRXML.const_get const_name
91
+ if const && self.class::VALID_CHILD_TYPES.include?(const)
92
+ if const == String
93
+ self << encode_special_chars(args.first)
94
+ else
95
+ self << const.new(*args, &block)
96
+ end
97
+ else
98
+ super
99
+ end
100
+ end
101
+
102
+ def eql?(o, *args)
103
+ super o, :content, :children, *args
104
+ end
105
+ end # Element
106
+ end # GRXML
107
+ end # RubySpeech