axml 0.0.3 → 0.0.4
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/README +34 -38
- data/Rakefile +19 -61
- data/lib/axml.rb +30 -367
- data/lib/axml/autoload.rb +106 -0
- data/lib/axml/el.rb +208 -0
- data/lib/axml/libxml.rb +110 -0
- data/lib/axml/traverse.rb +15 -0
- data/lib/axml/xmlparser.rb +114 -0
- data/spec/axml/autoload_spec.rb +18 -0
- data/spec/axml/libxml_spec.rb +13 -0
- data/spec/axml/xmlparser_spec.rb +16 -0
- data/spec/axml_spec.rb +299 -0
- metadata +18 -9
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
require 'axml/autoload'
|
4
|
+
|
5
|
+
class AXMLAutoload < MiniTest::Spec
|
6
|
+
|
7
|
+
it 'gives install instructions' do
|
8
|
+
yoshi = 'yoshidam'
|
9
|
+
rf = 'rubyforge.org'
|
10
|
+
{:xmlparser => [yoshi], :libxml => [rf], :all => [rf, yoshi] }.each do |key,val|
|
11
|
+
val.each do |st|
|
12
|
+
AXML::Autoload.install_instructions(key).include?(st).must_equal true
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../axml_spec'
|
2
|
+
|
3
|
+
|
4
|
+
class XMLParserBased < MiniTest::Spec
|
5
|
+
include GenericAXMLBehaviorSpec
|
6
|
+
include IndexBehaviorSpec
|
7
|
+
include ValuesAtBehaviorSpec
|
8
|
+
|
9
|
+
before do
|
10
|
+
super
|
11
|
+
@parser = :xmlparser
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
|
data/spec/axml_spec.rb
ADDED
@@ -0,0 +1,299 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper.rb"
|
2
|
+
|
3
|
+
require 'minitest/spec'
|
4
|
+
require 'axml'
|
5
|
+
|
6
|
+
module GenericAXMLBehaviorSpec
|
7
|
+
extend Shareable
|
8
|
+
|
9
|
+
before do
|
10
|
+
|
11
|
+
@class = nil # <- specify your class!
|
12
|
+
|
13
|
+
@xml_string = <<END
|
14
|
+
<xml>
|
15
|
+
<doc1>
|
16
|
+
<dog name="spot" height="23" weight="13">
|
17
|
+
<flea name="ouchy" height="20" weight="10"/>
|
18
|
+
<flea name="crawly" height="22" weight="9"/>
|
19
|
+
</dog>
|
20
|
+
</doc1>
|
21
|
+
<doc2>
|
22
|
+
<dog name="billy" height="5" weight="3">
|
23
|
+
</dog>
|
24
|
+
</doc2>
|
25
|
+
</xml>
|
26
|
+
END
|
27
|
+
@small_xml_string = <<END
|
28
|
+
<first>
|
29
|
+
<inner1 name="hello">
|
30
|
+
</inner1>
|
31
|
+
<inner2>
|
32
|
+
</inner2>
|
33
|
+
</first>
|
34
|
+
END
|
35
|
+
@xml_large_string = <<END
|
36
|
+
<n1>
|
37
|
+
<n2 id='1'>
|
38
|
+
<n3 id='1'> </n3>
|
39
|
+
<n3 id='2'> </n3>
|
40
|
+
<n3b id='5'></n3b>
|
41
|
+
<n3b id='6'></n3b>
|
42
|
+
</n2>
|
43
|
+
<n2 id='2'>
|
44
|
+
<n3 id='3'> </n3>
|
45
|
+
<n3 id='4'> </n3>
|
46
|
+
</n2>
|
47
|
+
</n1>
|
48
|
+
END
|
49
|
+
@xml_with_text = <<END
|
50
|
+
<n1>
|
51
|
+
<n2>doc1_text</n2>
|
52
|
+
<n3>doc2_text<n4>doc3_text</n4></n3>
|
53
|
+
<n5>Bill'y' "Wrangler" Jones</n5>
|
54
|
+
<n6 class="8 < and 6 >" id="27&22"/>
|
55
|
+
<n7>love & roses</n7>
|
56
|
+
</n1>
|
57
|
+
END
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'can return a parser' do # <- very rough spec
|
61
|
+
AXML::Autoload.parser('crazy').must_be_nil
|
62
|
+
AXML::Autoload.parser(@parser).wont_be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'reads xml strings' do
|
66
|
+
node = AXML.parse(@small_xml_string, :parser => @parser)
|
67
|
+
|
68
|
+
#node.class.must_equal AXML::El
|
69
|
+
node.name.must_equal 'first'
|
70
|
+
|
71
|
+
node.children.first.name.must_equal 'inner1'
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'reads IO objects' do
|
75
|
+
file = File.dirname(__FILE__) + '/axml.tmp'
|
76
|
+
File.open(file, 'w') {|io| io.puts @xml_string}
|
77
|
+
root = File.open(file) do |io|
|
78
|
+
AXML.parse(io, :parser => @parser)
|
79
|
+
end
|
80
|
+
root.name.must_equal 'xml'
|
81
|
+
root.kids[0].kids.first.attrs["name"].must_equal 'spot'
|
82
|
+
File.unlink(file) if File.exist? file
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'reads files' do
|
86
|
+
file = File.dirname(__FILE__) + '/axml.tmp'
|
87
|
+
File.open(file, 'w') {|fh| fh.puts @xml_string}
|
88
|
+
root = AXML.parse(file, :parser => @parser)
|
89
|
+
root.name.must_equal 'xml'
|
90
|
+
root.kids[0].kids.first.attrs["name"].must_equal 'spot'
|
91
|
+
File.unlink(file) if File.exist? file
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'can access subnodes with "children" or "kids"' do
|
95
|
+
node = AXML.parse(@small_xml_string, :parser => @parser)
|
96
|
+
node.name.must_equal 'first'
|
97
|
+
node.kids.zip(%w(inner1 inner2)) do |kd,nm|
|
98
|
+
kd.name.must_equal nm
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'accesses attributes with "[]"' do
|
103
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
104
|
+
dog_node = root.kids[0].kids[0]
|
105
|
+
dog_node.name.must_equal 'dog'
|
106
|
+
dog_node['name'].must_equal 'spot'
|
107
|
+
dog_node['height'].must_equal '23'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'can "find_first_descendant"' do
|
111
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
112
|
+
doc1_node = root.find_first_descendant('doc1')
|
113
|
+
doc1_node.name.must_equal 'doc1'
|
114
|
+
doc1_node.children.size.must_equal 1
|
115
|
+
doc1_node.find_first_descendant('xml').must_equal nil
|
116
|
+
doc1_node.find_first_descendant('doc1').must_equal nil
|
117
|
+
child_node = root.find_first_descendant('flea')
|
118
|
+
child_node.name.must_equal 'flea'
|
119
|
+
child_node['name'].must_equal 'ouchy'
|
120
|
+
child_node.find_first_descendant('flea').must_equal nil
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'can "find_first_child"' do
|
124
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
125
|
+
doc1_node = root.find_first_child('doc1')
|
126
|
+
doc1_node.name.must_equal 'doc1'
|
127
|
+
doc1_node.children.size.must_equal 1
|
128
|
+
doc1_node.find_first_child('xml').must_equal nil
|
129
|
+
doc1_node.find_first_child('doc1').must_equal nil
|
130
|
+
dog_node = doc1_node.find_first_child('dog')
|
131
|
+
dog_node.name.must_equal 'dog'
|
132
|
+
dog_node['name'].must_equal 'spot'
|
133
|
+
doc2_node = root.find_first_child('doc2')
|
134
|
+
doc2_node.name.must_equal 'doc2'
|
135
|
+
doc2_node.children.size.must_equal 1
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'can do some find_first xpath' do
|
139
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
140
|
+
flea_node = root.find_first('descendant::flea')
|
141
|
+
flea_node.name.must_equal 'flea'
|
142
|
+
flea_node['name'].must_equal 'ouchy'
|
143
|
+
root.find_first('child::flea').must_be_nil
|
144
|
+
#root.find_first('child::doc2').name.must_equal 'doc2'
|
145
|
+
root.find_first('child::doc2').name.must_equal 'doc2'
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'can drop nodes with "drop"' do
|
149
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
150
|
+
root.find_first_descendant("dog").wont_be_nil
|
151
|
+
root.child.name.must_equal "doc1"
|
152
|
+
doc2 = root.child.next
|
153
|
+
doc2.name.must_equal "doc2"
|
154
|
+
doc2.child.name.must_equal "dog"
|
155
|
+
doc2.child['height'].must_equal "5"
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'can return "child" node' do
|
159
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
160
|
+
doc1 = root.child
|
161
|
+
doc1.name.must_equal 'doc1'
|
162
|
+
dog = doc1.child
|
163
|
+
dog.name.must_equal 'dog'
|
164
|
+
dog['name'].must_equal 'spot'
|
165
|
+
flea = dog.child
|
166
|
+
flea.name.must_equal 'flea'
|
167
|
+
flea['name'].must_equal 'ouchy'
|
168
|
+
flea.child.must_equal nil
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'can return "next" node' do
|
172
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
173
|
+
root.next.must_equal nil
|
174
|
+
doc1 = root.child
|
175
|
+
doc2 = doc1.next
|
176
|
+
doc2.name.must_equal 'doc2'
|
177
|
+
doc2.next.must_equal nil
|
178
|
+
dog = doc1.child
|
179
|
+
dog.name.must_equal 'dog'
|
180
|
+
dog.next.must_equal nil
|
181
|
+
flea2 = dog.child.next
|
182
|
+
flea2.name.must_equal 'flea'
|
183
|
+
flea2['name'].must_equal 'crawly'
|
184
|
+
flea2.next.must_equal nil
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'can find "following-sibling"' do
|
188
|
+
n1 = AXML.parse(@xml_large_string, :parser => @parser)
|
189
|
+
n3 = n1.child.child
|
190
|
+
n3.name.must_equal 'n3'
|
191
|
+
n3id2 = n3.find_first("following-sibling::n3")
|
192
|
+
n3id2['id'].must_equal '2'
|
193
|
+
n3b = n3.find_first("following-sibling::n3b")
|
194
|
+
n3b['id'].must_equal '5'
|
195
|
+
n3b.find_first("following-sibling::n3").must_equal nil
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'knows if it has text' do
|
199
|
+
n1 = AXML.parse(@xml_with_text, :parser => @parser)
|
200
|
+
n5 = n1.find_first_child("n5")
|
201
|
+
n5.text?.must_equal true
|
202
|
+
n1.text?.must_equal false
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
it 'gets text from nodes' do
|
207
|
+
xml = '<n1><n2>this is the text</n2></n1>'
|
208
|
+
root = AXML.parse(xml, :parser => @parser)
|
209
|
+
root.child.text.must_equal 'this is the text'
|
210
|
+
root.child.content.must_equal 'this is the text'
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'does full node traversal' do
|
214
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
215
|
+
names = []
|
216
|
+
root.traverse do |node|
|
217
|
+
names << node.name
|
218
|
+
end
|
219
|
+
names.must_equal ["xml", "doc1", "dog", "flea", "flea", "doc2", "dog"]
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'can "find" with a little xpath' do
|
223
|
+
root = AXML.parse(@xml_large_string, :parser => @parser)
|
224
|
+
nodes = root.find('child::n2')
|
225
|
+
nodes.size.must_equal 2
|
226
|
+
nodes.each {|v| v.name.must_equal 'n2' }
|
227
|
+
nodes.each_with_index {|v,i| v['id'].must_equal( (i+1).to_s ) }
|
228
|
+
|
229
|
+
nodes = root.find('descendant::n3')
|
230
|
+
nodes.size.must_equal 4
|
231
|
+
nodes.each {|v| v.name.must_equal 'n3' }
|
232
|
+
nodes.each_with_index {|v,i| v['id'].must_equal( (i+1).to_s )}
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
module IndexBehaviorSpec
|
239
|
+
extend Shareable
|
240
|
+
|
241
|
+
it 'can retrieve text indices for a select node' do
|
242
|
+
root = AXML.parse(@xml_with_text, :text_indices => 'n2', :parser => @parser)
|
243
|
+
root.child.text.must_equal [11,9] # only the specified node affected
|
244
|
+
root.find_first_child("n7").text.must_equal "love & roses"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
module OutputBehaviorSpec
|
249
|
+
extend Shareable
|
250
|
+
|
251
|
+
it '"to_s" gives xml' do
|
252
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
253
|
+
to_string = <<END
|
254
|
+
<xml>
|
255
|
+
<doc1>
|
256
|
+
<dog name="spot" weight="13" height="23">
|
257
|
+
<flea name="ouchy" weight="10" height="20"/>
|
258
|
+
<flea name="crawly" weight="9" height="22"/>
|
259
|
+
</dog>
|
260
|
+
</doc1>
|
261
|
+
<doc2>
|
262
|
+
<dog name="billy" weight="3" height="5"/>
|
263
|
+
</doc2>
|
264
|
+
</xml>
|
265
|
+
END
|
266
|
+
root.to_s.must_equal to_string
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'escapes element text in to_s output' do
|
270
|
+
n1 = AXML.parse(@xml_with_text, :parser => @parser)
|
271
|
+
n5 = n1.find_first_child("n5")
|
272
|
+
xml = <<END
|
273
|
+
<n1>
|
274
|
+
<n2>doc1_text</n2>
|
275
|
+
<n3>doc2_text
|
276
|
+
<n4>doc3_text</n4>
|
277
|
+
</n3>
|
278
|
+
<n5>Bill'y' "Wrangler" Jones</n5>
|
279
|
+
<n6 class="8 < and 6 >" id="27&22"/>
|
280
|
+
<n7>love & roses</n7>
|
281
|
+
</n1>
|
282
|
+
END
|
283
|
+
n1.to_s.must_equal xml
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
module ValuesAtBehaviorSpec
|
289
|
+
extend Shareable
|
290
|
+
|
291
|
+
it 'can get many attributes at once with values_at (not supported by libxml)' do
|
292
|
+
root = AXML.parse(@xml_string, :parser => @parser)
|
293
|
+
dog = root.child.child.child
|
294
|
+
exp = %w(ouchy 20 10)
|
295
|
+
reply = dog.attrs.values_at('name', 'height', 'weight')
|
296
|
+
reply.must_equal exp
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: axml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Prince
|
@@ -9,12 +9,12 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-02-23 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
16
|
description:
|
17
|
-
email:
|
17
|
+
email: jtprince@gmail.com
|
18
18
|
executables: []
|
19
19
|
|
20
20
|
extensions: []
|
@@ -23,12 +23,18 @@ extra_rdoc_files:
|
|
23
23
|
- README
|
24
24
|
- LICENSE
|
25
25
|
files:
|
26
|
+
- lib/axml
|
27
|
+
- lib/axml/el.rb
|
28
|
+
- lib/axml/autoload.rb
|
29
|
+
- lib/axml/libxml.rb
|
30
|
+
- lib/axml/xmlparser.rb
|
31
|
+
- lib/axml/traverse.rb
|
26
32
|
- lib/axml.rb
|
27
33
|
- README
|
28
34
|
- LICENSE
|
29
35
|
- Rakefile
|
30
36
|
has_rdoc: true
|
31
|
-
homepage:
|
37
|
+
homepage: http://axml.rubyforge.org/
|
32
38
|
post_install_message:
|
33
39
|
rdoc_options:
|
34
40
|
- --main
|
@@ -50,11 +56,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
56
|
version: "0"
|
51
57
|
version:
|
52
58
|
requirements:
|
53
|
-
- xmlparser
|
54
|
-
rubyforge_project:
|
59
|
+
- xmlparser or libxml
|
60
|
+
rubyforge_project: axml
|
55
61
|
rubygems_version: 1.3.1
|
56
62
|
signing_key:
|
57
63
|
specification_version: 2
|
58
|
-
summary: AXML - Provides a simple DOM for working with XML
|
59
|
-
test_files:
|
60
|
-
|
64
|
+
summary: "AXML - Provides a simple, minimalistic DOM for working with data stored in an XML document. The API is very similar to LibXML, differing slightly in the handling of text nodes. It is designed with very large documents in mind: nodes are represented in memory efficient Struct objects and it works with either XMLParser or LibXML!"
|
65
|
+
test_files:
|
66
|
+
- spec/axml/xmlparser_spec.rb
|
67
|
+
- spec/axml/autoload_spec.rb
|
68
|
+
- spec/axml/libxml_spec.rb
|
69
|
+
- spec/axml_spec.rb
|