rexle 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/rexle.rb +121 -330
  2. metadata +18 -5
data/lib/rexle.rb CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/ruby
2
2
 
3
3
  # file: rexle.rb
4
4
 
@@ -6,48 +6,21 @@ require 'rexml/document'
6
6
  require 'rexleparser'
7
7
  require 'dynarex-parser'
8
8
  require 'polyrex-parser'
9
- require 'cgi'
10
9
  include REXML
11
10
 
12
- # modifications:
13
- # 20-Oct-2012: feature: added Rexle::Element#texts which is the equivalent
14
- # of REXML::Element#texts
15
- # 10-Sep-2012: bug fix: Removed code from method pretty_print in order to
16
- # get the XML displayed properly
17
- # 23-Aug-2012: feature: implemented xpath function contains()
18
- # 17-Aug-2012: bug fix: pretty print now ignores text containing empty space
19
- # 16-Aug-2012: the current element's text (if its not empty) is now returned
20
- # from its children method
21
- # 15-Aug-2012: feature: xpath containing child:: now supported
22
- # 13-Aug-2012: bug fix: xpath can now handle the name() function
23
- # 11-Aug-2012: bug fix: separated the max() method from 1 line into 3
24
- # and that fixed it
25
- # 08-Aug-2012: feature: added Element#insert_before and Element#insert_after
26
- # 19-Jul-2012: Changed children to elements where appropriate
27
- # 15-Jul-2012: bug fix: self.root.value is no longer appended
28
- # to the body if there are no child elements
29
- # 19-Jun-2012: a bug fix for .//*[@class]
30
- # 17-Jun-2012: a couple of new xpath things are supported '.' and '|'
31
- # 15-Apr-2012: bug fix: New element names are typecast as string
32
- # 16-Mar-2012: bug fix: Element names which contain a colon can now be selected
33
- # in the xpath.
34
- # 22-Feb-2012: bug resolution: Deactivated the PolyrexParser; using RexleParser instead
35
- # 14-Jan-2012: Implemented Rexle::Elements#each
36
- # 21-Dec-2011: Bug fix: xpath modified to allow querying from the actual
37
- # root rather than the 1st child element from the root
38
11
 
39
12
  module XMLhelper
40
13
 
41
14
  def doc_print(children)
42
-
43
- body = (children.nil? or children.empty? or children.is_an_empty_string? ) ? '' : scan_print(children).join
15
+
16
+ body = children.empty? ? self.root.value : scan_print(children).join
44
17
  a = self.root.attributes.to_a.map{|k,v| "%s='%s'" % [k,v]}
45
18
  "<%s%s>%s</%s>" % [self.root.name, a.empty? ? '' : ' ' + a.join(' '), body, self.root.name]
46
19
  end
47
20
 
48
21
  def doc_pretty_print(children)
49
22
 
50
- body = pretty_print(children,2).join
23
+ body = children.empty? ? self.value : pretty_print(children,2).join
51
24
  a = self.root.attributes.to_a.map{|k,v| "%s='%s'" % [k,v]}
52
25
  ind = "\n "
53
26
  "<%s%s>%s%s%s</%s>" % [self.root.name, a.empty? ? '' : ' ' + a.join(' '), ind, body, "\n", self.root.name]
@@ -56,24 +29,18 @@ module XMLhelper
56
29
  def scan_print(nodes)
57
30
 
58
31
  nodes.map do |x|
59
-
32
+ #puts 'x: ' + x.class.to_s #+ ' name: ' + x.name.to_s
60
33
  if x.is_a? Rexle::Element then
61
- if x.name.chr != '!' then
34
+ unless x.name == '![' then
62
35
  a = x.attributes.to_a.map{|k,v| "%s='%s'" % [k,v]}
63
36
  tag = x.name + (a.empty? ? '' : ' ' + a.join(' '))
64
37
 
65
- if x.value.length > 0 or (x.children.length > 0 and not x.children.is_an_empty_string?) then
66
- out = ["<%s>" % tag]
67
- #out << x.value unless x.value.nil? || x.value.empty?
68
- out << scan_print(x.children)
69
- out << "</%s>" % x.name
70
- else
71
- out = ["<%s/>" % tag]
72
- end
73
- elsif x.name == '!-' then
74
- "<!--%s-->" % x.value
75
- else
76
- "<![CDATA[%s]]>" % x.value
38
+ out = ["<%s>" % tag]
39
+ out << x.value unless x.value.nil? || x.value.empty?
40
+ out << scan_print(x.children)
41
+ out << "</%s>" % x.name
42
+ else
43
+ "<![CDATA[%s]]>" % x.value
77
44
  end
78
45
  elsif x.is_a? String then
79
46
  x
@@ -84,24 +51,19 @@ module XMLhelper
84
51
 
85
52
  def pretty_print(nodes, indent='0')
86
53
  indent = indent.to_i
87
-
88
- nodes.select(){|x| x.is_a? Rexle::Element or x.strip.length > 0}
89
- .map.with_index do |x, i|
90
-
54
+ nodes.map.with_index do |x, i|
91
55
  if x.is_a? Rexle::Element then
92
56
  unless x.name == '![' then
93
- #return ["<%s/>" % x.name] if x.value = ''
94
57
  a = x.attributes.to_a.map{|k,v| "%s='%s'" % [k,v]}
95
- a ||= []
96
58
  tag = x.name + (a.empty? ? '' : ' ' + a.join(' '))
97
59
 
98
- start = i > 0 ? ("\n" + ' ' * (indent - 1)) : ''
99
- ind1 = x.children.grep(Rexle::Element).length > 0 ?
100
- ("\n" + ' ' * indent) : ''
60
+ ind1 = x.children.length > 0 ? ("\n" + ' ' * indent) : ''
61
+ start = i > 0 ? ("\n" + ' ' * (indent - 1)) : ''
101
62
  out = ["%s<%s>%s" % [start, tag, ind1]]
102
63
 
64
+ out << x.value.sub(/^[\n\s]+$/,'') unless x.value.nil? || x.value.empty?
103
65
  out << pretty_print(x.children, (indent + 1).to_s.clone)
104
- ind2 = ind1.length > 0 ? ("\n" + ' ' * (indent - 1)) : ''
66
+ ind2 = x.children.length > 0 ? ("\n" + ' ' * (indent - 1)) : ''
105
67
  out << "%s</%s>" % [ind2, x.name]
106
68
  else
107
69
  "<![CDATA[%s]]>" % x.value
@@ -119,10 +81,6 @@ class Rexle
119
81
  include XMLhelper
120
82
 
121
83
  attr_reader :prefixes
122
-
123
- def self.version()
124
- '0.9.xx'
125
- end
126
84
 
127
85
  def initialize(x=nil)
128
86
  super()
@@ -134,144 +92,85 @@ class Rexle
134
92
  Array: proc {|x| x},
135
93
  :"REXML::Document" => proc {|x| scan_doc x.root}
136
94
  }
137
-
138
- doc_node = ['doc','',{}]
139
-
140
95
 
141
96
  @a = procs[x.class.to_s.to_sym].call(x)
142
- @doc = scan_element(*(doc_node << @a))
97
+ @doc = scan_element(*@a)
143
98
 
144
99
  # fetch the namespaces
145
100
  @prefixes = []
146
101
  if @doc.root.attributes then
147
-
102
+ #puts 'attrs : ' + @doc.root.attributes.inspect
148
103
  xmlns = @doc.root.attributes.select {|k,v| k[/^xmlns:/]}
149
104
  @prefixes = xmlns.keys.map{|x| x[/\w+$/]}
150
105
  end
106
+ end
107
+
108
+ end
109
+
110
+ def xpath(path, &blk)
111
+
112
+ # is it a function
113
+ fn_match = path.match(/^(\w+)\(([^\)]+)\)$/)
151
114
 
115
+ # Array: proc {|x| x.flatten.compact},
116
+ if (fn_match and fn_match.captures.first[/^(attribute|@)/]) or fn_match.nil? then
117
+ procs = {
118
+ Array: proc {|x| block_given? ? x : x.flatten },
119
+ String: proc {|x| x},
120
+ :"Rexle::Element" => proc {|x| [x]}
121
+ }
122
+ bucket = []
123
+ result = @doc.xpath(path, bucket, &blk)
124
+
125
+ procs[result.class.to_s.to_sym].call(result)
126
+
127
+ else
128
+ #puts 'fn ' + fn_match.captures.inspect
129
+ m, xpath_value = fn_match.captures
130
+ method(m.to_sym).call(xpath_value)
152
131
  end
153
132
 
133
+
154
134
  end
155
-
156
- def xpath(path, &blk)
157
- @doc.xpath(path, &blk)
158
- end
159
135
 
160
136
  class Element
161
137
  include XMLhelper
162
138
 
163
139
  attr_accessor :name, :value, :parent
164
- attr_reader :child_lookup, :child_elements
165
-
166
- alias original_clone clone
140
+ attr_reader :child_lookup
167
141
 
168
142
  def initialize(name=nil, value='', attributes={}, rexle=nil)
169
143
  @rexle = rexle
170
144
  super()
171
- @name, @value, @attributes = name.to_s, value, attributes
145
+ @name, @value, @attributes = name, value, attributes
172
146
  raise "Element name must not be blank" unless name
173
147
  @child_elements = []
174
148
  @child_lookup = []
175
149
  end
176
150
 
177
- def contains(raw_args)
178
- path, raw_val = raw_args.split(',',2)
179
- val = raw_val.strip[/^["']?.*["']?$/]
180
-
181
- anode = query_xpath(path)
182
- return unless anode
183
- a = scan_contents(anode.first)
184
-
185
- [a.grep(/#{val}/).length > 0]
186
- end
187
-
188
- def count(path)
189
- length = query_xpath(path).flatten.compact.length
190
- length
191
- end
192
-
193
- def max(path)
194
- a = query_xpath(path).flatten.compact.map(&:to_i)
195
- a.max
196
- end
197
-
198
151
  def name()
152
+ #puts 'zzz : ' + @rexle.prefixes.inspect
153
+ #puts '@rexle : ' + @rexle.inspect
199
154
  if @rexle then
200
- prefix = @rexle.prefixes.find {|x| x == @name[/^(\w+):/,1] } if @rexle.prefixes.is_a? Array
201
- prefix ? @name.sub(prefix + ':', '') : @name
155
+ prefix = @rexle.prefixes.find {|x| x == @name[/^(\w+):/,1] } if @rexle.prefixes.is_a? Array
156
+ #puts 'ppp: ' + prefix.inspect
157
+ prefix ? @name.sub(prefix + ':', '') : @name
202
158
  else
203
- @name
159
+ @name
204
160
  end
205
161
  end
206
162
 
207
- def xpath(path, rlist=[], &blk)
208
- r = filter_xpath(path, rlist=[], &blk)
209
- r.is_a?(Array) ? r.compact : r
210
- end
211
-
212
- def filter_xpath(path, rlist=[], &blk)
213
-
214
- # is it a function
215
- fn_match = path.match(/^(\w+)\(["']?([^\)]*)["']?\)$/)
216
-
217
- # Array: proc {|x| x.flatten.compact},
218
- if (fn_match and fn_match.captures.first[/^(attribute|@)/]) or fn_match.nil? then
219
- procs = {
220
- Array: proc {|x| block_given? ? x : x.flatten.uniq },
221
- String: proc {|x| x},
222
- Hash: proc {|x| x},
223
- TrueClass: proc{|x| x},
224
- FalseClass: proc{|x| x},
225
- :"Rexle::Element" => proc {|x| [x]}
226
- }
227
- bucket = []
228
- raw_results = path.split('|').map do |xp|
229
- query_xpath(xp, bucket, &blk)
230
- end
231
-
232
- #results = raw_results.inject(&:+)
233
- results = raw_results.last
234
- procs[results.class.to_s.to_sym].call(results) if results
235
-
236
- else
237
- m, xpath_value = fn_match.captures
238
- xpath_value.empty? ? method(m.to_sym).call : method(m.to_sym).call(xpath_value)
239
- end
240
-
241
- end
242
-
243
- def query_xpath(raw_xpath_value, rlist=[], &blk)
163
+ def xpath(xpath_value, rlist=[], &blk)
244
164
 
245
- #remove any pre'fixes
165
+ #remove any prefixes
246
166
  #@rexle.prefixes.each {|x| xpath_value.sub!(x + ':','') }
247
- flag_func = false
248
-
249
- xpath_value = raw_xpath_value.sub('child::','./')
250
- #xpath_value.sub!(/\.\/(?=[\/])/,'')
251
-
252
- if xpath_value[/^[\w\/]+\s*=.*/] then
253
- flag_func = true
254
-
255
- xpath_value.sub!(/^\w+\s*=.*/,'.[\0]')
256
- xpath_value.sub!(/\/([\w]+\s*=.*)/,'[\1]')
257
-
258
- #result = self.element xpath_value
259
- #return [(result.is_a?(Rexle::Element) ? true : false)]
260
- end
261
-
167
+
168
+ xpath_value.sub!(/^\[/,'*[')
262
169
  #xpath_value.sub!(/^attribute::/,'*/attribute::')
263
- raw_path, raw_condition = xpath_value.sub(/^\.?\/(?!\/)/,'')\
264
- .match(/([^\[]+)(\[[^\]]+\])?/).captures
170
+ raw_path, raw_condition = xpath_value.sub(/^\/(?!\/)/,'').match(/([^\[]+)(\[[^\]]+\])?/).captures
265
171
 
266
172
  remaining_path = ($').to_s
267
-
268
- r = raw_path[/([^\/]+)(?=\/\/)/,1]
269
- if r then
270
- a_path = raw_path.split(/(?=\/\/)/,2)
271
- else
272
- a_path = raw_path.split('/',2)
273
- end
274
-
173
+ a_path = raw_path.split('/')
275
174
  condition = raw_condition if a_path.length <= 1
276
175
 
277
176
  if raw_path[0,2] == '//' then
@@ -282,23 +181,20 @@ class Rexle
282
181
  else
283
182
 
284
183
  attribute = xpath_value[/^(attribute::|@)(.*)/,2]
285
-
286
- return @attributes if attribute == '*'
287
- return [@attributes[attribute.to_sym]] if attribute and @attributes and @attributes.has_key?(attribute.to_sym)
184
+ return [@attributes[attribute]] if attribute and @attributes and @attributes.has_key?(attribute)
185
+
288
186
  s = a_path.shift
289
187
  end
290
188
 
291
189
  # isolate the xpath to return just the path to the current element
292
-
293
- elmnt_path = s[/^([\w:\*]+\[[^\]]+\])|[\/]+{,2}[^\/]+/]
190
+ elmnt_path = s[/^([\w\*]+\[[^\]]+\])|[\/]+{,2}[^\/]+/]
294
191
  element_part = elmnt_path[/(^@?[^\[]+)?/,1] if elmnt_path
295
-
192
+
296
193
  if element_part then
297
194
  unless element_part[/^@/] then
298
- element_name = element_part[/^[\w:\*\.]+/]
195
+ element_name = element_part
299
196
  else
300
-
301
- condition = xpath_value[/^\[/] ? xpath_value : element_part
197
+ condition = element_part
302
198
  element_name = nil
303
199
  end
304
200
 
@@ -306,32 +202,15 @@ class Rexle
306
202
 
307
203
  #element_name ||= '*'
308
204
  raw_condition = '' if condition
309
- attr_search = format_condition(condition) if condition and condition.length > 0
310
-
311
- attr_search2 = xpath_value[/^\[(.*)\]$/,1]
312
- if attr_search2 then
313
- r4 = attribute_search(attr_search, self, self.attributes)
314
- return r4
315
- end
316
-
317
- return_elements = []
318
-
319
- if raw_path[0,2] == '//' then
320
205
 
321
- regex = /\[(\d+)\]/
322
- n = xpath_value[regex,1]
323
- xpath_value.slice!(regex)
324
-
325
- rs = scan_match(self, xpath_value).flatten.compact
326
- return n ? rs[n.to_i-1] : rs
206
+ attr_search = format_condition(condition) if condition and condition.length > 0
327
207
 
328
- elsif (raw_path == '.' or raw_path == self.name) and attr_search.nil? then
329
- return [self]
208
+ if raw_path[0,2] == '//'
209
+ return scan_match(self, xpath_value)
330
210
  else
331
211
 
332
- return_elements = @child_lookup.map.with_index.select do |x|
333
- (x[0][0] == element_name || element_name == '.') or \
334
- (element_name == '*' && x[0].is_a?(Array))
212
+ return_elements = @child_lookup.map.with_index.select do |x|
213
+ x[0][0] == element_name or element_name == '*'
335
214
  end
336
215
 
337
216
  end
@@ -339,6 +218,7 @@ class Rexle
339
218
  if return_elements.length > 0 then
340
219
 
341
220
  if (a_path + [remaining_path]).join.empty? then
221
+
342
222
  rlist = return_elements.map.with_index {|x,i| filter(x, i+1, attr_search, &blk)}.compact
343
223
  rlist = rlist[0] if rlist.length == 1
344
224
  else
@@ -348,9 +228,7 @@ class Rexle
348
228
  rtn_element = filter(x, i+1, attr_search){|e| r = e.xpath(a_path.join('/') + raw_condition.to_s + remaining_path, &blk); (r || e) }
349
229
  next if rtn_element.nil? or (rtn_element.is_a? Array and rtn_element.empty?)
350
230
 
351
- if rtn_element.is_a? Hash then
352
- rtn_element
353
- elsif rtn_element.is_a? Array then
231
+ if rtn_element.is_a? Array then
354
232
  rtn_element
355
233
  elsif (rtn_element.is_a? String) || (rtn_element.is_a?(Array) and not(rtn_element[0].is_a? String))
356
234
  rtn_element
@@ -359,26 +237,23 @@ class Rexle
359
237
  end
360
238
  end
361
239
  #
362
-
363
240
  rlist = rlist.flatten(1) unless rlist.length > 1 and rlist[0].is_a? Array
364
241
 
365
242
  end
366
-
367
243
  rlist.compact! if rlist.is_a? Array
368
244
 
369
245
  else
370
246
 
371
247
  # strip off the 1st element from the XPath
372
- new_xpath = xpath_value[/^\/\/[\w:]+\/(.*)/,1]
373
-
248
+ new_xpath = xpath_value[/^\/\/\w+\/(.*)/,1]
249
+
374
250
  if new_xpath then
375
251
  self.xpath(new_xpath + raw_condition.to_s + remaining_path, rlist,&blk)
376
252
  end
377
253
  end
378
-
254
+
379
255
  rlist = rlist.flatten(1) unless not(rlist.is_a? Array) or (rlist.length > 1 and rlist[0].is_a? Array)
380
256
  rlist = [rlist] if rlist.is_a? Rexle::Element
381
- rlist = (rlist.length > 0 ? true : false) if flag_func == true
382
257
  rlist
383
258
  end
384
259
 
@@ -398,11 +273,7 @@ class Rexle
398
273
  end
399
274
 
400
275
  def inspect()
401
- if self.xml.length > 30 then
402
276
  "%s ... </>" % self.xml[/<[^>]+>/]
403
- else
404
- self.xml
405
- end
406
277
  end
407
278
 
408
279
  alias add add_element
@@ -422,28 +293,11 @@ class Rexle
422
293
 
423
294
  def add_text(s) @value = s; self end
424
295
 
425
- def attribute(key)
426
- key = key.to_sym if key.is_a? String
427
- @attributes[key].gsub('&lt;','<').gsub('&gt;','>')
428
- end
429
-
296
+ def attribute(key) @attributes[key] end
430
297
  def attributes() @attributes end
431
-
432
- def children()
433
- return unless @value
434
- r = (@value.empty? ? [] : [@value]) + @child_elements
435
- def r.is_an_empty_string?()
436
- self.length == 1 and self.first == ''
437
- end
438
-
439
- return r
440
- end
441
-
442
- def children=(a) @child_elements = a end
443
-
444
- def deep_clone() Rexle.new(self.xml).root end
445
- def clone() Element.new(@name, @value, @attributes) end
446
-
298
+ def children() @child_elements end
299
+ def children=(a) @child_elements = a end
300
+
447
301
  def delete(obj=nil)
448
302
  if obj then
449
303
  i = @child_elements.index(obj)
@@ -453,14 +307,11 @@ class Rexle
453
307
  end
454
308
  end
455
309
 
456
- def element(s)
457
- r = self.xpath(s)
458
- r.is_a?(Array) ? r.first : r
459
- end
310
+ def element(s) self.xpath(s).first end
460
311
 
461
312
  def elements(s=nil)
462
313
  procs = {
463
- NilClass: proc {Elements.new(@child_elements.select{|x| x.is_a? Rexle::Element })},
314
+ NilClass: proc {Elements.new(@child_elements)},
464
315
  String: proc {|x| @child_elements[x]}
465
316
  }
466
317
 
@@ -468,14 +319,7 @@ class Rexle
468
319
  end
469
320
 
470
321
  def doc_root() @rexle.root end
471
- def each(&blk)
472
- @child_elements.each(&blk) #unless @child_elements.empty?
473
- end
474
- def has_elements?() !self.elements.empty? end
475
-
476
- def insert_after(node) insert(node, 1) end
477
- def insert_before(node) insert(node) end
478
-
322
+ def each(&blk) @child_elements.each(&blk) end
479
323
  def root() self end #@rexle.root end
480
324
 
481
325
  def text(s='')
@@ -486,7 +330,6 @@ class Rexle
486
330
  e = self.element(s)
487
331
  result = e.value if e
488
332
  end
489
- result = CGI.unescape_html result.to_s
490
333
 
491
334
  def result.unescape()
492
335
  s = self.clone
@@ -496,14 +339,10 @@ class Rexle
496
339
 
497
340
  result
498
341
  end
499
-
500
- def texts()
501
- [@value] + @child_elements.select {|x| x.is_a? String}
502
- end
503
342
 
504
343
  def value=(raw_s)
505
344
 
506
- @value = String.new(raw_s.to_s.clone)
345
+ @value = raw_s.to_s.clone
507
346
  escape_chars = %w(& &amp; < &lt; > &gt;).each_slice(2).to_a
508
347
  escape_chars.each{|x| @value.gsub!(*x)}
509
348
 
@@ -523,27 +362,17 @@ class Rexle
523
362
  method(msg).call(self.children)
524
363
  end
525
364
 
526
- alias to_s xml
527
365
 
528
366
  private
529
-
530
- def insert(node,offset=0)
531
- i = parent.child_elements.index(self)
532
- return unless i
533
- parent.child_elements.insert(i+offset,node)
534
- parent.child_lookup.insert(i+offset, [node.name, node.attributes, node.value])
535
- self
536
- end
537
367
 
538
368
  def format_condition(condition)
539
-
540
- raw_items = condition[1..-1].scan(/\'[^\']*\'|\"[^\"]*\"|and|or|\d+|[!=<>]+|position\(\)|[@\w\.\/&;]+/)
369
+ #raw_items = condition[1..-1].scan(/\'[^\']*\'|and|or|\d+|[!=]+|[@\w\.\/]+/)
370
+ raw_items = condition[1..-1].scan(/\'[^\']*\'|and|or|\d+|[!=<>]+|position\(\)|[@\w\.\/]+/)
541
371
 
542
372
  if raw_items[0][/^\d+$/] then
543
373
  return raw_items[0].to_i
544
374
  elsif raw_items[0] == 'position()' then
545
- rrr = "i %s %s" % [raw_items[1].gsub('&lt;','<').gsub('&gt;','>'), raw_items[-1]]
546
- return rrr
375
+ return "i %s %s" % raw_items[1..-1]
547
376
  else
548
377
 
549
378
  andor_items = raw_items.map.with_index.select{|x,i| x[/\band\b|\bor\b/]}.map{|x| [x.last, x.last + 1]}.flatten
@@ -558,10 +387,9 @@ class Rexle
558
387
 
559
388
  if x.length >= 3 then
560
389
  x[1] = '==' if x[1] == '='
561
- "h[:'%s'] %s %s" % x
390
+ "h['%s'] %s %s" % x
562
391
  else
563
-
564
- x.join[/^(and|or)$/] ? x : ("h[:'%s']" % x)
392
+ x
565
393
  end
566
394
  end
567
395
 
@@ -572,7 +400,6 @@ class Rexle
572
400
  items = cons_items.map do |x|
573
401
 
574
402
  if x.length >= 3 then
575
-
576
403
  x[1] = '==' if x[1] == '='
577
404
  if x[0] != '.' then
578
405
  if x[0][/\//] then
@@ -580,7 +407,7 @@ class Rexle
580
407
 
581
408
  "e.xpath('#{path}').first.value == #{value}"
582
409
  else
583
- "(name == '%s' and value %s '%s')" % [x[0], x[1], x[2].sub(/^['"](.*)['"]$/,'\1')]
410
+ "(name == '%s' and value %s %s)" % [x[0], x[1], x[2]]
584
411
  end
585
412
  else
586
413
  "e.value %s %s" % [x[1], x[2]]
@@ -589,7 +416,7 @@ class Rexle
589
416
  x
590
417
  end
591
418
  end
592
-
419
+
593
420
  return items.join(' ')
594
421
  end
595
422
  end
@@ -598,46 +425,35 @@ class Rexle
598
425
  end
599
426
 
600
427
 
601
- def scan_match(node, path)
602
-
603
- r = []
604
- xpath2 = path[2..-1]
605
- xpath2.sub!(/^\*\//,'')
606
- xpath2.sub!(/^\*/,self.name)
607
- xpath2.sub!(/^\w+/,'').sub!(/^\//,'') if xpath2[/^\w+/] == self.name
608
-
428
+ def scan_match(node, xpath)
609
429
 
610
- r << node.xpath(xpath2)
611
- r << node.elements.map {|n| scan_match(n, path) if n.is_a? Rexle::Element}
430
+ r = node.xpath(xpath[2..-1])
431
+ r << node.children.map {|n| scan_match(n, xpath)}
432
+ #puts 'r: ' + r.inspect
612
433
  r
613
434
  end
614
-
615
- # used by xpath function contains()
616
- #
617
- def scan_contents(node)
618
-
619
- a = []
620
- a << node.text
621
-
622
- node.elements.each do |child|
623
- a.concat scan_contents(child)
624
- end
625
- a
626
- end
627
-
628
435
 
629
436
  def filter(raw_element, i, attr_search, &blk)
630
437
 
631
438
  x = raw_element
632
439
  e = @child_elements[x.last]
633
440
 
634
- return unless e.is_a? Rexle::Element
635
- name, value = e.name, e.value if e.is_a? Rexle::Element
441
+ h = x[0][1] # <-- fetch the attributes
636
442
 
637
- h = x[0][1] # <-- fetch the attributes
638
-
639
443
  if attr_search then
640
- attribute_search(attr_search,e, h, i, &blk)
444
+ if attr_search.is_a? Fixnum then
445
+ block_given? ? blk.call(e) : e if i == attr_search
446
+ elsif attr_search[/i\s[<>\=]\s\d+/] and eval(attr_search) then
447
+ block_given? ? blk.call(e) : e
448
+ elsif h and attr_search[/^h\[/] and eval(attr_search)
449
+ block_given? ? blk.call(e) : e
450
+ elsif attr_search[/^\(name ==/] and e.child_lookup.select{|name, attributes, value| eval(attr_search) }.length > 0
451
+ block_given? ? blk.call(e) : e
452
+ elsif attr_search[/^e\.value/] and eval(attr_search)
453
+ block_given? ? blk.call(e) : e
454
+ elsif attr_search[/^e\.xpath/] and eval(attr_search)
455
+ block_given? ? blk.call(e) : e
456
+ end
641
457
  else
642
458
 
643
459
  block_given? ? blk.call(e) : e
@@ -645,28 +461,9 @@ class Rexle
645
461
 
646
462
  end
647
463
 
648
- def attribute_search(attr_search, e, h, i=nil, &blk)
649
- if attr_search.is_a? Fixnum then
650
- block_given? ? blk.call(e) : e if i == attr_search
651
- elsif attr_search[/i\s[<>\=]\s\d+/] and eval(attr_search) then
652
- block_given? ? blk.call(e) : e
653
- elsif h and attr_search[/^h\[/] and eval(attr_search)
654
- block_given? ? blk.call(e) : e
655
- elsif attr_search[/^\(name ==/] and e.child_lookup.select{|name, attributes, value| eval(attr_search) }.length > 0
656
- block_given? ? blk.call(e) : e
657
- elsif attr_search[/^\(name ==/] and eval(attr_search)
658
- block_given? ? blk.call(e) : e
659
- elsif attr_search[/^e\.value/] and eval(attr_search)
660
- block_given? ? blk.call(e) : e
661
- elsif attr_search[/^e\.xpath/] and eval(attr_search)
662
- block_given? ? blk.call(e) : e
663
- end
664
- end
665
464
  end # -- end of element --
666
465
 
667
466
  class Elements
668
- include Enumerable
669
-
670
467
  def initialize(elements=[])
671
468
  super()
672
469
  @elements = elements
@@ -675,10 +472,6 @@ class Rexle
675
472
  def [](i)
676
473
  @elements[i-1]
677
474
  end
678
-
679
- def each(&blk) @elements.each(&blk) end
680
- def to_a() @elements end
681
-
682
475
  end # -- end of elements --
683
476
 
684
477
 
@@ -696,9 +489,8 @@ class Rexle
696
489
  else
697
490
  a = yield
698
491
  end
699
- doc_node = ['doc','',{}]
700
- @a = procs[x.class.to_s.to_sym].call(x)
701
- @doc = scan_element(*(doc_node << @a))
492
+
493
+ @doc = scan_element(*a)
702
494
  self
703
495
  end
704
496
 
@@ -710,18 +502,14 @@ class Rexle
710
502
 
711
503
  alias add add_element
712
504
 
713
- def delete(xpath)
714
- e = @doc.element(xpath)
715
- e.delete if e
716
- end
717
-
505
+ def delete(xpath) @doc.element(xpath).delete end
718
506
  def element(xpath) self.xpath(xpath).first end
719
507
  def elements(s=nil) @doc.elements(s) end
720
508
  def name() @doc.root.name end
721
509
  def to_a() @a end
722
510
  def to_s(options={}) self.xml options end
723
511
  def text(xpath) @doc.text(xpath) end
724
- def root() @doc.elements.first end
512
+ def root() @doc end
725
513
 
726
514
  def write(f)
727
515
  f.write xml
@@ -730,11 +518,9 @@ class Rexle
730
518
  def xml(options={})
731
519
  o = {pretty: false, declaration: true}.merge(options)
732
520
  msg = o[:pretty] == false ? :doc_print : :doc_pretty_print
733
-
734
521
  r = ''
735
522
  r = "<?xml version='1.0' encoding='UTF-8'?>\n" if o[:declaration] == true
736
523
  r << method(msg).call(self.root.children)
737
-
738
524
  r
739
525
  end
740
526
 
@@ -751,23 +537,20 @@ class Rexle
751
537
  if recordx_type then
752
538
  procs = {
753
539
  'dynarex' => proc {|x| DynarexParser.new(x).to_a},
754
- 'polyrex' => proc {|x| PolyrexParser.new(x).to_a},
755
- 'polyrex' => proc {|x| RexleParser.new(x).to_a}
540
+ 'polyrex' => proc {|x| PolyrexParser.new(x).to_a}
756
541
  }
757
542
  procs[recordx_type].call(x)
758
543
  else
759
-
760
544
  RexleParser.new(x).to_a
761
545
  end
762
546
  else
763
-
764
547
  RexleParser.new(x).to_a
765
548
  end
766
549
 
767
550
  end
768
551
 
769
552
  def scan_element(name, value=nil, attributes=nil, *children)
770
-
553
+ #puts 'name : ' + name.inspect
771
554
  element = Element.new(name, value, attributes, self)
772
555
 
773
556
  if children then
@@ -782,6 +565,14 @@ class Rexle
782
565
  return element
783
566
  end
784
567
 
568
+ def count(path)
569
+ #puts 'path : ' + path
570
+ length = @doc.xpath(path).flatten.compact.length
571
+ #puts 'length = ' + length
572
+ length
573
+ end
574
+
575
+ def max(path) @doc.xpath(path).flatten.compact.map(&:to_i).max end
785
576
 
786
577
  # scan a rexml doc
787
578
  #
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
5
+ version: 0.9.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - James Robertson
@@ -10,7 +10,8 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-10-20 00:00:00 Z
13
+ date: 2011-07-19 00:00:00 +01:00
14
+ default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
17
  name: rexleparser
@@ -46,7 +47,7 @@ dependencies:
46
47
  type: :runtime
47
48
  version_requirements: *id003
48
49
  - !ruby/object:Gem::Dependency
49
- name: rexle-builder
50
+ name: nokogiri
50
51
  prerelease: false
51
52
  requirement: &id004 !ruby/object:Gem::Requirement
52
53
  none: false
@@ -56,6 +57,17 @@ dependencies:
56
57
  version: "0"
57
58
  type: :runtime
58
59
  version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: rexle-builder
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ type: :runtime
70
+ version_requirements: *id005
59
71
  description:
60
72
  email:
61
73
  executables: []
@@ -66,6 +78,7 @@ extra_rdoc_files: []
66
78
 
67
79
  files:
68
80
  - lib/rexle.rb
81
+ has_rdoc: true
69
82
  homepage:
70
83
  licenses: []
71
84
 
@@ -89,9 +102,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
102
  requirements: []
90
103
 
91
104
  rubyforge_project:
92
- rubygems_version: 1.8.23
105
+ rubygems_version: 1.5.2
93
106
  signing_key:
94
107
  specification_version: 3
95
- summary: Rexle is a simple XML parser written purely in Ruby
108
+ summary: rexle
96
109
  test_files: []
97
110