ostructer 0.1
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/History.rdoc +3 -0
- data/Manifest.txt +5 -0
- data/README.rdoc +17 -0
- data/Rakefile +23 -0
- data/lib/ostructer.rb +353 -0
- data/test/test_config.rb +69 -0
- data/test/test_customer.rb +63 -0
- data/test/test_misc.rb +40 -0
- metadata +123 -0
data/History.rdoc
ADDED
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= Ostructer - Open Struct Builder in Ruby
|
2
|
+
|
3
|
+
* http://github.com/geraldb/ostructer
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Lets you build open structs from nested hashes, arrays and strings.
|
8
|
+
|
9
|
+
== INSTALL:
|
10
|
+
|
11
|
+
Just install the gem:
|
12
|
+
|
13
|
+
$ sudo gem install ostructer
|
14
|
+
|
15
|
+
== LICENSE:
|
16
|
+
|
17
|
+
The ostructers sources are dedicated to the public domain. Use it as you please with no restrictions whatsoever.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'hoe'
|
2
|
+
require './lib/ostructer.rb'
|
3
|
+
|
4
|
+
Hoe.spec 'ostructer' do
|
5
|
+
|
6
|
+
self.version = Ostructer::VERSION
|
7
|
+
|
8
|
+
self.summary = 'Ostructer - Open Struct Builder'
|
9
|
+
self.url = 'http://github.com/geraldb/ostructer'
|
10
|
+
|
11
|
+
self.author = 'Gerald Bauer'
|
12
|
+
self.email = 'gerald.bauer@gmail.com'
|
13
|
+
|
14
|
+
self.extra_deps = [
|
15
|
+
['xml-simple','>= 1.1.0']
|
16
|
+
]
|
17
|
+
|
18
|
+
self.remote_rdoc_dir = 'doc'
|
19
|
+
|
20
|
+
# switch extension to .rdoc for gihub formatting
|
21
|
+
self.readme_file = 'README.rdoc'
|
22
|
+
self.history_file = 'History.rdoc'
|
23
|
+
end
|
data/lib/ostructer.rb
ADDED
@@ -0,0 +1,353 @@
|
|
1
|
+
|
2
|
+
require 'forwardable'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module Ostructer
|
6
|
+
|
7
|
+
VERSION = '0.1'
|
8
|
+
|
9
|
+
## todo: use blank slate/basic object (no id? no type?)
|
10
|
+
#
|
11
|
+
# undef id and type (possible?)
|
12
|
+
# class OpenStruct
|
13
|
+
# undef id # deprecated in Ruby 1.8; removed in 1.9
|
14
|
+
# undef type # same thing
|
15
|
+
# end
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# folded elements (e.g. element with no attributes just content) get returned as string, thus,
|
20
|
+
#
|
21
|
+
# to_bool
|
22
|
+
# to_date
|
23
|
+
# to_xml will not be available!!!!! (unless added to String class)
|
24
|
+
#
|
25
|
+
# check if to_date exists? in ruby standard
|
26
|
+
|
27
|
+
#
|
28
|
+
# NB: key.first -> different with Rails or without (without results in more than one letter!!)
|
29
|
+
|
30
|
+
class OsBase # base for OsArray/OsOpenStruct/OsOpenStructNil
|
31
|
+
|
32
|
+
attr :logger # read-only
|
33
|
+
attr_accessor :parent # read,write
|
34
|
+
attr_accessor :field # read,write
|
35
|
+
|
36
|
+
def full_dot_path
|
37
|
+
path = "#{@field}"
|
38
|
+
node = @parent
|
39
|
+
|
40
|
+
## NOTE: assume if parent == nil openstruct is root node
|
41
|
+
while node && node.parent
|
42
|
+
# logger.debug "node.class: #{node.class}, node.field: #{node.field}"
|
43
|
+
if node.is_a?( OsArray )
|
44
|
+
path = "#{node.field}" + path
|
45
|
+
else
|
46
|
+
path = "#{node.field}." + path
|
47
|
+
end
|
48
|
+
node = node.parent
|
49
|
+
end
|
50
|
+
path
|
51
|
+
end
|
52
|
+
|
53
|
+
end # class OsBase
|
54
|
+
|
55
|
+
|
56
|
+
class OsValue < OsBase
|
57
|
+
|
58
|
+
# holds/wraps a string
|
59
|
+
|
60
|
+
def initialize( value, logger )
|
61
|
+
@value = value
|
62
|
+
@logger = logger
|
63
|
+
|
64
|
+
@parent = nil
|
65
|
+
@field ="[!unknown_value]"
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_openstruct_pass2
|
69
|
+
# do nothing (has no children)
|
70
|
+
end
|
71
|
+
|
72
|
+
include Comparable
|
73
|
+
|
74
|
+
def <=>(other)
|
75
|
+
if other.is_a? Numeric
|
76
|
+
logger.debug "OsValue <=> Numeric: #{self.to_i} <=> #{other}"
|
77
|
+
self.to_i <=> other
|
78
|
+
elsif other.is_a? String
|
79
|
+
logger.debug "OsValue <=> String: #{self.to_s} <=> #{other}"
|
80
|
+
self.to_s <=> other
|
81
|
+
else
|
82
|
+
logger.debug "OsValue - no <=> defined for type #{other.class}"
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
## todo: add bool
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
@value
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_i
|
94
|
+
@value.to_i
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_bool
|
98
|
+
@value == 'true'
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
end # class OsValue
|
103
|
+
|
104
|
+
|
105
|
+
class OsArray < OsBase
|
106
|
+
extend Forwardable
|
107
|
+
|
108
|
+
include Enumerable
|
109
|
+
|
110
|
+
def_delegators :@ary, :each, :[], :size
|
111
|
+
|
112
|
+
def initialize( ary, logger )
|
113
|
+
@ary = ary
|
114
|
+
@logger = logger
|
115
|
+
|
116
|
+
@parent = nil
|
117
|
+
@field = "[!unknown_array]"
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_openstruct_pass2
|
121
|
+
self.each_with_index do | el, index |
|
122
|
+
if el.is_a?( OsOpenStruct ) || el.is_a?( OsArray ) || el.is_a?( OsValue )
|
123
|
+
el.field = "[#{index}]"
|
124
|
+
el.parent = self
|
125
|
+
end
|
126
|
+
el.to_openstruct_pass2
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end # class OsArray
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
class OsOpenStructNil < OsBase
|
135
|
+
|
136
|
+
def initialize( parent, field, logger )
|
137
|
+
@parent = parent
|
138
|
+
@field = "!#{field}" # mark missing field with starting ! (exclamation mark)
|
139
|
+
@logger = logger
|
140
|
+
end
|
141
|
+
|
142
|
+
def nil?
|
143
|
+
logger.debug "calling OsNil#nil?"
|
144
|
+
true
|
145
|
+
end
|
146
|
+
|
147
|
+
def to_s
|
148
|
+
logger.debug "calling OsNil#to_s"
|
149
|
+
nil
|
150
|
+
end
|
151
|
+
|
152
|
+
def to_i
|
153
|
+
logger.debug "calling OsNil#to_i"
|
154
|
+
nil
|
155
|
+
end
|
156
|
+
|
157
|
+
def to_date
|
158
|
+
logger.debug "calling OsNil#to_date"
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
|
162
|
+
def to_bool
|
163
|
+
logger.debug "calling OsNil#to_bool"
|
164
|
+
nil
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def method_missing(mn,*a)
|
169
|
+
## NEW: added; add to org
|
170
|
+
mn = mn.to_s
|
171
|
+
|
172
|
+
logger.warn "OsOpenStructNil - feld '#{mn}' nicht gefunden using path '#{full_dot_path}'; returning OsOpenStructNil"
|
173
|
+
OsOpenStructNil.new( self, mn, logger )
|
174
|
+
end
|
175
|
+
|
176
|
+
end # end class OsOpenStructNil
|
177
|
+
|
178
|
+
|
179
|
+
|
180
|
+
class OsOpenStruct < OsBase
|
181
|
+
|
182
|
+
def initialize( hash_in, logger )
|
183
|
+
@parent = nil
|
184
|
+
@field = "[!unknown_hash]"
|
185
|
+
|
186
|
+
@logger = logger
|
187
|
+
@hash = {}
|
188
|
+
|
189
|
+
## fix: can we change the hash-in-place?? don't create a new one
|
190
|
+
|
191
|
+
# todo: add hook for normalize keys (downcase first letter, strip packages, etc.)
|
192
|
+
hash_in.each do |key,value|
|
193
|
+
# downcase first letter (e.g. Address to address)
|
194
|
+
key = key[0...1].downcase + key[1..-1]
|
195
|
+
|
196
|
+
@hash[ key ] = value
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_openstruct_pass2 # link up: set parent and field
|
201
|
+
@hash.each do |key,value|
|
202
|
+
if value.is_a?( OsOpenStruct ) || value.is_a?( OsArray ) || value.is_a?( OsValue )
|
203
|
+
value.field = key.to_s
|
204
|
+
value.parent = self
|
205
|
+
end
|
206
|
+
value.to_openstruct_pass2
|
207
|
+
end
|
208
|
+
# logger.debug "after MyOpenStruct#to_openstruct_pass2 parent=#{parent.nil? ? 'nil' : parent.object_id}, field=#{field}"
|
209
|
+
end
|
210
|
+
|
211
|
+
def has_key?( key )
|
212
|
+
# NOTE: use has_key? instead of nil? to avoid warnings in log that are expected if fields are missing
|
213
|
+
@hash.has_key?( key.to_s )
|
214
|
+
end
|
215
|
+
|
216
|
+
def fetch( key, default = nil )
|
217
|
+
@hash.fetch( key, default)
|
218
|
+
end
|
219
|
+
|
220
|
+
include Comparable
|
221
|
+
|
222
|
+
def <=>(other)
|
223
|
+
|
224
|
+
## fix: check if struct has short-cut value (e.g. text); short-cut value might not exist
|
225
|
+
## fix/todo: add bool
|
226
|
+
|
227
|
+
if other.is_a? Numeric
|
228
|
+
logger.debug "OsOpenStruct <=> Numeric: #{self.to_i} <=> #{other}"
|
229
|
+
self.to_i <=> other
|
230
|
+
elsif other.is_a? String
|
231
|
+
logger.debug "OsOpenStruct <=> String: #{self.to_s} <=> #{other}"
|
232
|
+
self.to_s <=> other
|
233
|
+
else
|
234
|
+
logger.debug "OsOpenStruct - no <=> defined for type #{other.class}"
|
235
|
+
nil
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def method_missing(mn,*a)
|
240
|
+
|
241
|
+
mn = mn.to_s
|
242
|
+
|
243
|
+
## convenience property for boolean check
|
244
|
+
if mn[-1].chr == "?"
|
245
|
+
mn = mn[0..-2] # cut of trailing ?
|
246
|
+
if @hash.has_key?(mn)
|
247
|
+
value = @hash.fetch( mn ).fetch( 'text' )
|
248
|
+
|
249
|
+
logger.debug "OsOpenStruct - boolean feld '#{mn}' with value '#{value}' returns #{value=='1'}"
|
250
|
+
|
251
|
+
return value == "1" # return
|
252
|
+
else
|
253
|
+
logger.warn "OsOpenStruct - boolean feld '#{mn}' nicht gefunden in Hash using path '#{full_dot_path}'; returning OsOpenStructNil"
|
254
|
+
OsOpenStructNil.new( self, mn+"?", logger ) # return
|
255
|
+
end
|
256
|
+
else
|
257
|
+
if @hash.has_key?(mn)
|
258
|
+
@hash[mn]
|
259
|
+
else
|
260
|
+
logger.warn "OsOpenStruct - feld '#{mn}' nicht gefunden in Hash using path '#{full_dot_path}'; returning OsOpenStructNil"
|
261
|
+
## pp self
|
262
|
+
OsOpenStructNil.new( self, mn, logger )
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
def to_xml
|
269
|
+
logger.debug "calling OsOpenStruct#to_xml"
|
270
|
+
## todo: check if CGI module is included
|
271
|
+
## todo: use another unescape method for xml entities??
|
272
|
+
CGI.unescapeHTML( internal_value )
|
273
|
+
end
|
274
|
+
|
275
|
+
def to_s
|
276
|
+
# puts "[DEBUG] calling OsOpenStruct#to_s"
|
277
|
+
value = internal_value
|
278
|
+
value.nil? ? nil : value.to_s
|
279
|
+
end
|
280
|
+
|
281
|
+
def to_i
|
282
|
+
# puts "[DEBUG] calling OsOpenStruct#to_i"
|
283
|
+
value = internal_value
|
284
|
+
value.nil? ? nil : value.to_i
|
285
|
+
end
|
286
|
+
|
287
|
+
def to_date
|
288
|
+
logger.debug "calling MyOpenStruct#to_date"
|
289
|
+
internal_value # format to date required for sqlite
|
290
|
+
end
|
291
|
+
|
292
|
+
def to_bool
|
293
|
+
## todo: how to handle no value exists? return false or nil?
|
294
|
+
# puts "[DEBUG] calling MyOpenStruct#to_bool"
|
295
|
+
internal_value == 'true'
|
296
|
+
end
|
297
|
+
|
298
|
+
private
|
299
|
+
def internal_value
|
300
|
+
if @hash.has_key?('text')
|
301
|
+
value = @hash.fetch( 'text' )
|
302
|
+
return value
|
303
|
+
else
|
304
|
+
logger.warn "feld 'text' nicht gefunden (called internal_value())"
|
305
|
+
return nil
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
end # class OsOpenStruct
|
310
|
+
|
311
|
+
|
312
|
+
end # module Ostructer
|
313
|
+
|
314
|
+
|
315
|
+
################################
|
316
|
+
##
|
317
|
+
## extensions to core/built-in classes (Object, Array, Hash)
|
318
|
+
##
|
319
|
+
|
320
|
+
class Object
|
321
|
+
def to_openstruct( logger )
|
322
|
+
|
323
|
+
# pass 1: construct data structure using new classes (OsArray, OsOpenStruct, OsValue)
|
324
|
+
# convert Array to OsArray
|
325
|
+
# convert Hash to OsOpenStruct
|
326
|
+
# convert String to OsValue
|
327
|
+
|
328
|
+
newself = self.to_openstruct_pass1( logger )
|
329
|
+
newself.to_openstruct_pass2 # pass 2: link up parents (reverse link)
|
330
|
+
newself
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
class String
|
335
|
+
def to_openstruct_pass1( logger )
|
336
|
+
Ostructer::OsValue.new( self, logger )
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
class Array
|
341
|
+
def to_openstruct_pass1( logger )
|
342
|
+
mapped = map{ |el| el.to_openstruct_pass1( logger ) }
|
343
|
+
Ostructer::OsArray.new( mapped, logger )
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
class Hash
|
348
|
+
def to_openstruct_pass1( logger )
|
349
|
+
mapped = {}
|
350
|
+
each{ |key,value | mapped[key.to_s] = value.to_openstruct_pass1( logger ) }
|
351
|
+
Ostructer::OsOpenStruct.new( mapped, logger )
|
352
|
+
end
|
353
|
+
end
|
data/test/test_config.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'logger'
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'xmlsimple'
|
7
|
+
|
8
|
+
# LIB_PATH = File.expand_path( File.dirname( 'lib' ) )
|
9
|
+
# $LOAD_PATH.unshift(LIB_PATH)
|
10
|
+
|
11
|
+
require 'lib/ostructer.rb'
|
12
|
+
|
13
|
+
## notes:
|
14
|
+
## add note about faster_xml_simple (drop-in replacement for xml_in only using libxml)
|
15
|
+
|
16
|
+
## todo: check if root is simple root if forceArray is true!!
|
17
|
+
|
18
|
+
# NB: ContentKey text only added if at least one attribute present!!
|
19
|
+
# otherwise value is used-as-is in place (not as a hash)
|
20
|
+
# use ForceContent => true options to force creation of hash
|
21
|
+
#
|
22
|
+
#
|
23
|
+
#
|
24
|
+
|
25
|
+
class TestConfig < Test::Unit::TestCase
|
26
|
+
|
27
|
+
def setup
|
28
|
+
fn = 'test/config.xml'
|
29
|
+
opts = { 'ContentKey' => 'text',
|
30
|
+
'ForceArray' => false,
|
31
|
+
'ForceContent' => true,
|
32
|
+
'KeepRoot' => true }
|
33
|
+
|
34
|
+
@doc = XmlSimple.xml_in( fn, opts )
|
35
|
+
|
36
|
+
# puts "=== xmlsimple:"
|
37
|
+
# pp @doc
|
38
|
+
|
39
|
+
logger = Logger.new(STDOUT)
|
40
|
+
logger.level = Logger::DEBUG
|
41
|
+
|
42
|
+
@doc = @doc.to_openstruct( logger )
|
43
|
+
|
44
|
+
## puts "=== ostructer:"
|
45
|
+
## pp @doc
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_readers
|
49
|
+
assert_equal( 'sahara', @doc.config.server[0].name.to_s ) # attribute
|
50
|
+
assert_equal( '10.0.0.101', @doc.config.server[0].address[0].text.to_s ) # contentKey
|
51
|
+
assert_equal( '10.0.0.101', @doc.config.server[0].address[0].to_s ) # contentKey shortcut (no .text)
|
52
|
+
assert( '.text shortcut String <=>', @doc.config.server[0].address[0] == '10.0.0.101' )
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_full_dot_path
|
56
|
+
assert_equal( 'config.logdir', @doc.config.logdir.full_dot_path )
|
57
|
+
assert_equal( 'config.server', @doc.config.server.full_dot_path )
|
58
|
+
assert_equal( 'config.server[0]', @doc.config.server[0].full_dot_path )
|
59
|
+
assert_equal( 'config.server[0].name', @doc.config.server[0].name.full_dot_path )
|
60
|
+
assert_equal( 'config.server[0].address', @doc.config.server[0].address.full_dot_path )
|
61
|
+
assert_equal( 'config.server[0].address[0]', @doc.config.server[0].address[0].full_dot_path )
|
62
|
+
assert_equal( 'config.server[0].address[0].text', @doc.config.server[0].address[0].text.full_dot_path )
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_missing
|
66
|
+
assert_equal( '!one.!two.!three', @doc.one.two.three.full_dot_path )
|
67
|
+
end
|
68
|
+
|
69
|
+
end # class TestConfig
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'logger'
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'xmlsimple'
|
7
|
+
|
8
|
+
# LIB_PATH = File.expand_path( File.dirname( 'lib' ) )
|
9
|
+
# $LOAD_PATH.unshift(LIB_PATH)
|
10
|
+
|
11
|
+
require 'lib/ostructer.rb'
|
12
|
+
|
13
|
+
## NB: XmlSimple -> ForceArray is true by default (turn it off!!)
|
14
|
+
##
|
15
|
+
|
16
|
+
class TestCustomer < Test::Unit::TestCase
|
17
|
+
|
18
|
+
def setup
|
19
|
+
fn = 'test/customer.xml'
|
20
|
+
opts = { 'ContentKey' => 'text',
|
21
|
+
'ForceArray' => false,
|
22
|
+
'ForceContent' => true }
|
23
|
+
|
24
|
+
@customer = XmlSimple.xml_in( fn, opts )
|
25
|
+
|
26
|
+
puts "=== xmlsimple:"
|
27
|
+
pp @customer
|
28
|
+
|
29
|
+
logger = Logger.new(STDOUT)
|
30
|
+
logger.level = Logger::DEBUG
|
31
|
+
|
32
|
+
@customer = @customer.to_openstruct( logger )
|
33
|
+
|
34
|
+
# puts "=== ostructer:"
|
35
|
+
# pp @customer
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_readers
|
39
|
+
assert_equal( 'home', @customer.address[0].typ.to_s ) # attribute
|
40
|
+
assert_equal( 'Joe', @customer.first_name.text.to_s )
|
41
|
+
assert_equal( 'Joe', @customer.first_name.to_s ) # short-cut (.text)
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
end # class TestCustomer
|
46
|
+
|
47
|
+
|
48
|
+
## from the XmlSimple docs
|
49
|
+
#
|
50
|
+
# Elements which only contain text content will simply be represented as a scalar.
|
51
|
+
# Where an element has both attributes and text content, the element will be represented
|
52
|
+
# as a hash with the text content in the 'content' key:
|
53
|
+
#
|
54
|
+
# <opt>
|
55
|
+
# <one>first</one>
|
56
|
+
# <two attr="value">second</two>
|
57
|
+
# </opt>
|
58
|
+
#
|
59
|
+
# {
|
60
|
+
# 'one' => 'first',
|
61
|
+
# 'two' => { 'attr' => 'value', 'content' => 'second' }
|
62
|
+
# }
|
63
|
+
#
|
data/test/test_misc.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'xmlsimple'
|
6
|
+
|
7
|
+
# LIB_PATH = File.expand_path( File.dirname( 'lib' ) )
|
8
|
+
# $LOAD_PATH.unshift(LIB_PATH)
|
9
|
+
|
10
|
+
require 'lib/ostructer.rb'
|
11
|
+
|
12
|
+
|
13
|
+
def test_keep_root
|
14
|
+
fn = 'test/config.xml'
|
15
|
+
opts = { 'ContentKey' => 'text',
|
16
|
+
'ForceArray' => false,
|
17
|
+
'ForceContent' => true,
|
18
|
+
'KeepRoot' => true }
|
19
|
+
|
20
|
+
doc = XmlSimple.xml_in( fn, opts )
|
21
|
+
|
22
|
+
puts "=== xmlsimple:"
|
23
|
+
pp doc
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_parse_status
|
27
|
+
fn = 'test/status.xml'
|
28
|
+
opts = { 'ContentKey' => 'text',
|
29
|
+
'ForceArray' => false }
|
30
|
+
|
31
|
+
statuses = XmlSimple.xml_in( fn, opts )
|
32
|
+
|
33
|
+
puts "=== xmlsimple:"
|
34
|
+
pp statuses
|
35
|
+
end
|
36
|
+
|
37
|
+
if __FILE__ == $0
|
38
|
+
# test_keep_root()
|
39
|
+
test_parse_status()
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ostructer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 9
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: "0.1"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Gerald Bauer
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-09-11 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: xml-simple
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 19
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
version: 1.1.0
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rubyforge
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 7
|
45
|
+
segments:
|
46
|
+
- 2
|
47
|
+
- 0
|
48
|
+
- 4
|
49
|
+
version: 2.0.4
|
50
|
+
type: :development
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: hoe
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 21
|
61
|
+
segments:
|
62
|
+
- 2
|
63
|
+
- 6
|
64
|
+
- 1
|
65
|
+
version: 2.6.1
|
66
|
+
type: :development
|
67
|
+
version_requirements: *id003
|
68
|
+
description: Lets you build open structs from nested hashes, arrays and strings.
|
69
|
+
email: gerald.bauer@gmail.com
|
70
|
+
executables: []
|
71
|
+
|
72
|
+
extensions: []
|
73
|
+
|
74
|
+
extra_rdoc_files:
|
75
|
+
- Manifest.txt
|
76
|
+
files:
|
77
|
+
- History.rdoc
|
78
|
+
- Manifest.txt
|
79
|
+
- README.rdoc
|
80
|
+
- Rakefile
|
81
|
+
- lib/ostructer.rb
|
82
|
+
- test/test_customer.rb
|
83
|
+
- test/test_config.rb
|
84
|
+
- test/test_misc.rb
|
85
|
+
has_rdoc: true
|
86
|
+
homepage: http://github.com/geraldb/ostructer
|
87
|
+
licenses: []
|
88
|
+
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options:
|
91
|
+
- --main
|
92
|
+
- README.rdoc
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
hash: 3
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
version: "0"
|
113
|
+
requirements: []
|
114
|
+
|
115
|
+
rubyforge_project: ostructer
|
116
|
+
rubygems_version: 1.3.7
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: Ostructer - Open Struct Builder
|
120
|
+
test_files:
|
121
|
+
- test/test_customer.rb
|
122
|
+
- test/test_config.rb
|
123
|
+
- test/test_misc.rb
|