rexle 1.5.10 → 1.5.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/rexle.rb +374 -349
  4. data.tar.gz.sig +0 -0
  5. metadata +11 -11
  6. metadata.gz.sig +0 -0
data/lib/rexle.rb CHANGED
@@ -13,32 +13,40 @@ require 'backtrack-xpath'
13
13
 
14
14
  # modifications:
15
15
 
16
- # 20-Feb-2021: bug fix: The @instructions accessor is now ignored if nil
16
+ # 15-Jan-2022: bug fix: Related to previous bug fix; Detecting
17
+ # Attributes::Value is now performed instead of
18
+ # a String object
19
+ # 14-Jan-2022: bug fix: Related to previous bug fix; Unescape is
20
+ # now only applied to objects of type Attributes::Value
21
+ # 01-Jan-2022: bug fix: Attribute values are no longer unescaped when
22
+ # called from Rexle#xml
23
+ # 03-Apr-2021: bug fix: Using *to_a* a CDATA element if present is now output
24
+ # 20-Feb-2021: bug fix: The @instructions accessor is now ignored if nil.
17
25
  # 11-Sep-2020: feature: Rexle::Element#text now has unescaped HTML using CGI
18
26
  # 30-Jul-2020: minor improvement: #plaintext now unescapes & to &
19
27
  # 11-May-2020: bug fix: Rexle#css now responds correctly to valid selectors
20
28
  # 23-Apr-2020: feature: Added public method *plaintext*.
21
29
  # 04-Feb-2020: minor bug fix: Element A is now defined as a non self-closing tag
22
- # 18-Sep-2019: minor bug fix: &apos is now unescaped properly
23
- # 09-Jul-2019: minor improvement: A comment tag now has a
30
+ # 18-Sep-2019: minor bug fix: &apos is now unescaped properly
31
+ # 09-Jul-2019: minor improvement: A comment tag now has a
24
32
  # new line when pretty printed
25
33
  # 02-Feb-2019: feature: A comment tag can now have nested elements
26
34
  # 03-Nov-2018: feature: Debug messages can now use coloured text
27
35
  # 02-Oct-2018: feature: Added Rexle::Elements#last
28
- # 18-Jan-2018: bug fix: An Element's attributes are now cloned too
29
- # 16-Sep-2017: improvement: Multiple results are now returned if the
36
+ # 18-Jan-2018: bug fix: An Element's attributes are now cloned too
37
+ # 16-Sep-2017: improvement: Multiple results are now returned if the
30
38
  # xpath contains an *and* operator
31
- # 14-Sep-2017: improvement: An *and* operator can now be
39
+ # 14-Sep-2017: improvement: An *and* operator can now be
32
40
  # used between xpath statements
33
41
  # 10-Sep-2017: bug fix: The following XPath has now been tested => //.[@id]
34
- # 10-Aug-2017: feature: Rexle now has a member variable (@rexle) to keep
35
- # track of the working document when elements are passed to
42
+ # 10-Aug-2017: feature: Rexle now has a member variable (@rexle) to keep
43
+ # track of the working document when elements are passed to
36
44
  # different documents
37
45
  # bug fix: Element prefixes are now only processed if they exist
38
- # 13-Apr-2017: bug fix: Rexle::Elements#index was implemented which fixes the
46
+ # 13-Apr-2017: bug fix: Rexle::Elements#index was implemented which fixes the
39
47
  # Rexle::Element#next_sibling and Rexle::Element#previous_sibling bugs
40
- # 25-Feb-2017: improvement:
41
- # An input rexle array can now have an empty array for
48
+ # 25-Feb-2017: improvement:
49
+ # An input rexle array can now have an empty array for
42
50
  # children e.g. doc = Rexle.new(["records", {}, "", []])
43
51
  # 25-Dec-2016: revision for Ruby 2.4: Replaced Fixnum with Integer
44
52
 
@@ -52,7 +60,14 @@ module XMLhelper
52
60
  scan_print(children).join.force_encoding("utf-8")
53
61
 
54
62
  a = self.root.attributes.to_a.map do |k,v|
55
- "%s='%s'" % [k,(v.is_a?(Array) ? v.join(' ') : v.to_s)]
63
+
64
+ val = if v.is_a?(Array) then
65
+ v.join(' ')
66
+ else
67
+ v.is_a?(Attributes::Value) ? v.to_s(unescape: false) : v
68
+ end
69
+
70
+ "%s='%s'" % [k, val]
56
71
  end
57
72
 
58
73
  xml = "<%s%s>%s</%s>" % [self.root.name, a.empty? ? '' : \
@@ -60,7 +75,7 @@ module XMLhelper
60
75
 
61
76
  if self.instructions and declaration then
62
77
  processing_instructions() + xml
63
- else
78
+ else
64
79
  xml
65
80
  end
66
81
  end
@@ -69,43 +84,43 @@ module XMLhelper
69
84
 
70
85
  body = pretty_print(children,2).join
71
86
 
72
- a = self.root.attributes.to_a.map do |k,v|
73
- "%s='%s'" % [k,(v.is_a?(Array) ? v.join(' ') : v)]
87
+ a = self.root.attributes.to_a.map do |k,v|
88
+ "%s='%s'" % [k,(v.is_a?(Array) ? v.join(' ') : v.to_s)]
74
89
  end
75
-
76
- ind = "\n "
90
+
91
+ ind = "\n "
77
92
  xml = "<%s%s>%s%s%s</%s>" % [self.root.name, a.empty? ? '' : \
78
93
  ' ' + a.join(' '), ind, body, "\n", self.root.name]
79
94
 
80
95
  if self.instructions and declaration then
81
96
  processing_instructions("") + xml
82
- else
97
+ else
83
98
  xml
84
99
  end
85
100
  end
86
-
87
- def inspect()
101
+
102
+ def inspect()
88
103
  "#<Rexle:%s>" % [self.object_id]
89
104
  end
90
105
 
91
106
  def processing_instructions(s='')
92
107
  self.instructions.map do |instruction|
93
- "<?%s?>\n" % instruction.join(' ')
108
+ "<?%s?>\n" % instruction.join(' ')
94
109
  end.join s
95
110
  end
96
111
 
97
112
  def scan_print(nodes)
98
113
 
99
114
  r2 = nodes.map do |x|
100
-
115
+
101
116
  r = if x.is_a? Rexle::Element then
102
117
 
103
- a = x.attributes.to_a.map do |k,v|
118
+ a = x.attributes.to_a.map do |k,v|
104
119
  "%s='%s'" % [k,(v.is_a?(Array) ? v.join(' ') : v)]
105
120
  end
106
121
 
107
122
  tag = x.name + (a.empty? ? '' : ' ' + a.join(' '))
108
-
123
+
109
124
  non_self_closing_tags = %w(script textarea iframe div object a)
110
125
 
111
126
  if (x.children and x.children.length > 0 \
@@ -119,20 +134,20 @@ module XMLhelper
119
134
  else
120
135
  out = ["<%s/>" % tag]
121
136
  end
122
-
137
+
123
138
  elsif x.is_a? String then x
124
- elsif x.is_a? Rexle::CData then x.print
125
- elsif x.is_a? Rexle::Comment then x.print
126
-
139
+ elsif x.is_a? Rexle::CData then x.print
140
+ elsif x.is_a? Rexle::Comment then x.print
141
+
127
142
  end
128
143
 
129
144
  r
130
145
  end
131
-
146
+
132
147
  r2
133
148
 
134
149
  end
135
-
150
+
136
151
  def scan_to_a(nodes)
137
152
 
138
153
  nodes.inject([]) do |r,x|
@@ -141,6 +156,10 @@ module XMLhelper
141
156
 
142
157
  a = [String.new(x.name), Hash.new(x.attributes), x.value.to_s]
143
158
 
159
+ if x.cdatas.any? then
160
+ a.concat x.cdatas.map {|cdata| ['![', {}, cdata] }
161
+ end
162
+
144
163
  (a.concat(scan_to_a(x.children))) if x.children.length > 1
145
164
  r << a
146
165
  elsif x.is_a? String then
@@ -151,7 +170,7 @@ module XMLhelper
151
170
  end
152
171
 
153
172
  end
154
-
173
+
155
174
 
156
175
 
157
176
  def pretty_print(nodes, indent='0')
@@ -164,13 +183,13 @@ module XMLhelper
164
183
 
165
184
  if x.is_a? Rexle::Element then
166
185
 
167
- a = x.attributes.to_a.map do |k,v|
186
+ a = x.attributes.to_a.map do |k,v|
168
187
  "%s='%s'" % [k,(v.is_a?(Array) ? v.join(' ') : v)]
169
188
  end
170
189
  a ||= []
171
190
 
172
191
  tag = x.name + (a.empty? ? '' : ' ' + a.join(' '))
173
- start = i > 0 ? ("\n" + ' ' * (indent - 1)) : ''
192
+ start = i > 0 ? ("\n" + ' ' * (indent - 1)) : ''
174
193
 
175
194
  if (x.value and x.value.length > 0) \
176
195
  or (x.children and x.children.length > 0 \
@@ -178,13 +197,13 @@ module XMLhelper
178
197
  x.name == 'script' or x.name == 'textarea' or \
179
198
  x.name == 'iframe' then
180
199
 
181
- ind1 = (x.children and x.children.grep(Rexle::Element).length > 0) ?
200
+ ind1 = (x.children and x.children.grep(Rexle::Element).length > 0) ?
182
201
  ("\n" + ' ' * indent) : ''
183
-
202
+
184
203
  out = ["%s<%s>%s" % [start, tag, ind1]]
185
- out << pretty_print(x.children, (indent + 1).to_s.clone)
204
+ out << pretty_print(x.children, (indent + 1).to_s.clone)
186
205
  ind2 = (ind1 and ind1.length > 0) ? ("\n" + ' ' * (indent - 1)) : ''
187
- out << "%s</%s>" % [ind2, x.name]
206
+ out << "%s</%s>" % [ind2, x.name]
188
207
  else
189
208
 
190
209
  out = ["%s<%s/>" % [start, tag]]
@@ -192,8 +211,8 @@ module XMLhelper
192
211
 
193
212
 
194
213
  elsif x.is_a? String then x.sub(/^[\n\s]+$/,'')
195
- elsif x.is_a? Rexle::CData then x.print
196
- elsif x.is_a? Rexle::Comment then "\n" + (' ' * indent) + x.print
214
+ elsif x.is_a? Rexle::CData then x.print
215
+ elsif x.is_a? Rexle::Comment then "\n" + (' ' * indent) + x.print
197
216
 
198
217
  end
199
218
  end
@@ -208,17 +227,17 @@ class Rexle
208
227
 
209
228
  attr_reader :prefixes, :doctype
210
229
  attr_accessor :instructions
211
-
230
+
212
231
  def initialize(x=nil, rexle: self, debug: false)
213
232
 
214
233
  @rexle, @debug = rexle, debug
215
234
  $debug = @debug
216
-
235
+
217
236
  puts 'inside Rexle'.debug if debug
218
-
237
+
219
238
  super()
220
239
 
221
- @instructions = [["xml", "version='1.0' encoding='UTF-8'"]]
240
+ @instructions = [["xml", "version='1.0' encoding='UTF-8'"]]
222
241
  @doctype = :xml
223
242
 
224
243
  # what type of input is it? Is it a string, array
@@ -228,11 +247,11 @@ class Rexle
228
247
  Array: proc {|x| x},
229
248
  RexleParser: ->(x){ parse_rexle(x)}
230
249
  }
231
-
250
+
232
251
  doc_node = ['doc', Attributes.new]
233
-
252
+
234
253
  @a = procs[x.class.to_s.to_sym].call(x)
235
-
254
+
236
255
  @doc = scan_element(*(doc_node << @a))
237
256
 
238
257
  # fetch the namespaces
@@ -243,78 +262,78 @@ class Rexle
243
262
  xmlns = @doc.root.attributes.select {|k,v| k[/^xmlns:/]}
244
263
  @prefixes = xmlns.keys.map{|x| x[/\w+$/]}
245
264
  end
246
-
265
+
247
266
  end
248
267
 
249
268
  end
250
-
269
+
251
270
  def clone()
252
271
  Rexle.new self.to_a
253
272
  end
254
-
273
+
255
274
  def at_css(selector)
256
275
  @doc.root.element RexleCSS.new(selector).to_xpath
257
- end
258
-
276
+ end
277
+
259
278
  def css(selector)
260
-
261
- a = selector.split(',').flat_map do |x|
279
+
280
+ a = selector.split(',').flat_map do |x|
262
281
  @doc.root.xpath RexleCSS.new(x).to_xpath
263
282
  end
264
-
283
+
265
284
  return a
266
285
  end
267
-
286
+
268
287
  def xpath(path, &blk)
269
288
  @doc.xpath(path, &blk)
270
- end
289
+ end
271
290
 
272
291
  class Element
273
292
  include XMLhelper
274
-
293
+
275
294
  class Value < String
276
-
295
+
277
296
  def initialize(value)
278
297
  super(value)
279
298
  end
280
-
299
+
281
300
  def <(val2)
282
301
  self.to_f < val2.to_f
283
- end
284
-
302
+ end
303
+
285
304
  def >(val2)
286
305
  self.to_f > val2.to_f
287
- end
288
- end
289
-
306
+ end
307
+ end
308
+
290
309
  class Attribute
291
-
310
+
292
311
  attr_reader :value
293
-
312
+
294
313
  def initialize(value)
295
314
  @value = value
296
315
  end
297
-
316
+
298
317
  def to_f()
299
318
  @value.to_f
300
- end
301
-
319
+ end
320
+
302
321
  def to_i()
303
322
  @value.to_i
304
323
  end
305
-
324
+
306
325
  alias to_s value
307
-
326
+
308
327
  end
309
-
328
+
310
329
  attr_accessor :name, :value, :parent
311
330
  attr_reader :child_elements, :doc_id, :instructions
312
-
331
+
313
332
  alias original_clone clone
314
333
 
315
334
  def initialize(name=nil, value: nil, attributes: Attributes.new, rexle: self)
316
335
 
317
- @rexle = rexle
336
+ @rexle = rexle
318
337
  super()
319
338
 
320
339
  @name, @attributes = name.to_s, attributes
@@ -324,11 +343,11 @@ class Rexle
324
343
  self.add_text value if value
325
344
 
326
345
  end
327
-
346
+
328
347
  def backtrack(use_attributes: true)
329
348
  BacktrackXPath.new(self, use_attributes: use_attributes)
330
349
  end
331
-
350
+
332
351
  def cdata?()
333
352
  self.is_a? CData
334
353
  end
@@ -336,8 +355,8 @@ class Rexle
336
355
  def contains(raw_args)
337
356
 
338
357
  path, raw_val = raw_args.split(',',2)
339
- val = raw_val.strip[/^["']?.*["']?$/]
340
-
358
+ val = raw_val.strip[/^["']?.*["']?$/]
359
+
341
360
  anode = query_xpath(path)
342
361
 
343
362
  return [false] if anode.nil? or anode.empty?
@@ -346,21 +365,21 @@ class Rexle
346
365
  r = [a.grep(/#{val.sub(/^["'](.*)["']$/,'\1')}/).length > 0]
347
366
 
348
367
  r.any?
349
- end
350
-
368
+ end
369
+
351
370
  def count(path)
352
371
  length = query_xpath(path).flatten.compact.length
353
372
  length
354
373
  end
355
-
374
+
356
375
  def current()
357
376
  self
358
377
  end
359
378
 
360
379
  def at_css(selector)
361
380
  self.root.element RexleCSS.new(selector).to_xpath
362
- end
363
-
381
+ end
382
+
364
383
  def css(selector)
365
384
 
366
385
  selector.split(',')\
@@ -371,76 +390,76 @@ class Rexle
371
390
  def lowercase(s)
372
391
 
373
392
  end
374
-
375
- def max(path)
393
+
394
+ def max(path)
376
395
  a = query_xpath(path).flatten.select{|x| x.is_a? String or x.is_a? Rexle::Element::Attribute}.map(&:to_i)
377
- a.max
396
+ a.max
378
397
  end
379
-
398
+
380
399
  def name()
381
-
400
+
382
401
  if @rexle and @rexle.respond_to? :prefixes then
383
-
402
+
384
403
  if @rexle.prefixes.is_a? Array then
385
- prefix = @rexle.prefixes.find {|x| x == @name[/^(\w+):/,1] }
404
+ prefix = @rexle.prefixes.find {|x| x == @name[/^(\w+):/,1] }
386
405
  end
387
-
406
+
388
407
  prefix ? @name.sub(prefix + ':', '') : @name
389
-
408
+
390
409
  else
391
410
  @name
392
411
  end
393
-
412
+
394
413
  end
395
-
396
- def next_element()
414
+
415
+ def next_element()
397
416
 
398
417
  id = self.object_id
399
- a = self.parent.elements
418
+ a = self.parent.elements
400
419
 
401
420
  i = a.index {|x| x.object_id == id} + 2
402
421
  a[i] if i < a.length + 1
403
-
422
+
404
423
  end
405
-
424
+
406
425
  alias next_sibling next_element
407
-
426
+
408
427
  def not(bool)
409
428
 
410
429
  r = self.xpath(bool).any?
411
430
 
412
431
  !r
413
432
  end
414
-
415
- def previous_element()
416
-
433
+
434
+ def previous_element()
435
+
417
436
  id = self.object_id
418
- a = self.parent.elements
437
+ a = self.parent.elements
419
438
  i = a.index {|x| x.object_id == id}
420
439
 
421
- a[i] if i > 0
440
+ a[i] if i > 0
422
441
 
423
442
  end
424
-
443
+
425
444
  alias previous_sibling previous_element
426
-
445
+
427
446
  def xpath(path, rlist=[], &blk)
428
-
447
+
429
448
  #@log.debug 'inside xpath ' + path.inspect
430
449
 
431
450
  r = filter_xpath(path, rlist=[], &blk)
432
451
  #@log.debug 'after filter_xpath : ' + r.inspect
433
-
452
+
434
453
  if r.is_a?(Array) then
435
-
454
+
436
455
  Recordset.new(r.compact)
437
-
456
+
438
457
  else
439
458
  r
440
459
  end
441
-
460
+
442
461
  end
443
-
462
+
444
463
  def filter_xpath(raw_path, rlist=[], &blk)
445
464
  #@log.debug 'inside filter_xpath : ' + raw_path.inspect
446
465
  path = String.new raw_path
@@ -450,25 +469,25 @@ class Rexle
450
469
  #fn_match = path.match(/^(\w+)\(/)
451
470
  #@log.debug 'fn_match : ' + fn_match.inspect
452
471
  end_fn_match = path.slice!(/\[\w+\(\)\]$/)
453
-
472
+
454
473
  if end_fn_match then
455
-
474
+
456
475
  m = end_fn_match[1..-4]
457
476
  #@log.debug 'its a function'
458
477
  [method(m.to_sym).call(xpath path)]
459
-
460
- elsif (fn_match and fn_match.captures.first[/^(attribute|@)/])
478
+
479
+ elsif (fn_match and fn_match.captures.first[/^(attribute|@)/])
461
480
 
462
481
  procs = {
463
482
 
464
- Array: proc { |x|
465
- if block_given? then
466
- x.flatten(1)
483
+ Array: proc { |x|
484
+ if block_given? then
485
+ x.flatten(1)
467
486
  else
468
487
  rs = x.flatten
469
- rs.any?{|x| x == true or x == false} ? rs : rs.uniq(&:object_id)
488
+ rs.any?{|x| x == true or x == false} ? rs : rs.uniq(&:object_id)
470
489
  end
471
- },
490
+ },
472
491
  String: proc {|x| x},
473
492
  Hash: proc {|x| x},
474
493
  TrueClass: proc{|x| x},
@@ -477,25 +496,25 @@ class Rexle
477
496
  }
478
497
  bucket = []
479
498
  raw_results = path.split('|').map do |xp|
480
- query_xpath(xp.strip, bucket, &blk)
499
+ query_xpath(xp.strip, bucket, &blk)
481
500
  end
482
-
501
+
483
502
  results = raw_results
484
503
 
485
- procs[results.class.to_s.to_sym].call(results) if results
486
-
504
+ procs[results.class.to_s.to_sym].call(results) if results
505
+
487
506
  elsif fn_match.nil?
488
-
507
+
489
508
  procs = {
490
509
 
491
- Array: proc { |x|
492
- if block_given? then
493
- x.flatten(1)
510
+ Array: proc { |x|
511
+ if block_given? then
512
+ x.flatten(1)
494
513
  else
495
514
  rs = x.flatten
496
- rs.any?{|x| x == true or x == false} ? rs : rs.uniq(&:object_id)
515
+ rs.any?{|x| x == true or x == false} ? rs : rs.uniq(&:object_id)
497
516
  end
498
- },
517
+ },
499
518
  String: proc {|x| x},
500
519
  Hash: proc {|x| x},
501
520
  TrueClass: proc{|x| x},
@@ -503,23 +522,23 @@ class Rexle
503
522
  :"Rexle::Element" => proc {|x| [x]}
504
523
  }
505
524
  bucket = []
506
-
525
+
507
526
  results = if path =~ /[\[]|\(/ then
508
527
 
509
528
  raw_results = path.split(/\|/).map do |xp|
510
- query_xpath(xp.strip, bucket, &blk)
529
+ query_xpath(xp.strip, bucket, &blk)
511
530
  end
512
531
 
513
532
  raw_results.flatten.index(true) ? [true] : []
514
-
533
+
515
534
  else
516
535
  raw_results = path.split(/ *(?:\||\band\b) */).map do |xp|
517
- query_xpath(xp.strip, bucket, &blk)
518
- end
536
+ query_xpath(xp.strip, bucket, &blk)
537
+ end
519
538
 
520
539
  if path =~ / and / then
521
540
 
522
- raw_results.flatten.select {|x| x == true or x == false}
541
+ raw_results.flatten.select {|x| x == true or x == false}
523
542
 
524
543
  else
525
544
  raw_results.flatten.index(true) ? [true] : []
@@ -528,12 +547,12 @@ class Rexle
528
547
 
529
548
  return results if !path[/[><]/] and results.any?
530
549
  results = raw_results # .flatten.select {|x| x}
531
-
532
- procs[results.class.to_s.to_sym].call(results) if results
550
+
551
+ procs[results.class.to_s.to_sym].call(results) if results
533
552
 
534
553
  else
535
-
536
- m, xpath_value, index = fn_match.captures
554
+
555
+ m, xpath_value, index = fn_match.captures
537
556
 
538
557
  if m == 'text' then
539
558
  a = texts()
@@ -547,14 +566,14 @@ class Rexle
547
566
 
548
567
  end
549
568
 
550
- end
551
-
569
+ end
570
+
552
571
  def query_xpath(raw_xpath_value, rlist=[], &blk)
553
572
 
554
573
  #@log.debug 'query_xpath : ' + raw_xpath_value.inspect
555
574
  #@log.debug '++ ' + self.xml.inspect
556
575
 
557
- flag_func = false
576
+ flag_func = false
558
577
 
559
578
  xpath_value = raw_xpath_value.sub('child::','./')
560
579
 
@@ -578,38 +597,38 @@ class Rexle
578
597
 
579
598
  raw_condition = raw_condition ? raw_condition + '/' + remaining_path \
580
599
  : remaining_path
581
- remaining_path = ''
600
+ remaining_path = ''
582
601
  end
583
602
 
584
- r = raw_path[/^([^\/]+)(?=\/\/)/,1]
603
+ r = raw_path[/^([^\/]+)(?=\/\/)/,1]
585
604
 
586
605
  if r then
587
606
  a_path = raw_path.split(/(?=\/\/)/,2)
588
607
  else
589
608
  a_path = raw_path.split('/',2)
590
609
  end
591
-
610
+
592
611
  condition = raw_condition if a_path.length <= 1 #and not raw_condition[/^\[\w+\(.*\)\]$/]
593
612
 
594
613
  if raw_path[0,2] == '//' then
595
614
  s = ''
596
- elsif raw_path == 'text()'
615
+ elsif raw_path == 'text()'
597
616
 
598
617
  a_path.shift
599
618
  #return @value
600
619
  return self.texts
601
620
  else
602
621
 
603
- attribute = xpath_value[/^(attribute::|@)(.*)/,2]
604
-
622
+ attribute = xpath_value[/^(attribute::|@)(.*)/,2]
623
+
605
624
  return @attributes if attribute == '*'
606
-
625
+
607
626
  if attribute and @attributes and \
608
627
  @attributes.has_key?(attribute.to_sym) then
609
628
  return [Attribute.new(@attributes[attribute.to_sym])]
610
629
  end
611
630
  s = a_path.shift
612
- end
631
+ end
613
632
 
614
633
  # isolate the xpath to return just the path to the current element
615
634
 
@@ -625,7 +644,7 @@ class Rexle
625
644
  if element_name and element_name[/^\d/] then
626
645
  element_name = nil
627
646
  end
628
-
647
+
629
648
  condition = raw_xpath_value if element_name.nil?
630
649
 
631
650
  else
@@ -661,11 +680,11 @@ class Rexle
661
680
  r4 = attribute_search(attr_search, self, self.attributes)
662
681
  return r4
663
682
  end
664
-
665
-
683
+
684
+
666
685
  return_elements = []
667
-
668
-
686
+
687
+
669
688
 
670
689
  if raw_path[0,2] == '//' then
671
690
 
@@ -680,25 +699,25 @@ class Rexle
680
699
 
681
700
  if element_name.is_a? String then
682
701
  ename, raw_selector = (element_name.split('::',2)).reverse
683
-
702
+
684
703
  selector = case raw_selector
685
704
  when 'following-sibling' then 1
686
705
  when 'preceding-sibling' then -1
687
706
  end
688
-
707
+
689
708
  else
690
709
  ename = element_name
691
- end
710
+ end
692
711
 
693
712
  if ename == '..' then
694
-
713
+
695
714
  remaining_xpath = raw_path[/\.\.\/(.*)/,1]
696
715
  # select the parent element
697
716
 
698
717
  r2 = self.parent.xpath(remaining_xpath)
699
718
 
700
719
  return r2
701
-
720
+
702
721
  elsif ename == '.'
703
722
 
704
723
  remaining_xpath = raw_path[1..-1]
@@ -707,41 +726,41 @@ class Rexle
707
726
  if xpath_value.length > 0 and xpath_value =~ /\[/ then
708
727
 
709
728
  r = eval(attr_search.sub(/^h/,'self.attributes'))
710
- return self if r
729
+ return self if r
711
730
 
712
731
  else
713
732
  return self
714
733
  end
715
734
  else
716
735
  return self.xpath(remaining_xpath)
717
- end
736
+ end
718
737
 
719
738
  elsif element_name.nil?
720
739
  puts ('attr_search: ' + attr_search.inspect).debug if $debug
721
- return eval attr_search
740
+ return eval attr_search
722
741
  else
723
742
 
724
743
  if raw_selector.nil? and ename != element_part then
725
744
 
726
745
  right_cond = element_part[/#{ename}(.*)/,1]
727
746
 
728
- end
747
+ end
729
748
 
730
749
  return_elements = @child_elements.map.with_index.select do |x, i|
731
750
 
732
751
  next unless x.is_a? Rexle::Element
733
752
 
734
753
  #x.name == ename or (ename == '*')
735
-
754
+
736
755
  r10 = ((x.name == ename) or (ename == '*'))
737
756
 
738
-
757
+
739
758
 
740
759
  end
741
-
760
+
742
761
  if right_cond then
743
-
744
-
762
+
763
+
745
764
  r12 = return_elements.map do |x, i|
746
765
 
747
766
  if x.text then
@@ -751,15 +770,15 @@ class Rexle
751
770
  else
752
771
  false
753
772
  end
754
-
773
+
755
774
  end
756
-
775
+
757
776
  return r12
758
-
759
- end
760
-
777
+
778
+ end
779
+
761
780
  if selector then
762
- ne = return_elements.inject([]) do |r,x|
781
+ ne = return_elements.inject([]) do |r,x|
763
782
  i = x.last + selector
764
783
  if i >= 0 then
765
784
  r << i
@@ -770,17 +789,17 @@ class Rexle
770
789
 
771
790
  return_elements = ne.map {|x| [@child_elements[x], x] if x}
772
791
  end
773
-
792
+
774
793
 
775
794
  end
776
795
  end
777
-
796
+
778
797
  if return_elements.length > 0 then
779
798
 
780
799
  if (a_path + [remaining_path]).join.empty? then
781
800
 
782
801
  # pass in a block to the filter if it is function contains?
783
- rlist = return_elements.map.with_index do |x,i|
802
+ rlist = return_elements.map.with_index do |x,i|
784
803
  r5 = filter(x, i+1, attr_search, &blk)
785
804
 
786
805
  r5
@@ -790,9 +809,9 @@ class Rexle
790
809
 
791
810
  else
792
811
 
793
- rlist << return_elements.map.with_index do |x,i|
812
+ rlist << return_elements.map.with_index do |x,i|
794
813
 
795
- rtn_element = filter(x, i+1, attr_search) do |e|
814
+ rtn_element = filter(x, i+1, attr_search) do |e|
796
815
 
797
816
  r = e.xpath(a_path.join('/') + raw_condition.to_s \
798
817
  + remaining_path, &blk)
@@ -838,7 +857,7 @@ class Rexle
838
857
  rlist,&blk)
839
858
  end
840
859
  end
841
-
860
+
842
861
  rlist = rlist.flatten(1) unless not(rlist.is_a? Array) \
843
862
  or (rlist.length > 1 and rlist[0].is_a? Array)
844
863
  rlist = [rlist] if rlist.is_a? Rexle::Element
@@ -855,21 +874,21 @@ class Rexle
855
874
  elsif item.is_a? Rexle::CData then
856
875
  @child_elements << item
857
876
  elsif item.is_a? Rexle::Comment then
858
- @child_elements << item
877
+ @child_elements << item
859
878
  elsif item.is_a? Rexle::Element then
860
879
 
861
880
  @child_elements << item
862
881
  # add a reference from this element (the parent) to the child
863
882
  item.parent = self
864
- item
865
-
883
+ item
884
+
866
885
  elsif item.is_a? Rexle then
867
886
  self.add_element(item.root)
868
887
  end
869
888
 
870
- end
889
+ end
871
890
 
872
- def add(item)
891
+ def add(item)
873
892
 
874
893
  if item.is_a? Rexle::Element then
875
894
 
@@ -895,13 +914,13 @@ class Rexle
895
914
  "%s ... </>" % self.xml[/<[^>]+>/]
896
915
  else
897
916
  self.xml
898
- end
917
+ end
899
918
  end
900
919
 
901
920
  def add_attribute(*x)
902
-
921
+
903
922
  proc_hash = lambda {|x| Hash[*x]}
904
-
923
+
905
924
  procs = {
906
925
  Hash: lambda {|x| x[0] || {}},
907
926
  String: proc_hash,
@@ -919,57 +938,57 @@ class Rexle
919
938
  def add_text(s)
920
939
 
921
940
  self.child_elements << s
922
- self
941
+ self
923
942
  end
924
-
925
- def attribute(key)
926
-
943
+
944
+ def attribute(key)
945
+
927
946
  key = key.to_sym if key.is_a? String
928
-
947
+
929
948
  if @attributes[key].is_a? String then
930
- @attributes[key].gsub('&lt;','<').gsub('&gt;','>')
949
+ @attributes[key].gsub('&lt;','<').gsub('&gt;','>')
931
950
  else
932
951
  @attributes[key]
933
952
  end
934
- end
935
-
936
- def attributes() @attributes end
937
-
953
+ end
954
+
955
+ def attributes() @attributes end
956
+
938
957
  def cdatas()
939
958
  self.children.inject([]){|r,x| x.is_a?(Rexle::CData) ? r << x.to_s : r }
940
959
  end
941
-
960
+
942
961
  def children()
943
962
 
944
963
  r = @child_elements
945
-
964
+
946
965
  def r.is_an_empty_string?()
947
966
  self.length == 1 and self.first == ''
948
- end
949
-
967
+ end
968
+
950
969
  return r
951
- end
970
+ end
952
971
 
953
972
  def children=(a) @child_elements = a if a.is_a? Array end
954
-
973
+
955
974
  def deep_clone() Rexle.new(self.xml).root end
956
-
957
- def clone()
958
- Element.new(@name, attributes: Marshal.load( Marshal.dump(@attributes)))
975
+
976
+ def clone()
977
+ Element.new(@name, attributes: Marshal.load( Marshal.dump(@attributes)))
959
978
  end
960
-
979
+
961
980
  def delete(obj=nil)
962
981
 
963
982
  if obj then
964
983
 
965
984
  if obj.is_a? String then
966
-
985
+
967
986
  self.xpath(obj).each {|e| e.delete; e = nil}
968
-
987
+
969
988
  else
970
989
 
971
990
  i = @child_elements.index(obj)
972
- [@child_elements].each{|x| x.delete_at i} if i
991
+ [@child_elements].each{|x| x.delete_at i} if i
973
992
  end
974
993
  else
975
994
 
@@ -991,50 +1010,50 @@ class Rexle
991
1010
  String: proc {|x| @child_elements[x]}
992
1011
  }
993
1012
 
994
- procs[s.class.to_s.to_sym].call(s)
1013
+ procs[s.class.to_s.to_sym].call(s)
995
1014
  end
996
1015
 
997
1016
  def doc_root() @rexle.root end
998
1017
  def each(&blk) self.children.each(&blk) end
999
1018
  def each_recursive(&blk) recursive_scan(self.children,&blk) end
1000
1019
  alias traverse each_recursive
1001
- def has_elements?() !self.elements.empty? end
1002
- def insert_after(node) insert(node, 1) end
1020
+ def has_elements?() !self.elements.empty? end
1021
+ def insert_after(node) insert(node, 1) end
1003
1022
  def insert_before(node) insert(node) end
1004
1023
  def last(a) a.last end
1005
- def map(&blk) self.children.map(&blk) end
1006
-
1024
+ def map(&blk) self.children.map(&blk) end
1025
+
1007
1026
  def plaintext()
1008
1027
  CGI.unescapeHTML xml().gsub(/<\/?[^>]+>/,'').gsub('&nbsp;',' ')\
1009
1028
  .gsub(/\n\s+/,' ')
1010
1029
  end
1011
-
1012
- def root() self end
1030
+
1031
+ def root() self end
1013
1032
 
1014
1033
  def text(s='')
1015
-
1016
- return self.value if s.empty?
1017
-
1034
+
1035
+ return self.value if s.empty?
1036
+
1018
1037
  e = self.element(s)
1019
1038
  return e if e.is_a? String
1020
-
1039
+
1021
1040
  e.value if e
1022
1041
  end
1023
-
1042
+
1024
1043
  def texts()
1025
1044
 
1026
1045
  r = @child_elements.select do |x|
1027
1046
  x.is_a? String or x.is_a? Rexle::CData
1028
1047
  end
1029
-
1048
+
1030
1049
  r.map do |x|
1031
1050
  def x.unescape()
1032
1051
  s = self.to_s.clone
1033
1052
  %w(&lt; < &gt; > &amp; & &apos; ').each_slice(2){|x| s.gsub!(*x)}
1034
1053
  s
1035
- end
1054
+ end
1036
1055
  end
1037
-
1056
+
1038
1057
  return r
1039
1058
  end
1040
1059
 
@@ -1042,20 +1061,20 @@ class Rexle
1042
1061
 
1043
1062
  r = @child_elements.first
1044
1063
  return nil unless r.is_a? String
1045
-
1064
+
1046
1065
  def r.unescape()
1047
1066
  s = self.clone
1048
1067
  %w(&lt; < &gt; > &amp; & &apos; ').each_slice(2){|x| s.gsub!(*x)}
1049
1068
  s
1050
- end
1051
-
1069
+ end
1070
+
1052
1071
  return r
1053
1072
  end
1054
-
1073
+
1055
1074
  def value=(raw_s)
1056
1075
 
1057
1076
  val = Value.new(raw_s.to_s.clone)
1058
-
1077
+
1059
1078
  escape_chars = %w(& &amp; ' &apos; < &lt; > &gt;).each_slice(2).to_a
1060
1079
  escape_chars.each{|x| val.gsub!(*x)}
1061
1080
 
@@ -1065,9 +1084,15 @@ class Rexle
1065
1084
  end
1066
1085
 
1067
1086
  alias text= value=
1068
-
1087
+
1069
1088
  def to_a()
1089
+
1070
1090
  e = [String.new(self.name), Hash.new(self.attributes)]
1091
+
1092
+ if self.cdatas.any? then
1093
+ e.concat self.cdatas.map {|cdata| ['![', {}, cdata] }
1094
+ end
1095
+
1071
1096
  [*e, *scan_to_a(self.children)]
1072
1097
  end
1073
1098
 
@@ -1077,10 +1102,10 @@ class Rexle
1077
1102
  Hash: lambda {|x|
1078
1103
  o = {pretty: false}.merge(x)
1079
1104
  msg = o[:pretty] == false ? :doc_print : :doc_pretty_print
1080
-
1105
+
1081
1106
  method(msg).call(self.children)
1082
1107
  },
1083
- String: lambda {|x|
1108
+ String: lambda {|x|
1084
1109
  r = self.element(x)
1085
1110
  r ? r.xml : ''
1086
1111
  }
@@ -1093,18 +1118,18 @@ class Rexle
1093
1118
  end
1094
1119
 
1095
1120
  def prepend(item)
1096
-
1121
+
1097
1122
  @child_elements.unshift item
1098
-
1123
+
1099
1124
  # add a reference from this element (the parent) to the child
1100
1125
  item.parent = self
1101
- item
1102
- end
1103
-
1126
+ item
1127
+ end
1128
+
1104
1129
  alias to_s xml
1105
1130
 
1106
1131
  private
1107
-
1132
+
1108
1133
  def insert(node,offset=0)
1109
1134
 
1110
1135
  i = parent.child_elements.index(self)
@@ -1116,7 +1141,7 @@ class Rexle
1116
1141
  node.instance_variable_set(:@doc_id, self.doc_root.object_id)
1117
1142
 
1118
1143
  self
1119
- end
1144
+ end
1120
1145
 
1121
1146
  def format_condition(condition)
1122
1147
 
@@ -1141,21 +1166,21 @@ class Rexle
1141
1166
  elsif raw_items[0][/^not\(/]
1142
1167
 
1143
1168
  return raw_items[0]
1144
-
1169
+
1145
1170
  else
1146
1171
 
1147
1172
  andor_items = raw_items.map.with_index\
1148
1173
  .select{|x,i| x[/\band\b|\bor\b/]}\
1149
1174
  .map{|x| [x.last, x.last + 1]}.flatten
1150
-
1175
+
1151
1176
  indices = [0] + andor_items + [raw_items.length]
1152
1177
 
1153
1178
  if raw_items[0][0] == '@' then
1154
1179
 
1155
1180
  raw_items.each{|x| x.gsub!(/^@/,'')}
1156
- cons_items = indices.each_cons(2).map{|x,y| raw_items.slice(x...y)}
1181
+ cons_items = indices.each_cons(2).map{|x,y| raw_items.slice(x...y)}
1157
1182
 
1158
- items = cons_items.map do |x|
1183
+ items = cons_items.map do |x|
1159
1184
 
1160
1185
  if x.length >= 3 then
1161
1186
  if x[0] != 'class' then
@@ -1174,17 +1199,17 @@ class Rexle
1174
1199
  else
1175
1200
 
1176
1201
  cons_items = indices.each_cons(2).map{|x,y| raw_items.slice(x...y)}
1177
-
1178
- items = cons_items.map do |x|
1202
+
1203
+ items = cons_items.map do |x|
1179
1204
 
1180
1205
  if x.length >= 3 then
1181
1206
 
1182
1207
  x[1] = '==' if x[1] == '='
1183
1208
  if x[0] != '.' then
1184
1209
  if x[0][/\//] then
1185
-
1210
+
1186
1211
  path, value = x.values_at(0,-1)
1187
-
1212
+
1188
1213
  if x[0][/@\w+$/] then
1189
1214
  "r = e.xpath('#{path}').first; r and r.value == #{value}"
1190
1215
  else
@@ -1208,16 +1233,16 @@ class Rexle
1208
1233
 
1209
1234
 
1210
1235
  end
1211
-
1236
+
1212
1237
  def scan_match(node, path)
1213
-
1238
+
1214
1239
  if path == '//' then
1215
- return [node, node.text,
1240
+ return [node, node.text,
1216
1241
  node.elements.map {|x| scan_match x, path}]
1217
1242
  end
1218
-
1243
+
1219
1244
  r = []
1220
- xpath2 = path[2..-1]
1245
+ xpath2 = path[2..-1]
1221
1246
  #jr150316 xpath2.sub!(/^\*\//,'')
1222
1247
  #jr150316xpath2.sub!(/^\*/,self.name)
1223
1248
  #jr150316xpath2.sub!(/^\w+/,'').sub!(/^\//,'') if xpath2[/^\w+/] == self.name
@@ -1240,17 +1265,17 @@ class Rexle
1240
1265
  end
1241
1266
  a
1242
1267
  end
1243
-
1244
-
1268
+
1269
+
1245
1270
  def filter(raw_element, i, attr_search, &blk)
1246
-
1271
+
1247
1272
  x, index = raw_element
1248
1273
  e = @child_elements[index]
1249
1274
 
1250
1275
  return unless e.is_a? Rexle::Element
1251
1276
  name, value = e.name, e.value if e.is_a? Rexle::Element
1252
1277
 
1253
- h = x.attributes # <-- fetch the attributes
1278
+ h = x.attributes # <-- fetch the attributes
1254
1279
 
1255
1280
  if attr_search then
1256
1281
 
@@ -1266,21 +1291,21 @@ class Rexle
1266
1291
  def attribute_search(attr_search, e, h, i=nil, &blk)
1267
1292
 
1268
1293
  r2 = if attr_search.is_a? Integer then
1269
- block_given? ? blk.call(e) : e if i == attr_search
1294
+ block_given? ? blk.call(e) : e if i == attr_search
1270
1295
  elsif attr_search[/i\s(?:<|>|==|%)\s\d+/] and eval(attr_search) then
1271
- block_given? ? blk.call(e) : e
1296
+ block_given? ? blk.call(e) : e
1272
1297
  elsif h and !h.empty? and attr_search[/^h\[/] and eval(attr_search) then
1273
1298
  block_given? ? blk.call(e) : e
1274
- elsif attr_search[/^\(name ==/] and e.child_elements.select {|x|
1299
+ elsif attr_search[/^\(name ==/] and e.child_elements.select {|x|
1275
1300
  next unless x.is_a? Rexle::Element
1276
1301
  name, attributes, value = x.name, x.attributes, x.value.to_s
1277
1302
  b = eval(attr_search)
1278
1303
  b}.length > 0
1279
1304
 
1280
1305
  block_given? ? blk.call(e) : e
1281
-
1282
- elsif attr_search[/^\(name ==/] and eval(attr_search)
1283
- block_given? ? blk.call(e) : e
1306
+
1307
+ elsif attr_search[/^\(name ==/] and eval(attr_search)
1308
+ block_given? ? blk.call(e) : e
1284
1309
  elsif attr_search[/^e\.value/]
1285
1310
 
1286
1311
  v = attr_search[/[^\s]+$/]
@@ -1294,92 +1319,92 @@ class Rexle
1294
1319
  block_given? ? blk.call(e) : e
1295
1320
  elsif attr_search[/^\w*\(/] and e.element(attr_search)
1296
1321
  block_given? ? blk.call(e) : e
1297
- end
1322
+ end
1298
1323
 
1299
1324
  r2
1300
1325
  end
1301
-
1326
+
1302
1327
  def recursive_scan(nodes, &blk)
1303
-
1328
+
1304
1329
  nodes.each do |x|
1305
1330
 
1306
1331
  if x.is_a? Rexle::Element then
1307
1332
  blk.call(x)
1308
1333
  recursive_scan(x.children, &blk) if x.children.length > 0
1309
- end
1334
+ end
1310
1335
  end
1311
1336
  end
1312
-
1337
+
1313
1338
  end # -- end of element --
1314
-
1339
+
1315
1340
 
1316
1341
  class CData
1317
-
1342
+
1318
1343
  def initialize(val='')
1319
1344
  @value = val
1320
1345
  end
1321
-
1346
+
1322
1347
  def clone()
1323
1348
  CData.new(@value)
1324
1349
  end
1325
-
1350
+
1326
1351
  def inspect()
1327
1352
  @value.inspect
1328
1353
  end
1329
-
1354
+
1330
1355
  def print()
1331
1356
  "<![CDATA[%s]]>" % @value
1332
1357
  end
1333
-
1358
+
1334
1359
  def to_s()
1335
1360
  @value
1336
1361
  end
1337
-
1362
+
1338
1363
  def unescape()
1339
1364
  s = @value.clone
1340
1365
  %w(&lt; < &gt; > &amp; & &apos; ').each_slice(2){|x| s.gsub!(*x)}
1341
1366
  s
1342
- end
1343
-
1367
+ end
1368
+
1344
1369
  end
1345
-
1346
-
1370
+
1371
+
1347
1372
  class Comment
1348
-
1373
+
1349
1374
 
1350
1375
  def initialize(val='')
1351
1376
  @e = Element.new('_').add_text val
1352
1377
  @value = val
1353
1378
  end
1354
-
1379
+
1355
1380
  def add_element(e2)
1356
1381
  @e.add e2
1357
1382
  end
1358
-
1383
+
1359
1384
  def add_text(t)
1360
1385
  @e.add_text t
1361
1386
  end
1362
-
1387
+
1363
1388
  def inspect()
1364
1389
  @value
1365
1390
  end
1366
-
1391
+
1367
1392
  def print()
1368
1393
  "<!--%s-->" % @e.root.xpath('//./text()').join
1369
1394
  end
1370
-
1395
+
1371
1396
  def texts()
1372
1397
  @e.texts
1373
1398
  end
1374
-
1399
+
1375
1400
  def to_s()
1376
1401
  @value
1377
1402
  end
1378
1403
  end
1379
-
1404
+
1380
1405
  class Elements
1381
1406
  include Enumerable
1382
-
1407
+
1383
1408
  def initialize(elements=[])
1384
1409
  super()
1385
1410
  @elements = elements
@@ -1391,63 +1416,63 @@ class Rexle
1391
1416
  i = raw_i - 1
1392
1417
  @elements[i]
1393
1418
  end
1394
-
1419
+
1395
1420
  def each(&blk) @elements.each(&blk) end
1396
1421
  def empty?() @elements.empty? end
1397
-
1422
+
1398
1423
  def index(e=nil, &blk)
1399
-
1424
+
1400
1425
  if block_given? then
1401
1426
  @elements.index(&blk)
1402
1427
  else
1403
1428
  @elements.index e
1404
1429
  end
1405
1430
  end
1406
-
1431
+
1407
1432
  def last() @elements.last end
1408
1433
  def length() @elements.length end
1409
1434
  def to_a() @elements end
1410
-
1435
+
1411
1436
  end # -- end of elements --
1412
1437
 
1413
1438
 
1414
1439
  def parse(x=nil)
1415
-
1440
+
1416
1441
  a = []
1417
-
1442
+
1418
1443
  if x then
1419
1444
  procs = {
1420
1445
  String: proc {|x| parse_string(x)},
1421
1446
  Array: proc {|x| x}
1422
1447
  }
1423
1448
  a = procs[x.class.to_s.to_sym].call(x)
1424
- else
1449
+ else
1425
1450
  a = yield
1426
1451
  end
1427
-
1452
+
1428
1453
  doc_node = ['doc',Attributes.new]
1429
1454
  @a = procs[x.class.to_s.to_sym].call(x)
1430
1455
  @doc = scan_element(*(doc_node << @a))
1431
-
1456
+
1432
1457
  self
1433
1458
  end
1434
1459
 
1435
1460
  def add_attribute(x) @doc.attribute(x) end
1436
1461
  def attribute(key) @doc.attribute(key) end
1437
1462
  def attributes() @doc.attributes end
1438
-
1439
- def add_element(element)
1440
1463
 
1441
- if @doc then
1464
+ def add_element(element)
1465
+
1466
+ if @doc then
1442
1467
  raise 'attempted adding second root element to document' if @doc.root
1443
- @doc.root.add_element(element)
1468
+ @doc.root.add_element(element)
1444
1469
  else
1445
- doc_node = ['doc', Attributes.new, element.to_a]
1446
- @doc = scan_element(*doc_node)
1470
+ doc_node = ['doc', Attributes.new, element.to_a]
1471
+ @doc = scan_element(*doc_node)
1447
1472
  end
1448
1473
  element
1449
1474
  end
1450
-
1475
+
1451
1476
  def add_text(s) end
1452
1477
 
1453
1478
  alias add add_element
@@ -1457,26 +1482,26 @@ class Rexle
1457
1482
  @doc.xpath(xpath).each {|e| e.delete; e = nil }
1458
1483
 
1459
1484
  end
1460
-
1485
+
1461
1486
  alias remove delete
1462
1487
 
1463
- def element(xpath) self.xpath(xpath).first end
1488
+ def element(xpath) self.xpath(xpath).first end
1464
1489
  def elements(s=nil) @doc.elements(s) end
1465
1490
  def name() @doc.root.name end
1466
1491
  def to_a() @a end
1467
-
1468
- def to_s(options={})
1492
+
1493
+ def to_s(options={})
1469
1494
  return '<UNDEFINED/>' unless @doc
1470
- self.xml options
1495
+ self.xml options
1471
1496
  end
1472
-
1497
+
1473
1498
  def text(xpath) @doc.text(xpath) end
1474
- def root()
1475
- @doc.elements.first
1499
+ def root()
1500
+ @doc.elements.first
1476
1501
  end
1477
1502
 
1478
- def write(f)
1479
- f.write xml
1503
+ def write(f)
1504
+ f.write xml
1480
1505
  end
1481
1506
 
1482
1507
  def xml(options={})
@@ -1505,14 +1530,14 @@ class Rexle
1505
1530
  private
1506
1531
 
1507
1532
  def parse_rexle(x)
1508
-
1533
+
1509
1534
  rp = RexleParser.new(x)
1510
1535
  a = rp.to_a
1511
1536
 
1512
1537
  @instructions = rp.instructions
1513
- return a
1538
+ return a
1514
1539
  end
1515
-
1540
+
1516
1541
  def parse_string(x)
1517
1542
 
1518
1543
  # check if the XML string is a dynarex document
@@ -1528,50 +1553,50 @@ class Rexle
1528
1553
  'polyrex' => proc {|x| parse_rexle(x)}
1529
1554
  }
1530
1555
  other_parser = procs[recordx_type]
1531
-
1556
+
1532
1557
  if other_parser then
1533
-
1558
+
1534
1559
  begin
1535
1560
  other_parser.call(x)
1536
1561
  rescue
1537
1562
  parse_rexle x
1538
1563
  end
1539
-
1564
+
1540
1565
  else
1541
-
1566
+
1542
1567
  parse_rexle x
1543
-
1544
- end
1545
-
1568
+
1569
+ end
1570
+
1546
1571
  else
1547
1572
 
1548
1573
  parse_rexle x
1549
-
1574
+
1550
1575
  end
1551
1576
  else
1552
1577
 
1553
1578
  parse_rexle x
1554
-
1579
+
1555
1580
  end
1556
1581
 
1557
1582
  end
1558
-
1583
+
1559
1584
  def scan_element(name=nil, attributes=nil, *children)
1560
-
1585
+
1561
1586
  return unless name
1562
-
1587
+
1563
1588
  return Rexle::CData.new(children.first) if name == '!['
1564
1589
  return Rexle::Comment.new(children.first) if name == '!-'
1565
1590
 
1566
- element = Rexle::Element.new(name, attributes: attributes, rexle: @rexle)
1591
+ element = Rexle::Element.new(name, attributes: attributes, rexle: @rexle)
1567
1592
 
1568
1593
  if children then
1569
1594
 
1570
1595
  children.each do |x4|
1571
-
1596
+
1572
1597
 
1573
1598
  if x4.is_a? Array then
1574
- element.add_element scan_element(*x4)
1599
+ element.add_element scan_element(*x4)
1575
1600
  elsif x4.is_a? String then
1576
1601
 
1577
1602
  e = if x4.is_a? String then
@@ -1580,22 +1605,22 @@ class Rexle
1580
1605
  elsif x4.name == '![' then
1581
1606
 
1582
1607
  Rexle::CData.new(x4)
1583
-
1608
+
1584
1609
  elsif x4.name == '!-' then
1585
1610
 
1586
1611
  Rexle::Comment.new(x4)
1587
-
1612
+
1588
1613
  end
1589
1614
 
1590
1615
  element.add_element e
1591
1616
  end
1592
1617
  end
1593
1618
  end
1594
-
1619
+
1595
1620
  return element
1596
1621
  end
1597
1622
 
1598
-
1623
+
1599
1624
  # scan a rexml doc
1600
1625
  #
1601
1626
  def scan_doc(node)
@@ -1603,28 +1628,28 @@ class Rexle
1603
1628
  attributes = node.attributes.inject({}){|r,x| r.merge(Hash[*x])}
1604
1629
  [node.name, node.text.to_s, attributes, *children]
1605
1630
  end
1606
-
1631
+
1607
1632
  class Recordset < Array
1608
1633
 
1609
1634
  def initialize(a)
1610
1635
  super(a)
1611
1636
  end
1612
-
1637
+
1613
1638
  def to_doc(root: 'root')
1614
-
1639
+
1615
1640
  recordset = self.map(&:to_a)
1616
1641
  Rexle.new([root,{}, *recordset])
1617
-
1642
+
1618
1643
  end
1619
-
1644
+
1620
1645
  def xpath(xpath)
1621
1646
  self.to_doc.root.xpath(xpath)
1622
1647
  end
1623
-
1648
+
1624
1649
  def element(xpath)
1625
1650
  self.to_doc.root.element(xpath)
1626
1651
  end
1627
1652
 
1628
- end
1629
-
1653
+ end
1654
+
1630
1655
  end