rexle 0.9.14 → 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rexle.rb +108 -71
- metadata +2 -2
data/lib/rexle.rb
CHANGED
@@ -11,6 +11,8 @@ include REXML
|
|
11
11
|
|
12
12
|
|
13
13
|
# modifications:
|
14
|
+
# 21-Dec-2011: Bug fix: xpath modified to allow querying from the actual
|
15
|
+
# root rather than the 1st child element from the root
|
14
16
|
# 04-Sep-2011: Bug fix: xpath will now only return Rexle:elements when
|
15
17
|
# * is used.
|
16
18
|
# 03-Sep-2011: Implemented deep_clone as well as modifying clone to function
|
@@ -26,6 +28,7 @@ module XMLhelper
|
|
26
28
|
body = children.empty? ? self.root.value : scan_print(children).join
|
27
29
|
a = self.root.attributes.to_a.map{|k,v| "%s='%s'" % [k,v]}
|
28
30
|
"<%s%s>%s</%s>" % [self.root.name, a.empty? ? '' : ' ' + a.join(' '), body, self.root.name]
|
31
|
+
#"<%s%s>%s</%s>" % [self.root.name, a.empty? ? '' : ' ' + a.join(' '), body]
|
29
32
|
end
|
30
33
|
|
31
34
|
def doc_pretty_print(children)
|
@@ -39,9 +42,9 @@ module XMLhelper
|
|
39
42
|
def scan_print(nodes)
|
40
43
|
|
41
44
|
nodes.map do |x|
|
42
|
-
|
45
|
+
|
43
46
|
if x.is_a? Rexle::Element then
|
44
|
-
|
47
|
+
if x.name.chr != '!' then
|
45
48
|
a = x.attributes.to_a.map{|k,v| "%s='%s'" % [k,v]}
|
46
49
|
tag = x.name + (a.empty? ? '' : ' ' + a.join(' '))
|
47
50
|
|
@@ -49,8 +52,10 @@ module XMLhelper
|
|
49
52
|
out << x.value unless x.value.nil? || x.value.empty?
|
50
53
|
out << scan_print(x.children)
|
51
54
|
out << "</%s>" % x.name
|
52
|
-
|
53
|
-
|
55
|
+
elsif x.name == '!-' then
|
56
|
+
"<!--%s-->" % x.value
|
57
|
+
else
|
58
|
+
"<![CDATA[%s]]>" % x.value
|
54
59
|
end
|
55
60
|
elsif x.is_a? String then
|
56
61
|
x
|
@@ -91,7 +96,8 @@ class Rexle
|
|
91
96
|
include XMLhelper
|
92
97
|
|
93
98
|
attr_reader :prefixes
|
94
|
-
|
99
|
+
|
100
|
+
def self.version() "1.1.1" end
|
95
101
|
def initialize(x=nil)
|
96
102
|
super()
|
97
103
|
|
@@ -103,13 +109,13 @@ class Rexle
|
|
103
109
|
:"REXML::Document" => proc {|x| scan_doc x.root}
|
104
110
|
}
|
105
111
|
|
112
|
+
doc_node = ['doc','',{}]
|
106
113
|
@a = procs[x.class.to_s.to_sym].call(x)
|
107
|
-
@doc = scan_element(
|
114
|
+
@doc = scan_element(*(doc_node << @a))
|
108
115
|
|
109
116
|
# fetch the namespaces
|
110
117
|
@prefixes = []
|
111
118
|
if @doc.root.attributes then
|
112
|
-
#puts 'attrs : ' + @doc.root.attributes.inspect
|
113
119
|
xmlns = @doc.root.attributes.select {|k,v| k[/^xmlns:/]}
|
114
120
|
@prefixes = xmlns.keys.map{|x| x[/\w+$/]}
|
115
121
|
end
|
@@ -117,31 +123,9 @@ class Rexle
|
|
117
123
|
|
118
124
|
end
|
119
125
|
|
120
|
-
def xpath(path,
|
121
|
-
|
122
|
-
|
123
|
-
fn_match = path.match(/^(\w+)\(([^\)]+)\)$/)
|
124
|
-
|
125
|
-
# Array: proc {|x| x.flatten.compact},
|
126
|
-
if (fn_match and fn_match.captures.first[/^(attribute|@)/]) or fn_match.nil? then
|
127
|
-
procs = {
|
128
|
-
Array: proc {|x| block_given? ? x : x.flatten },
|
129
|
-
String: proc {|x| x},
|
130
|
-
:"Rexle::Element" => proc {|x| [x]}
|
131
|
-
}
|
132
|
-
bucket = []
|
133
|
-
result = @doc.xpath(path, bucket, &blk)
|
134
|
-
|
135
|
-
procs[result.class.to_s.to_sym].call(result)
|
136
|
-
|
137
|
-
else
|
138
|
-
#puts 'fn ' + fn_match.captures.inspect
|
139
|
-
m, xpath_value = fn_match.captures
|
140
|
-
method(m.to_sym).call(xpath_value)
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
end
|
126
|
+
def xpath(path, &blk)
|
127
|
+
@doc.xpath(path, &blk)
|
128
|
+
end
|
145
129
|
|
146
130
|
class Element
|
147
131
|
include XMLhelper
|
@@ -160,29 +144,74 @@ class Rexle
|
|
160
144
|
@child_lookup = []
|
161
145
|
end
|
162
146
|
|
147
|
+
def count(path)
|
148
|
+
length = query_xpath(path).flatten.compact.length
|
149
|
+
length
|
150
|
+
end
|
151
|
+
|
152
|
+
def max(path) query_xpath(path).flatten.compact.map(&:to_i).max end
|
153
|
+
|
163
154
|
def name()
|
164
|
-
|
165
|
-
#puts '@rexle : ' + @rexle.inspect
|
155
|
+
|
166
156
|
if @rexle then
|
167
157
|
prefix = @rexle.prefixes.find {|x| x == @name[/^(\w+):/,1] } if @rexle.prefixes.is_a? Array
|
168
|
-
#puts 'ppp: ' + prefix.inspect
|
169
158
|
prefix ? @name.sub(prefix + ':', '') : @name
|
170
159
|
else
|
171
160
|
@name
|
172
161
|
end
|
173
162
|
end
|
174
163
|
|
175
|
-
def xpath(
|
164
|
+
def xpath(path, rlist=[], &blk)
|
165
|
+
filter_xpath(path, rlist=[], &blk)
|
166
|
+
end
|
167
|
+
|
168
|
+
def filter_xpath(path, rlist=[], &blk)
|
169
|
+
|
170
|
+
# is it a function
|
171
|
+
fn_match = path.match(/^(\w+)\(([^\)]+)\)$/)
|
172
|
+
|
173
|
+
# Array: proc {|x| x.flatten.compact},
|
174
|
+
if (fn_match and fn_match.captures.first[/^(attribute|@)/]) or fn_match.nil? then
|
175
|
+
procs = {
|
176
|
+
Array: proc {|x| block_given? ? x : x.flatten },
|
177
|
+
String: proc {|x| x},
|
178
|
+
TrueClass: proc{|x| x},
|
179
|
+
FalseClass: proc{|x| x},
|
180
|
+
:"Rexle::Element" => proc {|x| [x]}
|
181
|
+
}
|
182
|
+
bucket = []
|
183
|
+
result = query_xpath(path, bucket, &blk)
|
184
|
+
procs[result.class.to_s.to_sym].call(result)
|
185
|
+
|
186
|
+
else
|
176
187
|
|
177
|
-
|
188
|
+
m, xpath_value = fn_match.captures
|
189
|
+
method(m.to_sym).call(xpath_value)
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
def query_xpath(raw_xpath_value, rlist=[], &blk)
|
195
|
+
|
196
|
+
#remove any pre'fixes
|
178
197
|
#@rexle.prefixes.each {|x| xpath_value.sub!(x + ':','') }
|
198
|
+
flag_func = false
|
199
|
+
|
200
|
+
xpath_value = raw_xpath_value.sub(/^\[/,'*[')
|
201
|
+
|
202
|
+
if xpath_value[/^[\w\/]+\s*=.*/] then
|
203
|
+
flag_func = true
|
204
|
+
xpath_value = raw_xpath_value.sub(/^\w+\s*=.*/,'.[\0]')
|
205
|
+
xpath_value = raw_xpath_value.sub(/\/([\w]+\s*=.*)/,'[\1]')
|
206
|
+
#result = self.element xpath_value
|
207
|
+
#return [(result.is_a?(Rexle::Element) ? true : false)]
|
208
|
+
end
|
179
209
|
|
180
|
-
xpath_value.sub!(/^\[/,'*[')
|
181
|
-
#xpath_value.sub!(/^attribute::/,'*/attribute::')
|
182
210
|
raw_path, raw_condition = xpath_value.sub(/^\/(?!\/)/,'').match(/([^\[]+)(\[[^\]]+\])?/).captures
|
183
211
|
|
184
212
|
remaining_path = ($').to_s
|
185
213
|
a_path = raw_path.split('/')
|
214
|
+
|
186
215
|
condition = raw_condition if a_path.length <= 1
|
187
216
|
|
188
217
|
if raw_path[0,2] == '//' then
|
@@ -196,15 +225,17 @@ class Rexle
|
|
196
225
|
return [@attributes[attribute.to_sym]] if attribute and @attributes and @attributes.has_key?(attribute.to_sym)
|
197
226
|
|
198
227
|
s = a_path.shift
|
228
|
+
|
199
229
|
end
|
200
230
|
|
201
231
|
# isolate the xpath to return just the path to the current element
|
202
232
|
elmnt_path = s[/^([\w\*]+\[[^\]]+\])|[\/]+{,2}[^\/]+/]
|
233
|
+
|
203
234
|
element_part = elmnt_path[/(^@?[^\[]+)?/,1] if elmnt_path
|
204
235
|
|
205
236
|
if element_part then
|
206
237
|
unless element_part[/^@/] then
|
207
|
-
element_name = element_part
|
238
|
+
element_name = element_part[/^[\w\*]+/]
|
208
239
|
else
|
209
240
|
condition = element_part
|
210
241
|
element_name = nil
|
@@ -212,27 +243,28 @@ class Rexle
|
|
212
243
|
|
213
244
|
end
|
214
245
|
|
215
|
-
#element_name ||= '*'
|
216
246
|
raw_condition = '' if condition
|
217
247
|
|
218
248
|
attr_search = format_condition(condition) if condition and condition.length > 0
|
219
|
-
|
249
|
+
|
250
|
+
return_elements = []
|
251
|
+
|
220
252
|
if raw_path[0,2] == '//'
|
221
253
|
rs = scan_match(self, xpath_value).flatten.compact
|
222
254
|
return rs
|
223
255
|
else
|
224
256
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
257
|
+
return_elements = @child_lookup.map.with_index.select do |x|
|
258
|
+
(x[0][0] == element_name || element_name == '.') or \
|
259
|
+
(element_name == '*' && x[0].is_a?(Array))
|
260
|
+
end
|
229
261
|
end
|
230
262
|
|
231
263
|
if return_elements.length > 0 then
|
232
264
|
|
233
265
|
if (a_path + [remaining_path]).join.empty? then
|
234
|
-
|
235
266
|
rlist = return_elements.map.with_index {|x,i| filter(x, i+1, attr_search, &blk)}.compact
|
267
|
+
|
236
268
|
rlist = rlist[0] if rlist.length == 1
|
237
269
|
else
|
238
270
|
|
@@ -253,6 +285,7 @@ class Rexle
|
|
253
285
|
rlist = rlist.flatten(1) unless rlist.length > 1 and rlist[0].is_a? Array
|
254
286
|
|
255
287
|
end
|
288
|
+
|
256
289
|
rlist.compact! if rlist.is_a? Array
|
257
290
|
|
258
291
|
else
|
@@ -264,9 +297,10 @@ class Rexle
|
|
264
297
|
self.xpath(new_xpath + raw_condition.to_s + remaining_path, rlist,&blk)
|
265
298
|
end
|
266
299
|
end
|
267
|
-
|
300
|
+
|
268
301
|
rlist = rlist.flatten(1) unless not(rlist.is_a? Array) or (rlist.length > 1 and rlist[0].is_a? Array)
|
269
302
|
rlist = [rlist] if rlist.is_a? Rexle::Element
|
303
|
+
rlist = (rlist.length > 0 ? true : false) if flag_func == true
|
270
304
|
rlist
|
271
305
|
end
|
272
306
|
|
@@ -314,7 +348,7 @@ class Rexle
|
|
314
348
|
def attributes() @attributes end
|
315
349
|
def children() @child_elements end
|
316
350
|
def children=(a) @child_elements = a end
|
317
|
-
def deep_clone() self.
|
351
|
+
def deep_clone() Rexle.new(self.xml).root end
|
318
352
|
def clone() Element.new(@name, @value, @attributes) end
|
319
353
|
|
320
354
|
def delete(obj=nil)
|
@@ -326,7 +360,10 @@ class Rexle
|
|
326
360
|
end
|
327
361
|
end
|
328
362
|
|
329
|
-
def element(s)
|
363
|
+
def element(s)
|
364
|
+
r = self.xpath(s)
|
365
|
+
r.is_a?(Array) ? r.first : r
|
366
|
+
end
|
330
367
|
|
331
368
|
def elements(s=nil)
|
332
369
|
procs = {
|
@@ -349,9 +386,8 @@ class Rexle
|
|
349
386
|
e = self.element(s)
|
350
387
|
result = e.value if e
|
351
388
|
end
|
389
|
+
result = CGI.unescape_html result.to_s
|
352
390
|
|
353
|
-
result = CGI.unescape_html result
|
354
|
-
|
355
391
|
def result.unescape()
|
356
392
|
s = self.clone
|
357
393
|
%w(< < > > & & &pos; ').each_slice(2){|x| s.gsub!(*x)}
|
@@ -388,7 +424,7 @@ class Rexle
|
|
388
424
|
private
|
389
425
|
|
390
426
|
def format_condition(condition)
|
391
|
-
|
427
|
+
|
392
428
|
raw_items = condition[1..-1].scan(/\'[^\']*\'|and|or|\d+|[!=<>]+|position\(\)|[@\w\.\/]+/)
|
393
429
|
|
394
430
|
if raw_items[0][/^\d+$/] then
|
@@ -411,7 +447,8 @@ class Rexle
|
|
411
447
|
x[1] = '==' if x[1] == '='
|
412
448
|
"h[:'%s'] %s %s" % x
|
413
449
|
else
|
414
|
-
|
450
|
+
|
451
|
+
x.join[/^(and|or)$/] ? x : ("h[:'%s']" % x)
|
415
452
|
end
|
416
453
|
end
|
417
454
|
|
@@ -422,6 +459,7 @@ class Rexle
|
|
422
459
|
items = cons_items.map do |x|
|
423
460
|
|
424
461
|
if x.length >= 3 then
|
462
|
+
|
425
463
|
x[1] = '==' if x[1] == '='
|
426
464
|
if x[0] != '.' then
|
427
465
|
if x[0][/\//] then
|
@@ -429,7 +467,7 @@ class Rexle
|
|
429
467
|
|
430
468
|
"e.xpath('#{path}').first.value == #{value}"
|
431
469
|
else
|
432
|
-
"(name == '%s' and value %s %s)" % [x[0], x[1], x[2]]
|
470
|
+
"(name == '%s' and value %s '%s')" % [x[0], x[1], x[2].sub(/^['"](.*)['"]$/,'\1')]
|
433
471
|
end
|
434
472
|
else
|
435
473
|
"e.value %s %s" % [x[1], x[2]]
|
@@ -438,7 +476,7 @@ class Rexle
|
|
438
476
|
x
|
439
477
|
end
|
440
478
|
end
|
441
|
-
|
479
|
+
|
442
480
|
return items.join(' ')
|
443
481
|
end
|
444
482
|
end
|
@@ -451,17 +489,19 @@ class Rexle
|
|
451
489
|
|
452
490
|
r = node.xpath(xpath[2..-1])
|
453
491
|
r << node.children.map {|n| scan_match(n, xpath) if n.is_a? Rexle::Element}
|
454
|
-
|
492
|
+
|
455
493
|
r
|
456
494
|
end
|
457
495
|
|
458
496
|
def filter(raw_element, i, attr_search, &blk)
|
459
497
|
|
460
498
|
x = raw_element
|
461
|
-
e = @child_elements[x.last]
|
462
499
|
|
500
|
+
e = @child_elements[x.last]
|
501
|
+
name, value = e.name, e.value if e.is_a? Rexle::Element
|
463
502
|
h = x[0][1] # <-- fetch the attributes
|
464
503
|
|
504
|
+
|
465
505
|
if attr_search then
|
466
506
|
if attr_search.is_a? Fixnum then
|
467
507
|
block_given? ? blk.call(e) : e if i == attr_search
|
@@ -469,11 +509,15 @@ class Rexle
|
|
469
509
|
block_given? ? blk.call(e) : e
|
470
510
|
elsif h and attr_search[/^h\[/] and eval(attr_search)
|
471
511
|
block_given? ? blk.call(e) : e
|
472
|
-
elsif attr_search[/^\(name ==/] and
|
512
|
+
elsif attr_search[/^\(name ==/] and e.child_lookup.select{|name, attributes, value| eval(attr_search) }.length > 0
|
513
|
+
|
473
514
|
block_given? ? blk.call(e) : e
|
515
|
+
elsif attr_search[/^\(name ==/] and eval(attr_search)
|
516
|
+
block_given? ? blk.call(e) : e
|
474
517
|
elsif attr_search[/^e\.value/] and eval(attr_search)
|
475
518
|
block_given? ? blk.call(e) : e
|
476
519
|
elsif attr_search[/^e\.xpath/] and eval(attr_search)
|
520
|
+
|
477
521
|
block_given? ? blk.call(e) : e
|
478
522
|
end
|
479
523
|
else
|
@@ -511,8 +555,9 @@ class Rexle
|
|
511
555
|
else
|
512
556
|
a = yield
|
513
557
|
end
|
514
|
-
|
515
|
-
@
|
558
|
+
doc_node = ['doc','',{}]
|
559
|
+
@a = procs[x.class.to_s.to_sym].call(x)
|
560
|
+
@doc = scan_element(*(doc_node << @a))
|
516
561
|
self
|
517
562
|
end
|
518
563
|
|
@@ -535,7 +580,7 @@ class Rexle
|
|
535
580
|
def to_a() @a end
|
536
581
|
def to_s(options={}) self.xml options end
|
537
582
|
def text(xpath) @doc.text(xpath) end
|
538
|
-
def root() @doc end
|
583
|
+
def root() @doc.children.first end
|
539
584
|
|
540
585
|
def write(f)
|
541
586
|
f.write xml
|
@@ -576,7 +621,7 @@ class Rexle
|
|
576
621
|
end
|
577
622
|
|
578
623
|
def scan_element(name, value=nil, attributes=nil, *children)
|
579
|
-
|
624
|
+
|
580
625
|
element = Element.new(name, value, attributes, self)
|
581
626
|
|
582
627
|
if children then
|
@@ -591,14 +636,6 @@ class Rexle
|
|
591
636
|
return element
|
592
637
|
end
|
593
638
|
|
594
|
-
def count(path)
|
595
|
-
#puts 'path : ' + path
|
596
|
-
length = @doc.xpath(path).flatten.compact.length
|
597
|
-
#puts 'length = ' + length
|
598
|
-
length
|
599
|
-
end
|
600
|
-
|
601
|
-
def max(path) @doc.xpath(path).flatten.compact.map(&:to_i).max end
|
602
639
|
|
603
640
|
# scan a rexml doc
|
604
641
|
#
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: rexle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.9.
|
5
|
+
version: 0.9.15
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- James Robertson
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-12-
|
13
|
+
date: 2011-12-21 00:00:00 +00:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|