rexle 0.9.5 → 0.9.6

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.
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