jaxb2ruby 0.0.1-java

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.
@@ -0,0 +1,33 @@
1
+ require "erb"
2
+
3
+ module JAXB2Ruby
4
+ class Template # :nodoc:
5
+ HEADING=<<HEAD
6
+ #
7
+ # Auto-generated by jaxb2ruby v<%= VERSION %> on <%= Time.now %>
8
+ # https://github.com/sshaw/jaxb2ruby
9
+ #
10
+ HEAD
11
+
12
+ PATHS = Hash[
13
+ Dir[File.expand_path(__FILE__ + "/../../templates/*.erb")].map do |path|
14
+ [File.basename(path, ".erb"), path]
15
+ end
16
+ ]
17
+
18
+ DEFAULT = PATHS["roxml"]
19
+
20
+ def initialize(name = nil)
21
+ # If it's not a named template assume it's a path
22
+ path = PATHS[name] || name || DEFAULT
23
+ @__erb = ERB.new(HEADING + File.read(path), nil, "<>%-")
24
+ rescue => e
25
+ raise Error, "cannot load class template: #{e}"
26
+ end
27
+
28
+ def build(klass)
29
+ @class = klass
30
+ @__erb.result(binding)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,90 @@
1
+ module JAXB2Ruby
2
+ class TypeUtil # :nodoc:
3
+ # Only includes types that aren't annotated with @XmlSchemaType
4
+ JAVA_TO_SCHEMA = {
5
+ "java.lang.Boolean" => "boolean",
6
+ "boolean" => "boolean",
7
+ "byte" => "byte",
8
+ # byte[]
9
+ "[B" => "base64Binary",
10
+ "double" => "double",
11
+ "float" => "float",
12
+ "java.lang.Integer" => "int",
13
+ "int" => "int",
14
+ "java.lang.Object" => "anySimpleType",
15
+ "java.lang.String" => "string",
16
+ "java.math.BigDecimal" => "decimal",
17
+ "java.math.BigInteger" => "int",
18
+ "javax.xml.datatype.Duration" => "duration",
19
+ "javax.xml.datatype.XMLGregorianCalendar" => "dateTime",
20
+ #"javax.xml.namespace.QName" => "NOTATION"
21
+ "javax.xml.namespace.QName" => "QName",
22
+ "java.lang.Long" => "long",
23
+ "long" => "long",
24
+ "short" => "short"
25
+ }
26
+
27
+ SCHEMA_TO_RUBY = {
28
+ "ID" => :ID,
29
+ "IDREF" => :IDREF,
30
+ "Name" => "String",
31
+ "NCName" => "String",
32
+ "NMTOKEN" => "String",
33
+ "anySimpleType" => "Object",
34
+ "anyType" => "Object",
35
+ "anyURI" => "String",
36
+ "base64Binary" => "String",
37
+ "boolean" => :boolean,
38
+ "byte" => "Integer",
39
+ "date" => "Date",
40
+ "dateTime" => "DateTime",
41
+ "decimal" => "Float", # BigDecimal
42
+ "double" => "Float",
43
+ "duration" => "String",
44
+ "float" => "Float",
45
+ "gDay" => "String",
46
+ "gMonth" => "String",
47
+ "gMonthDay" => "String",
48
+ "gYear" => "String",
49
+ "gYearMonth" => "String",
50
+ "hexBinary" => "String",
51
+ "int" => "Integer",
52
+ "integer" => "Integer",
53
+ "long" => "Integer",
54
+ "language" => "String",
55
+ "nonNegativeInteger" => "Integer",
56
+ "nonPositiveInteger" => "Integer",
57
+ "normalizedString" => "String",
58
+ "positiveInteger" => "Integer",
59
+ "QName" => "String",
60
+ "short" => "Integer",
61
+ "string" => "String",
62
+ "time" => "Time",
63
+ "token" => "String",
64
+ "unsignedByte" => "Integer",
65
+ "unsignedInt" => "Integer",
66
+ "unsignedLong" => "Integer",
67
+ "unsignedShort" => "Integer"
68
+ }
69
+
70
+ def initialize(schema2ruby)
71
+ @schema2ruby = SCHEMA_TO_RUBY.merge(schema2ruby || {})
72
+ end
73
+
74
+ def schema_ruby_types
75
+ @schema_types ||= SCHEMA_TO_RUBY.values.uniq
76
+ end
77
+
78
+ def java2schema(klass)
79
+ JAVA_TO_SCHEMA[klass]
80
+ end
81
+
82
+ def schema2ruby(type)
83
+ @schema2ruby[type]
84
+ end
85
+
86
+ def java2ruby(klass)
87
+ schema2ruby(java2schema(klass))
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,3 @@
1
+ module JAXB2Ruby
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,59 @@
1
+ require "tmpdir"
2
+ require "cocaine"
3
+
4
+ module JAXB2Ruby
5
+ class XJC # :nodoc:
6
+ CONFIG = File.join(File.dirname(__FILE__), "config.xjb")
7
+
8
+ # https://github.com/thoughtbot/cocaine/issues/24
9
+ Cocaine::CommandLine.runner = Cocaine::CommandLine::BackticksRunner.new
10
+
11
+ def initialize(schema, options = {})
12
+ @schema = schema
13
+ @options = options
14
+ setup_tmpdirs
15
+ end
16
+
17
+ def execute
18
+ xjc
19
+ javac
20
+ @classes
21
+ end
22
+
23
+ private
24
+ def setup_tmpdirs
25
+ @tmproot = Dir.mktmpdir
26
+ @classes = File.join(@tmproot, "classes")
27
+ @sources = File.join(@tmproot, "source")
28
+ [@classes, @sources].each { |dir| Dir.mkdir(dir) }
29
+ rescue IOErorr, SystemCallError => e
30
+ raise Error, "error creating temp directories: #{e}"
31
+ end
32
+
33
+ def xjc
34
+ options = @schema.end_with?(".wsdl") || @options[:wsdl] ? "-wsdl " : ""
35
+ options << "-extension -npa -d :sources :schema -b :config"
36
+ options << @options[:jvm].map { |opt| " -J#{opt}" }.join(" ") if @options[:jvm]
37
+ line = Cocaine::CommandLine.new("xjc", options)
38
+ line.run(:schema => @schema, :sources => @sources, :config => CONFIG)
39
+ rescue Cocaine::ExitStatusError => e
40
+ raise Error, "xjc execution failed: #{e}"
41
+ rescue Cocaine::CommandNotFoundError => e
42
+ raise command_not_found("xjc")
43
+ end
44
+
45
+ def javac
46
+ files = Dir[ File.join(@sources, "**/*.java") ]
47
+ line = Cocaine::CommandLine.new("javac", "-d :classes :files")
48
+ line.run(:classes => @classes, :files => files)
49
+ rescue Cocaine::ExitStatusError => e
50
+ raise Error, "javac execution failed: #{e}"
51
+ rescue Cocaine::CommandNotFoundError => e
52
+ raise command_not_found("javac")
53
+ end
54
+
55
+ def command_not_found(cmd)
56
+ Error.new("#{cmd} command not found, is it in your PATH enviornment variable?")
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,39 @@
1
+ <%- require "templates/util/happymapper" -%>
2
+
3
+ require "happymapper"
4
+ <%- @class.requires.each do |mod| -%>
5
+ require "<%= mod %>"
6
+ <%- end -%>
7
+
8
+ <%= @class.module.map { |mod| "module #{mod}" }.join " " %>
9
+ <%= @class.outter_class.map { |klass| "class #{klass}" }.join "; " %>
10
+
11
+ class <%= @class.basename %> <%= "< #{@class.superclass}" if @class.superclass %>
12
+ include HappyMapper
13
+
14
+ <%- [@class.element].concat(@class.element.children).map { |e| e.namespace }.compact.uniq.each do |ns| -%>
15
+ register_namespace "<%= ns.prefix %>", "<%= ns %>"
16
+ <%- end -%>
17
+
18
+ <%- if @class.element.root? && @class.element.namespace -%>
19
+ namespace "<%= @class.element.namespace.prefix %>"
20
+ <%- end -%>
21
+
22
+ tag "<%= @class.element.local_name %>"
23
+
24
+ <%- @class.element.children.each do |e| -%>
25
+ <% next if e.type == :ID || e.type == :IDREF %>
26
+ <%= accessor_method(e) %> :<%= e.accessor %>, <%= type_name(e) %>, :tag => "<%= e.local_name %>", :namespace => <%= namespace(e.namespace) %>
27
+ <%- end -%>
28
+
29
+ <%- if @class.element.text? -%>
30
+ content :content
31
+ <%- end -%>
32
+
33
+ <% @class.element.attributes.each do |attr| %>
34
+ attribute :<%= attr.accessor %>, <%= type_name(attr) %>, :tag => "<%= attr.local_name %>", :namespace => <%= namespace(attr.namespace) %>
35
+ <% end %>
36
+ end
37
+
38
+ <%= @class.outter_class.map { "end" }.join " " %>
39
+ <%= @class.module.map { "end" }.join " " %>
@@ -0,0 +1,42 @@
1
+ <%- require "templates/util/roxml" -%>
2
+
3
+ require "roxml"
4
+ <%- @class.requires.each do |mod| -%>
5
+ require "<%= mod %>"
6
+ <%- end -%>
7
+
8
+ <%= @class.module.map { |mod| "module #{mod}" }.join " " %>
9
+ <%= @class.outter_class.map { |klass| "class #{klass}" }.join "; " %>
10
+
11
+ class <%= @class.basename %> <%= "< #{@class.superclass}" if @class.superclass %>
12
+ include ROXML
13
+
14
+ <%= namespace_map(@class) %>
15
+
16
+ xml_name "<%= @class.element.name %>"
17
+
18
+ <%- @class.element.children.each do |e| -%>
19
+ <% if e.array? %>
20
+ xml_accessor <%= accessor_name(e) %>, :as => <%= type_name(e) %>, :from => "<%= e.name %>", :required => <%= e.required? %>
21
+ <%- elsif unsupported_type?(e.type) -%>
22
+ xml_accessor <%= accessor_name(e) %>, :from => "<%= e.name %>", :required => <%= e.required? %>
23
+ <%- else -%>
24
+ xml_accessor <%= accessor_name(e) %>, :as => <%= type_name(e) %>, :from => "<%= e.name %>", :required => <%= e.required? %>
25
+ <%- end -%>
26
+ <%- end -%>
27
+
28
+ <%- if @class.element.text? -%>
29
+ xml_accessor :content, :from => ".", :required => <%= @class.element.required? %>
30
+ <%- end -%>
31
+
32
+ <% @class.element.attributes.each do |attr| %>
33
+ <%- if unsupported_type?(attr.type) -%>
34
+ xml_accessor <%= accessor_name(attr) %>, :from => "@<%= attr.name %>", :required => <%= attr.required? %>
35
+ <% else %>
36
+ xml_accessor <%= accessor_name(attr) %>, :as => <%= type_name(attr) %>, :from => "@<%= attr.name %>", :required => <%= attr.required? %>
37
+ <% end %>
38
+ <% end %>
39
+ end
40
+
41
+ <%= @class.outter_class.map { "end" }.join " " %>
42
+ <%= @class.module.map { "end" }.join " " %>
@@ -0,0 +1,44 @@
1
+ <%- accessor = lambda { |node| node.accessor.tr("?", "") }; order = lambda { |nodes| nodes.sort_by { |n| n.name } } %>
2
+ <%- @class.requires.each do |mod| -%>
3
+ require "<%= mod %>"
4
+ <%- end -%>
5
+
6
+ <%= @class.module.map { |mod| "module #{mod}" }.join " " %>
7
+
8
+ <%= @class.outter_class.map { |klass| "class #{klass}" }.join "; " %>
9
+
10
+ class <%= @class.basename %> <%= "< #{@class.superclass}" if @class.superclass %>
11
+ <%- if @class.element.children.any? %>
12
+ # Elements
13
+ <%- order[@class.element.children].each do |attr| -%>
14
+ attr_accessor :<%= accessor[attr] %>
15
+ <%- end -%>
16
+ <% end %>
17
+
18
+ <%- if @class.element.attributes.any? %>
19
+ # Attributes
20
+ <%- order[@class.element.attributes].each do |attr| -%>
21
+ attr_accessor :<%= accessor[attr] %>
22
+ <%- end -%>
23
+ <%- end -%>
24
+
25
+ <%- nodes = order[@class.element.children + @class.element.attributes] %>
26
+ def initialize(attributes = nil)
27
+ attributes ||= {}
28
+ <% nodes.each do |node| %>
29
+ <%- if node.respond_to?(:array?) && node.array? -%>
30
+ @<%= accessor[node] %> = Array(attributes[:<%= accessor[node] %>]).dup unless attributes[:<%= accessor[node] %>].nil? <%# should these always ret an array? %>
31
+ <%- else -%>
32
+ @<%= accessor[node] %> = attributes[:<%= accessor[node] %>]
33
+ <%- end -%>
34
+ <%- end -%>
35
+ end
36
+
37
+ def inspect
38
+ sprintf "#<%%s:0x%x <%= nodes.map { |node| "@#{accessor[node]}=%s" }.join(", ") %>>", self.class.name, object_id, <%= nodes.map { |node| "@#{accessor[node]}.inspect" }.join(", ") %>
39
+ end
40
+ end
41
+
42
+ <%= @class.outter_class.map { "end" }.join " " %>
43
+
44
+ <%= @class.module.map { "end" }.join " " %>
@@ -0,0 +1,26 @@
1
+ def accessor_method(node)
2
+ if node.array?
3
+ "has_many"
4
+ elsif node.type.to_s.include?("::") # Class with namespace?
5
+ "has_one"
6
+ else
7
+ "element"
8
+ end
9
+ end
10
+
11
+ # HappyMapper quirk: we need to return nil if there's no namespace, otherwise the parent element's
12
+ # namespace will be used in XPath searches
13
+ def namespace(ns)
14
+ ns.blank? ? "nil" : %|"#{ns.prefix}"|
15
+ end
16
+
17
+ def type_name(node)
18
+ case node.type
19
+ when :boolean
20
+ "Boolean"
21
+ when "Object"
22
+ "String"
23
+ else
24
+ node.type
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ UNSUPPORTED_TYPES = [:ID, :IDREF, :boolean, "String", "Object"]
2
+
3
+ def unsupported_type?(type)
4
+ UNSUPPORTED_TYPES.include?(type)
5
+ end
6
+
7
+ def namespace_map(klass)
8
+ ns = [klass.element].concat(klass.element.children).map { |e| e.namespace }.compact.uniq
9
+ return unless ns.any?
10
+
11
+ map = "xml_namespaces "
12
+ map << ns.map { |e| sprintf('"%s" => "%s"', e.prefix, e) }.join(", ")
13
+ end
14
+
15
+ def type_name(node)
16
+ name = unsupported_type?(node.type) ? "" : node.type.dup
17
+ # May be an attribute node
18
+ if node.respond_to?(:array?) && node.array?
19
+ name.prepend "["
20
+ name.concat "]"
21
+ end
22
+ name
23
+ end
24
+
25
+ def accessor_name(node)
26
+ name = ":#{node.accessor}"
27
+ name << "?" if node.type == :boolean
28
+ name
29
+ end
@@ -0,0 +1,213 @@
1
+ require "spec_helper"
2
+ require "jaxb2ruby/type_util"
3
+
4
+ describe JAXB2Ruby::Converter do
5
+ it "creates ruby classes" do
6
+ classes = convert("address")
7
+ classes.size.must_equal(2)
8
+
9
+ hash = class_hash(classes)
10
+ hash["Address"].must_be_instance_of(JAXB2Ruby::RubyClass)
11
+ hash["Address"].name.must_equal("Com::Example::Address")
12
+ hash["Address"].module.must_equal("Com::Example")
13
+ hash["Address"].basename.must_equal("Address")
14
+ hash["Address"].outter_class.must_be_nil
15
+ hash["Address"].superclass.must_be_nil
16
+
17
+ hash["Recipient"].must_be_instance_of(JAXB2Ruby::RubyClass)
18
+ hash["Recipient"].name.must_equal("Com::Example::Recipient")
19
+ hash["Recipient"].module.must_equal("Com::Example")
20
+ hash["Recipient"].basename.must_equal("Recipient")
21
+ hash["Recipient"].superclass.must_be_nil
22
+ hash["Recipient"].outter_class.must_be_nil
23
+ end
24
+
25
+ it "creates inner classes from complex anonymous types" do
26
+ hash = class_hash(convert("types"))
27
+ hash["NestedClass"].must_be_instance_of(JAXB2Ruby::RubyClass)
28
+ hash["NestedClass"].name.must_equal("Com::Example::Types::Types::NestedClass")
29
+ hash["NestedClass"].module.must_equal("Com::Example::Types")
30
+ hash["NestedClass"].outter_class.must_equal("Types")
31
+ hash["NestedClass"].basename.must_equal("NestedClass")
32
+ end
33
+
34
+ it "creates superclasses from complex extension bases" do
35
+ hash = class_hash(convert("types"))
36
+ hash["TextSubType"].must_be_instance_of(JAXB2Ruby::RubyClass)
37
+ hash["TextSubType"].name.must_equal("Com::Example::Types::TextSubType")
38
+ hash["TextSubType"].superclass.must_equal("Com::Example::Types::TextType")
39
+ end
40
+
41
+ it "creates an element for each class" do
42
+ classes = convert("address")
43
+
44
+ hash = class_hash(classes)
45
+ hash["Address"].element.must_be_instance_of(JAXB2Ruby::Element)
46
+ hash["Address"].element.name.must_match(/\Ans\d+:Address\z/)
47
+ hash["Address"].element.local_name.must_equal("Address")
48
+ hash["Address"].element.namespace.must_equal("http://example.com")
49
+
50
+ hash["Recipient"].element.must_be_instance_of(JAXB2Ruby::Element)
51
+ hash["Recipient"].element.local_name.must_equal("Recipient")
52
+ hash["Recipient"].element.name.must_match(/\Ans\d+:Recipient\z/)
53
+ end
54
+
55
+ it "creates the right child elements for each class' element" do
56
+ classes = convert("address")
57
+ hash = class_hash(classes)
58
+
59
+ elements = class_hash(hash["Address"].element.children)
60
+ elements.size.must_equal(5)
61
+ %w[House Street Town County Country].each do |name|
62
+ elements[name].must_be_instance_of(JAXB2Ruby::Element)
63
+ elements[name].accessor.must_equal(name.underscore)
64
+ elements[name].type.must_equal("String")
65
+ end
66
+
67
+ elements = class_hash(hash["Recipient"].element.children)
68
+ elements.size.must_equal(2)
69
+ %w[FirstName LastName].each do |name|
70
+ elements[name].must_be_instance_of(JAXB2Ruby::Element)
71
+ elements[name].accessor.must_equal(name.underscore)
72
+ elements[name].type.must_equal("String")
73
+ end
74
+ end
75
+
76
+ it "creates the right attributes for each class" do
77
+ classes = class_hash(convert("address"))
78
+ classes["Address"].element.attributes.size.must_equal(2)
79
+
80
+ hash = class_hash(classes["Address"].element.attributes)
81
+ attr = hash["PostCode"]
82
+ attr.name.must_equal("PostCode")
83
+ attr.local_name.must_equal("PostCode")
84
+ attr.accessor.must_equal("post_code")
85
+ attr.type.must_equal("String")
86
+
87
+ attr = hash["State"]
88
+ attr.name.must_equal("State")
89
+ attr.local_name.must_equal("State")
90
+ attr.accessor.must_equal("state_code")
91
+ attr.type.must_equal("String")
92
+
93
+ classes["Recipient"].element.attributes.must_be_empty
94
+ end
95
+
96
+ it "detects classes that are a root xml element" do
97
+ classes = class_hash(convert("types"))
98
+ classes["Types"].element.root?.must_equal(true)
99
+ classes["NestedClass"].element.root?.must_equal(false)
100
+ end
101
+
102
+ it "detects types that are nillable" do
103
+ classes = class_hash(convert("types"))
104
+ nodes = node_hash(classes["Types"].element)
105
+ nodes["nillable"].nillable?.must_equal(true)
106
+ nodes["element"].nillable?.must_equal(false)
107
+ end
108
+
109
+ it "detects classes that are arrays" do
110
+ classes = class_hash(convert("types"))
111
+ nodes = node_hash(classes["Types"].element)
112
+ nodes["idrefs"].array?.must_equal(true)
113
+ nodes["idrefs"].type.must_equal("Object")
114
+
115
+ nodes["anyType"].must_be_instance_of(JAXB2Ruby::Element)
116
+ nodes["anyType"].array?.must_equal(false)
117
+ end
118
+
119
+ it "detects classes that contain text nodes" do
120
+ classes = class_hash(convert("types"))
121
+ classes["Types"].element.text?.must_equal(false)
122
+ classes["TextType"].element.text?.must_equal(true)
123
+ end
124
+
125
+ it "detects elements that are required" do
126
+ classes = class_hash(convert("address"))
127
+ required = node_hash(classes["Recipient"].element).select { |_, v| v.required? }
128
+ required.size.must_equal(2)
129
+ required.must_include("FirstName")
130
+ required.must_include("LastName")
131
+
132
+ required = node_hash(classes["Address"].element).select { |_, v| v.required? }
133
+ required.size.must_equal(4)
134
+ %w[House Street Town PostCode].each { |attr| required.must_include(attr) }
135
+ end
136
+
137
+ it "detects attributes that are required" do
138
+ classes = class_hash(convert("address"))
139
+ required = classes["Recipient"].element.attributes.select { |_, v| v.required? }
140
+ required.must_be_empty
141
+
142
+ required = class_hash(classes["Address"].element.attributes).select { |_, v| v.required? }
143
+ required.size.must_equal(1)
144
+ required.first.must_include("PostCode")
145
+ end
146
+
147
+ it "detects element defaults" do
148
+ classes = class_hash(convert("address"))
149
+ defaults = class_hash(classes["Recipient"].element.children).reject { |_, v| v.default.nil? }
150
+ defaults.must_be_empty
151
+
152
+ defaults = class_hash(classes["Address"].element.children).reject { |_, v| v.default.nil? }
153
+ defaults.size.must_equal(1)
154
+ defaults.must_include("Country")
155
+ defaults["Country"].default.must_equal("US")
156
+ end
157
+
158
+ it "detects attribute defaults" do
159
+ skip "No all XJC implementations support attribute defaults... but we do"
160
+ end
161
+
162
+ describe "given a namespace to module mapping" do
163
+ let(:mod) { "A::Namespace" }
164
+ let(:nsmap) { { "http://example.com" => mod } }
165
+
166
+ it "converts elements in the given namespace to the classes in the given module" do
167
+ hash = class_hash(convert("address", :namespace => nsmap))
168
+ hash["Address"].must_be_instance_of(JAXB2Ruby::RubyClass)
169
+ hash["Address"].name.must_equal("#{mod}::Address")
170
+ hash["Address"].module.must_equal(mod)
171
+ hash["Address"].basename.must_equal("Address")
172
+ end
173
+ end
174
+
175
+ describe "given an XML Schema type to Ruby type mapping" do
176
+ let(:typemap) { {
177
+ "anySimpleType" => "My::Type",
178
+ "boolean" => "TrueClass"
179
+ } }
180
+
181
+ # describe "elements without a mapping" do
182
+ # it "does not convert them" do
183
+ # end
184
+ # end
185
+
186
+ describe "elements with a mapping" do
187
+ it "converts them to the given classes" do
188
+ classes = class_hash(convert("types", :typemap => typemap))
189
+ nodes = node_hash(classes["Types"].element)
190
+ typemap.each do |xsd, ruby|
191
+ nodes[xsd].must_be_instance_of(JAXB2Ruby::Element)
192
+ nodes[xsd].type.must_equal(ruby)
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ describe "XML schema to ruby data type mapping" do
199
+ let(:nodes) {
200
+ classes = class_hash(convert("types"))
201
+ node_hash(classes["Types"].element)
202
+ }
203
+
204
+ # TODO: nillablePrimitiveArray
205
+ JAXB2Ruby::TypeUtil::SCHEMA_TO_RUBY.each do |xsd, ruby|
206
+ it "maps the schema type #{xsd} to the ruby type #{ruby}" do
207
+ # xsd type is also the accessor name
208
+ nodes[xsd].must_be_instance_of(JAXB2Ruby::Element)
209
+ nodes[xsd].type.must_equal(ruby)
210
+ end
211
+ end
212
+ end
213
+ end