chef-gyoku 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +62 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +154 -0
- data/Gemfile +6 -0
- data/MIT-LICENSE +20 -0
- data/README.md +313 -0
- data/Rakefile +12 -0
- data/gyoku.gemspec +27 -0
- data/lib/gyoku/array.rb +96 -0
- data/lib/gyoku/hash.rb +105 -0
- data/lib/gyoku/prettifier.rb +29 -0
- data/lib/gyoku/version.rb +3 -0
- data/lib/gyoku/xml_key.rb +67 -0
- data/lib/gyoku/xml_value.rb +41 -0
- data/lib/gyoku.rb +14 -0
- data/spec/gyoku/array_spec.rb +121 -0
- data/spec/gyoku/hash_spec.rb +431 -0
- data/spec/gyoku/prettifier_spec.rb +39 -0
- data/spec/gyoku/xml_key_spec.rb +76 -0
- data/spec/gyoku/xml_value_spec.rb +61 -0
- data/spec/gyoku_spec.rb +82 -0
- data/spec/spec_helper.rb +15 -0
- metadata +132 -0
data/lib/gyoku/array.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module Gyoku
|
2
|
+
module Array
|
3
|
+
module_function
|
4
|
+
|
5
|
+
NESTED_ELEMENT_NAME = "element"
|
6
|
+
|
7
|
+
# Builds XML and prettifies it if +pretty_print+ option is set to +true+
|
8
|
+
def to_xml(array, key, escape_xml = true, attributes = {}, options = {})
|
9
|
+
xml = build_xml(array, key, escape_xml, attributes, options)
|
10
|
+
|
11
|
+
if options[:pretty_print] && options[:unwrap]
|
12
|
+
Prettifier.prettify(xml, options)
|
13
|
+
else
|
14
|
+
xml
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Translates a given +array+ to XML. Accepts the XML +key+ to add the elements to,
|
19
|
+
# whether to +escape_xml+ and an optional Hash of +attributes+.
|
20
|
+
def self.build_xml(array, key, escape_xml = true, attributes = {}, options = {})
|
21
|
+
self_closing = options.delete(:self_closing)
|
22
|
+
unwrap = unwrap?(options.fetch(:unwrap, false), key)
|
23
|
+
|
24
|
+
iterate_with_xml array, key, attributes, options do |xml, item, attrs, index|
|
25
|
+
if self_closing
|
26
|
+
xml.tag!(key, attrs)
|
27
|
+
else
|
28
|
+
case item
|
29
|
+
when ::Hash
|
30
|
+
if unwrap
|
31
|
+
xml << Hash.to_xml(item, options)
|
32
|
+
else
|
33
|
+
xml.tag!(key, attrs) { xml << Hash.build_xml(item, options) }
|
34
|
+
end
|
35
|
+
when ::Array
|
36
|
+
xml.tag!(key, attrs) { xml << Array.build_xml(item, NESTED_ELEMENT_NAME) }
|
37
|
+
when NilClass
|
38
|
+
xml.tag!(key, "xsi:nil" => "true")
|
39
|
+
else
|
40
|
+
xml.tag!(key, attrs) { xml << XMLValue.create(item, escape_xml) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Iterates over a given +array+ with a Hash of +attributes+ and yields a builder +xml+
|
47
|
+
# instance, the current +item+, any XML +attributes+ and the current +index+.
|
48
|
+
def iterate_with_xml(array, key, attributes, options, &block)
|
49
|
+
xml = Builder::XmlMarkup.new
|
50
|
+
unwrap = unwrap?(options.fetch(:unwrap, false), key)
|
51
|
+
|
52
|
+
if unwrap
|
53
|
+
xml.tag!(key, attributes) { iterate_array(xml, array, attributes, &block) }
|
54
|
+
else
|
55
|
+
iterate_array(xml, array, attributes, &block)
|
56
|
+
end
|
57
|
+
|
58
|
+
xml.target!
|
59
|
+
end
|
60
|
+
private_class_method :iterate_with_xml
|
61
|
+
|
62
|
+
# Iterates over a given +array+ with a Hash of +attributes+ and yields a builder +xml+
|
63
|
+
# instance, the current +item+, any XML +attributes+ and the current +index+.
|
64
|
+
def iterate_array(xml, array, attributes, &block)
|
65
|
+
array.each_with_index do |item, index|
|
66
|
+
attrs = if item.respond_to?(:keys)
|
67
|
+
item.each_with_object({}) do |v, st|
|
68
|
+
k = v[0].to_s
|
69
|
+
st[k[1..]] = v[1].to_s if Hash.explicit_attribute?(k)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
{}
|
73
|
+
end
|
74
|
+
yield xml, item, tag_attributes(attributes, index).merge(attrs), index
|
75
|
+
end
|
76
|
+
end
|
77
|
+
private_class_method :iterate_array
|
78
|
+
|
79
|
+
# Takes a Hash of +attributes+ and the +index+ for which to return attributes
|
80
|
+
# for duplicate tags.
|
81
|
+
def tag_attributes(attributes, index)
|
82
|
+
return {} if attributes.empty?
|
83
|
+
|
84
|
+
attributes.inject({}) do |hash, (key, value)|
|
85
|
+
value = value[index] if value.is_a? ::Array
|
86
|
+
value ? hash.merge(key => value) : hash
|
87
|
+
end
|
88
|
+
end
|
89
|
+
private_class_method :tag_attributes
|
90
|
+
|
91
|
+
def unwrap?(unwrap, key)
|
92
|
+
unwrap.is_a?(::Array) ? unwrap.include?(key.to_sym) : unwrap
|
93
|
+
end
|
94
|
+
private_class_method :unwrap?
|
95
|
+
end
|
96
|
+
end
|
data/lib/gyoku/hash.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require "builder"
|
2
|
+
require "gyoku/prettifier"
|
3
|
+
require "gyoku/array"
|
4
|
+
require "gyoku/xml_key"
|
5
|
+
require "gyoku/xml_value"
|
6
|
+
|
7
|
+
module Gyoku
|
8
|
+
module Hash
|
9
|
+
module_function
|
10
|
+
|
11
|
+
# Builds XML and prettifies it if +pretty_print+ option is set to +true+
|
12
|
+
def to_xml(hash, options = {})
|
13
|
+
xml = build_xml(hash, options)
|
14
|
+
|
15
|
+
if options[:pretty_print]
|
16
|
+
Prettifier.prettify(xml, options)
|
17
|
+
else
|
18
|
+
xml
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Translates a given +hash+ with +options+ to XML.
|
23
|
+
def build_xml(hash, options = {})
|
24
|
+
iterate_with_xml hash do |xml, key, value, attributes|
|
25
|
+
self_closing = key.to_s[-1, 1] == "/"
|
26
|
+
escape_xml = key.to_s[-1, 1] != "!"
|
27
|
+
xml_key = XMLKey.create key, options
|
28
|
+
|
29
|
+
if :content! === key
|
30
|
+
xml << XMLValue.create(value, escape_xml, options)
|
31
|
+
elsif ::Array === value
|
32
|
+
xml << Array.build_xml(value, xml_key, escape_xml, attributes, options.merge(self_closing: self_closing))
|
33
|
+
elsif ::Hash === value
|
34
|
+
xml.tag!(xml_key, attributes) { xml << build_xml(value, options) }
|
35
|
+
elsif self_closing
|
36
|
+
xml.tag!(xml_key, attributes)
|
37
|
+
elsif NilClass === value
|
38
|
+
xml.tag!(xml_key, "xsi:nil" => "true")
|
39
|
+
else
|
40
|
+
xml.tag!(xml_key, attributes) { xml << XMLValue.create(value, escape_xml, options) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def explicit_attribute?(key)
|
46
|
+
key.to_s.start_with?("@")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Iterates over a given +hash+ and yields a builder +xml+ instance, the current
|
50
|
+
# Hash +key+ and any XML +attributes+.
|
51
|
+
#
|
52
|
+
# Keys beginning with "@" are treated as explicit attributes for their container.
|
53
|
+
# You can use both :attributes! and "@" keys to specify attributes.
|
54
|
+
# In the event of a conflict, the "@" key takes precedence.
|
55
|
+
def iterate_with_xml(hash)
|
56
|
+
xml = Builder::XmlMarkup.new
|
57
|
+
attributes = hash[:attributes!] || {}
|
58
|
+
hash_without_attributes = hash.except(:attributes!)
|
59
|
+
|
60
|
+
order(hash_without_attributes).each do |key|
|
61
|
+
node_attr = attributes[key] || {}
|
62
|
+
# node_attr must be kind of ActiveSupport::HashWithIndifferentAccess
|
63
|
+
node_attr = node_attr.map { |k, v| [k.to_s, v] }.to_h
|
64
|
+
node_value = hash[key].respond_to?(:keys) ? hash[key].clone : hash[key]
|
65
|
+
|
66
|
+
if node_value.respond_to?(:keys)
|
67
|
+
explicit_keys = node_value.keys.select { |k| explicit_attribute?(k) }
|
68
|
+
explicit_attr = {}
|
69
|
+
explicit_keys.each { |k| explicit_attr[k.to_s[1..]] = node_value[k] }
|
70
|
+
node_attr.merge!(explicit_attr)
|
71
|
+
explicit_keys.each { |k| node_value.delete(k) }
|
72
|
+
|
73
|
+
tmp_node_value = node_value.delete(:content!)
|
74
|
+
node_value = tmp_node_value unless tmp_node_value.nil?
|
75
|
+
node_value = "" if node_value.respond_to?(:empty?) && node_value.empty?
|
76
|
+
end
|
77
|
+
|
78
|
+
yield xml, key, node_value, node_attr
|
79
|
+
end
|
80
|
+
|
81
|
+
xml.target!
|
82
|
+
end
|
83
|
+
private_class_method :iterate_with_xml
|
84
|
+
|
85
|
+
# Deletes and returns an Array of keys stored under the :order! key of a given +hash+.
|
86
|
+
# Defaults to return the actual keys of the Hash if no :order! key could be found.
|
87
|
+
# Raises an ArgumentError in case the :order! Array does not match the Hash keys.
|
88
|
+
def order(hash)
|
89
|
+
order = hash[:order!] || hash.delete("order!")
|
90
|
+
hash_without_order = hash.except(:order!)
|
91
|
+
order = hash_without_order.keys unless order.is_a? ::Array
|
92
|
+
|
93
|
+
# Ignore Explicit Attributes
|
94
|
+
orderable = order.delete_if { |k| explicit_attribute?(k) }
|
95
|
+
hashable = hash_without_order.keys.select { |k| !explicit_attribute?(k) }
|
96
|
+
|
97
|
+
missing, spurious = hashable - orderable, orderable - hashable
|
98
|
+
raise ArgumentError, "Missing elements in :order! #{missing.inspect}" unless missing.empty?
|
99
|
+
raise ArgumentError, "Spurious elements in :order! #{spurious.inspect}" unless spurious.empty?
|
100
|
+
|
101
|
+
order
|
102
|
+
end
|
103
|
+
private_class_method :order
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rexml/document"
|
2
|
+
|
3
|
+
module Gyoku
|
4
|
+
class Prettifier
|
5
|
+
DEFAULT_INDENT = 2
|
6
|
+
DEFAULT_COMPACT = true
|
7
|
+
|
8
|
+
attr_accessor :indent, :compact
|
9
|
+
|
10
|
+
def self.prettify(xml, options = {})
|
11
|
+
new(options).prettify(xml)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@indent = options[:indent] || DEFAULT_INDENT
|
16
|
+
@compact = options[:compact].nil? ? DEFAULT_COMPACT : options[:compact]
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adds intendations and newlines to +xml+ to make it more readable
|
20
|
+
def prettify(xml)
|
21
|
+
result = ""
|
22
|
+
formatter = REXML::Formatters::Pretty.new indent
|
23
|
+
formatter.compact = compact
|
24
|
+
doc = REXML::Document.new xml
|
25
|
+
formatter.write doc, result
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Gyoku
|
2
|
+
module XMLKey
|
3
|
+
class << self
|
4
|
+
CAMELCASE = lambda { |key| key.gsub(/\/(.?)/) { |m| "::#{m[-1].upcase}" }.gsub(/(?:^|_)(.)/) { |m| m[-1].upcase } }
|
5
|
+
LOWER_CAMELCASE = lambda { |key| key[0].chr.downcase + CAMELCASE.call(key)[1..] }
|
6
|
+
UPCASE = lambda { |key| key.upcase }
|
7
|
+
|
8
|
+
FORMULAS = {
|
9
|
+
lower_camelcase: lambda { |key| LOWER_CAMELCASE.call(key) },
|
10
|
+
camelcase: lambda { |key| CAMELCASE.call(key) },
|
11
|
+
upcase: lambda { |key| UPCASE.call(key) },
|
12
|
+
none: lambda { |key| key }
|
13
|
+
}
|
14
|
+
|
15
|
+
# Converts a given +object+ with +options+ to an XML key.
|
16
|
+
def create(key, options = {})
|
17
|
+
xml_key = chop_special_characters key.to_s
|
18
|
+
|
19
|
+
if unqualified = unqualify?(xml_key)
|
20
|
+
xml_key = xml_key.split(":").last
|
21
|
+
end
|
22
|
+
|
23
|
+
xml_key = key_converter(options, xml_key).call(xml_key) if Symbol === key
|
24
|
+
|
25
|
+
if !unqualified && qualify?(options) && !xml_key.include?(":")
|
26
|
+
xml_key = "#{options[:namespace]}:#{xml_key}"
|
27
|
+
end
|
28
|
+
|
29
|
+
xml_key
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Returns the formula for converting Symbol keys.
|
35
|
+
def key_converter(options, xml_key)
|
36
|
+
return options[:key_converter] if options[:key_converter].is_a? Proc
|
37
|
+
|
38
|
+
defined_key = options[:key_to_convert]
|
39
|
+
key_converter = if !defined_key.nil? && (defined_key == xml_key)
|
40
|
+
options[:key_converter]
|
41
|
+
elsif !defined_key.nil?
|
42
|
+
:lower_camelcase
|
43
|
+
elsif options[:except] == xml_key
|
44
|
+
:lower_camelcase
|
45
|
+
else
|
46
|
+
options[:key_converter] || :lower_camelcase
|
47
|
+
end
|
48
|
+
FORMULAS[key_converter]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Chops special characters from the end of a given +string+.
|
52
|
+
def chop_special_characters(string)
|
53
|
+
["!", "/"].include?(string[-1, 1]) ? string.chop : string
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns whether to remove the namespace from a given +key+.
|
57
|
+
def unqualify?(key)
|
58
|
+
key[0, 1] == ":"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns whether to namespace all keys (elementFormDefault).
|
62
|
+
def qualify?(options)
|
63
|
+
options[:element_form_default] == :qualified && options[:namespace]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "cgi"
|
2
|
+
require "date"
|
3
|
+
|
4
|
+
module Gyoku
|
5
|
+
module XMLValue
|
6
|
+
class << self
|
7
|
+
# xs:date format
|
8
|
+
XS_DATE_FORMAT = "%Y-%m-%d"
|
9
|
+
|
10
|
+
# xs:time format
|
11
|
+
XS_TIME_FORMAT = "%H:%M:%S"
|
12
|
+
|
13
|
+
# xs:dateTime format
|
14
|
+
XS_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%Z"
|
15
|
+
|
16
|
+
# Converts a given +object+ to an XML value.
|
17
|
+
def create(object, escape_xml = true, options = {})
|
18
|
+
case object
|
19
|
+
when Time
|
20
|
+
object.strftime XS_TIME_FORMAT
|
21
|
+
when DateTime
|
22
|
+
object.strftime XS_DATETIME_FORMAT
|
23
|
+
when Date
|
24
|
+
object.strftime XS_DATE_FORMAT
|
25
|
+
when String
|
26
|
+
escape_xml ? CGI.escapeHTML(object) : object
|
27
|
+
when ::Hash
|
28
|
+
Gyoku::Hash.to_xml(object, options)
|
29
|
+
else
|
30
|
+
if object.respond_to?(:to_datetime)
|
31
|
+
create object.to_datetime
|
32
|
+
elsif object.respond_to?(:call)
|
33
|
+
create object.call
|
34
|
+
else
|
35
|
+
object.to_s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/gyoku.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "gyoku/version"
|
2
|
+
require "gyoku/hash"
|
3
|
+
|
4
|
+
module Gyoku
|
5
|
+
# Converts a given Hash +key+ with +options+ into an XML tag.
|
6
|
+
def self.xml_tag(key, options = {})
|
7
|
+
XMLKey.create(key, options)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Translates a given +hash+ with +options+ to XML.
|
11
|
+
def self.xml(hash, options = {})
|
12
|
+
Hash.to_xml hash.dup, options
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Gyoku::Array do
|
4
|
+
describe ".to_xml" do
|
5
|
+
it "returns the XML for an Array of Hashes" do
|
6
|
+
array = [{name: "adam"}, {name: "eve"}]
|
7
|
+
result = "<user><name>adam</name></user><user><name>eve</name></user>"
|
8
|
+
|
9
|
+
expect(to_xml(array, "user")).to eq(result)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns the XML for an Array of Hashes unwrapped" do
|
13
|
+
array = [{name: "adam"}, {name: "eve"}]
|
14
|
+
result = "<user><name>adam</name><name>eve</name></user>"
|
15
|
+
|
16
|
+
expect(to_xml(array, "user", true, {}, unwrap: true)).to eq(result)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns the XML for an Array of different Objects" do
|
20
|
+
array = [:symbol, "string", 123]
|
21
|
+
result = "<value>symbol</value><value>string</value><value>123</value>"
|
22
|
+
|
23
|
+
expect(to_xml(array, "value")).to eq(result)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "defaults to escape special characters" do
|
27
|
+
array = ["<tag />", "adam & eve"]
|
28
|
+
result = "<value><tag /></value><value>adam & eve</value>"
|
29
|
+
|
30
|
+
expect(to_xml(array, "value")).to eq(result)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "does not escape special characters when told to" do
|
34
|
+
array = ["<tag />", "adam & eve"]
|
35
|
+
result = "<value><tag /></value><value>adam & eve</value>"
|
36
|
+
|
37
|
+
expect(to_xml(array, "value", false)).to eq(result)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "adds attributes to a given tag" do
|
41
|
+
array = ["adam", "eve"]
|
42
|
+
result = '<value active="true">adam</value><value active="true">eve</value>'
|
43
|
+
|
44
|
+
expect(to_xml(array, "value", :escape_xml, active: true)).to eq(result)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "adds attributes to tags when :unwrap is true" do
|
48
|
+
array = [{item: "abc"}]
|
49
|
+
key = "items"
|
50
|
+
escape_xml = :escape_xml
|
51
|
+
attributes = {"amount" => "1"}
|
52
|
+
options = {unwrap: true}
|
53
|
+
result = "<items amount=\"1\"><item>abc</item></items>"
|
54
|
+
|
55
|
+
expect(to_xml(array, key, escape_xml, attributes, options)).to eq result
|
56
|
+
end
|
57
|
+
|
58
|
+
it "adds attributes to duplicate tags" do
|
59
|
+
array = ["adam", "eve"]
|
60
|
+
result = '<value id="1">adam</value><value id="2">eve</value>'
|
61
|
+
|
62
|
+
expect(to_xml(array, "value", :escape_xml, id: [1, 2])).to eq(result)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "skips attribute for element without attributes if there are fewer attributes than elements" do
|
66
|
+
array = ["adam", "eve", "serpent"]
|
67
|
+
result = '<value id="1">adam</value><value id="2">eve</value><value>serpent</value>'
|
68
|
+
|
69
|
+
expect(to_xml(array, "value", :escape_xml, id: [1, 2])).to eq(result)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "handles nested Arrays" do
|
73
|
+
array = [["one", "two"]]
|
74
|
+
result = "<value><element>one</element><element>two</element></value>"
|
75
|
+
|
76
|
+
expect(to_xml(array, "value")).to eq(result)
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when :pretty_print option is set to true" do
|
80
|
+
context "when :unwrap option is set to true" do
|
81
|
+
it "returns prettified xml" do
|
82
|
+
array = ["one", "two", {"three" => "four"}]
|
83
|
+
options = {pretty_print: true, unwrap: true}
|
84
|
+
result = "<test>\n <test>one</test>\n <test>two</test>\n <three>four</three>\n</test>"
|
85
|
+
expect(to_xml(array, "test", true, {}, options)).to eq(result)
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when :indent option is specified" do
|
89
|
+
it "returns prettified xml with specified indent" do
|
90
|
+
array = ["one", "two", {"three" => "four"}]
|
91
|
+
options = {pretty_print: true, indent: 3, unwrap: true}
|
92
|
+
result = "<test>\n <test>one</test>\n <test>two</test>\n <three>four</three>\n</test>"
|
93
|
+
expect(to_xml(array, "test", true, {}, options)).to eq(result)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when :compact option is specified" do
|
98
|
+
it "returns prettified xml with specified compact mode" do
|
99
|
+
array = ["one", {"two" => "three"}]
|
100
|
+
options = {pretty_print: true, compact: false, unwrap: true}
|
101
|
+
result = "<test>\n <test>\n one\n </test>\n <two>\n three \n </two>\n</test>"
|
102
|
+
expect(to_xml(array, "test", true, {}, options)).to eq(result)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when :unwrap option is not set" do
|
108
|
+
it "returns non-prettified xml" do
|
109
|
+
array = ["one", "two", {"three" => "four"}]
|
110
|
+
options = {pretty_print: true}
|
111
|
+
result = "<test>one</test><test>two</test><test><three>four</three></test>"
|
112
|
+
expect(to_xml(array, "test", true, {}, options)).to eq(result)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_xml(*args)
|
119
|
+
Gyoku::Array.to_xml(*args)
|
120
|
+
end
|
121
|
+
end
|