dynarex 1.8.27 → 1.9.3

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/dynarex.rb +352 -325
  4. data.tar.gz.sig +0 -0
  5. metadata +58 -58
  6. metadata.gz.sig +0 -0
data/lib/dynarex.rb CHANGED
@@ -30,7 +30,7 @@ hkey_gems
30
30
  require dynarex
31
31
  class Dynarex
32
32
  media_type dynarex
33
- '
33
+ '
34
34
  end
35
35
  end
36
36
 
@@ -39,35 +39,35 @@ class DynarexException < Exception
39
39
  end
40
40
 
41
41
  class DynarexRecordset < Array
42
-
42
+
43
43
  def initialize(a, caller=nil)
44
44
  super(a)
45
45
  @caller = caller
46
46
  end
47
-
47
+
48
48
  def reject!()
49
-
49
+
50
50
  a = self.to_a.clone
51
51
  a2 = super
52
52
  return nil unless a2
53
53
  a3 = a - a2
54
-
54
+
55
55
  @caller.delete a3.map(&:id)
56
56
  self
57
57
  end
58
-
58
+
59
59
  def sum(field)
60
60
  self.inject(0) {|r, x| r + x[field.to_sym][/\d+(\.\d+)?$/].to_f }
61
61
  end
62
-
63
- def index(val)
62
+
63
+ def index(val)
64
64
  self.map(&:to_h).index val.to_h
65
65
  end
66
-
67
- def index_by_id(id)
66
+
67
+ def index_by_id(id)
68
68
  self.map(&:id).index id
69
- end
70
-
69
+ end
70
+
71
71
  end
72
72
 
73
73
 
@@ -77,8 +77,8 @@ class Dynarex
77
77
 
78
78
  attr_accessor :format_mask, :delimiter, :xslt_schema, :schema, :linked,
79
79
  :order, :type, :limit, :xslt, :json_out, :unique
80
-
81
-
80
+
81
+
82
82
  #Create a new dynarex document from 1 of the following options:
83
83
  #* a local file path
84
84
  #* a URL
@@ -87,18 +87,18 @@ class Dynarex
87
87
  #* an XML string
88
88
  # Dynarex.new '<contacts><summary><schema>contacts/contact(name,age,dob)</schema></summary><records/></contacts>'
89
89
 
90
- def initialize(rawx=nil, username: nil, password: nil, schema: nil,
91
- default_key: nil, json_out: true, debug: false,
92
- delimiter: ' # ', autosave: false, order: 'ascending',
90
+ def initialize(rawx=nil, username: nil, password: nil, schema: nil,
91
+ default_key: nil, json_out: true, debug: false,
92
+ delimiter: ' # ', autosave: false, order: 'ascending',
93
93
  unique: false, filepath: nil)
94
94
 
95
95
 
96
96
  puts 'inside Dynarex::initialize' if debug
97
- @username, @password, @schema, @default_key, @json_out, @debug = \
98
- username, password, schema, default_key, json_out, debug
97
+ @username, @password, @schema, = username, password, schema
98
+ @default_key, @json_out, @debug = default_key, json_out, debug
99
99
  @autosave, @unique = autosave, unique
100
100
  @local_filepath = filepath
101
-
101
+
102
102
  puts ('@debug: ' + @debug.inspect).debug if debug
103
103
  @delimiter = delimiter
104
104
  @spaces_delimited = false
@@ -108,12 +108,12 @@ class Dynarex
108
108
  rawx ||= schema if schema
109
109
 
110
110
  if rawx then
111
-
111
+
112
112
  return import(rawx) if rawx =~ /\.txt$/
113
- openx(rawx.clone)
114
-
113
+ openx(rawx.clone)
114
+
115
115
  end
116
-
116
+
117
117
  self.order = @order unless @order.to_sym == :ascending
118
118
 
119
119
  end
@@ -125,17 +125,17 @@ class Dynarex
125
125
  end
126
126
 
127
127
  def all()
128
-
128
+
129
129
  refresh! if @dirty_flag
130
130
  a = @doc.root.xpath("records/*").map {|x| recordx_to_record x}
131
131
  DynarexRecordset.new(a, self)
132
-
132
+
133
133
  end
134
-
134
+
135
135
  def clone()
136
136
  Dynarex.new(self.to_xml)
137
137
  end
138
-
138
+
139
139
  def default_key()
140
140
  self.summary[:default_key]
141
141
  end
@@ -146,10 +146,10 @@ class Dynarex
146
146
  @spaces_delimited = true
147
147
  separator = ' # '
148
148
  end
149
-
149
+
150
150
  @delimiter = separator
151
151
 
152
- if separator.length > 0 then
152
+ if separator.length > 0 then
153
153
  @summary[:delimiter] = separator
154
154
  else
155
155
  @summary.delete :delimiter
@@ -158,14 +158,14 @@ class Dynarex
158
158
  @format_mask = @format_mask.to_s.gsub(/\s/, separator)
159
159
  @summary[:format_mask] = @format_mask
160
160
  end
161
-
161
+
162
162
  def doc
163
163
  (load_records; rebuild_doc) if @dirty_flag == true
164
164
  @doc
165
- end
165
+ end
166
166
 
167
167
  # XML import
168
- #
168
+ #
169
169
  def foreign_import(options={})
170
170
  o = {xml: '', schema: ''}.merge(options)
171
171
  h = {xml: o[:xml], schema: @schema, foreign_schema: o[:schema]}
@@ -174,21 +174,21 @@ class Dynarex
174
174
  openx(buffer)
175
175
  self
176
176
  end
177
-
177
+
178
178
  def fields
179
179
  @fields
180
180
  end
181
-
181
+
182
182
  def first
183
183
  r = @doc.root.element("records/*")
184
- r ? recordx_to_record(r) : nil
184
+ r ? recordx_to_record(r) : nil
185
185
  end
186
186
 
187
187
  def format_mask=(s)
188
188
  @format_mask = s
189
189
  @summary[:format_mask] = @format_mask
190
190
  end
191
-
191
+
192
192
  def insert(raw_params)
193
193
  record = make_record(raw_params)
194
194
  @doc.root.element('records/*').insert_before record
@@ -198,32 +198,32 @@ class Dynarex
198
198
  def inspect()
199
199
  "<object #%s>" % [self.object_id]
200
200
  end
201
-
201
+
202
202
  def linked=(bool)
203
203
  @linked = bool == 'true'
204
204
  end
205
-
205
+
206
206
  def order=(value)
207
-
208
- self.summary.merge!({order: value.to_s})
207
+
208
+ self.summary.merge!({order: value.to_s})
209
209
 
210
210
  @order = value.to_s
211
211
  end
212
-
212
+
213
213
  def recordx_type()
214
214
  @summary[:recordx_type]
215
215
  end
216
-
216
+
217
217
  def schema=(s)
218
218
  openx s
219
219
  end
220
-
220
+
221
221
  def type=(v)
222
222
  @order = 'descending' if v == 'feed'
223
223
  @type = v
224
224
  @summary[:type] = v
225
225
  end
226
-
226
+
227
227
  # Returns the hash representation of the document summary.
228
228
  #
229
229
  def summary
@@ -233,29 +233,29 @@ class Dynarex
233
233
  # Return a Hash (which can be edited) containing all records.
234
234
  #
235
235
  def records
236
-
236
+
237
237
  load_records if @dirty_flag == true
238
-
238
+
239
239
  if block_given? then
240
240
  yield(@records)
241
241
  rebuild_doc
242
- @dirty_flag = true
242
+ @dirty_flag = true
243
243
  else
244
244
  @records
245
245
  end
246
-
246
+
247
247
  end
248
-
249
- # Returns a ready-only snapshot of records as a simple Hash.
248
+
249
+ # Returns a ready-only snapshot of records as a simple Hash.
250
250
  #
251
251
  def flat_records(select: nil)
252
-
252
+
253
253
  fields = select
254
-
254
+
255
255
  load_records if @dirty_flag == true
256
256
 
257
257
  if fields then
258
-
258
+
259
259
  case fields.class.to_s.downcase.to_sym
260
260
  when :string
261
261
  field = fields.to_sym
@@ -267,58 +267,58 @@ class Dynarex
267
267
  @flat_records.map {|row| fields.inject({})\
268
268
  {|r,x| r.merge(x.to_sym => row[x.to_sym])}}
269
269
  end
270
-
270
+
271
271
  else
272
272
  @flat_records
273
273
  end
274
-
274
+
275
275
  end
276
-
276
+
277
277
  alias to_a flat_records
278
-
278
+
279
279
  # Returns an array snapshot of OpenStruct records
280
280
  #
281
281
  def ro_records
282
282
  flat_records.map {|record| OpenStruct.new record }
283
283
  end
284
-
284
+
285
285
  def rm(force: false)
286
-
286
+
287
287
  if force or all.empty? then
288
288
  FileX.rm @local_filepath if @local_filepath
289
289
  'file ' + @local_filepath + ' deleted'
290
290
  else
291
291
  'unable to rm file: document not empty'
292
292
  end
293
-
293
+
294
294
  end
295
-
296
295
 
297
- def to_doc
296
+
297
+ def to_doc
298
298
  self.clone().doc
299
299
  end
300
-
300
+
301
301
  # Typically uses the 1st field as a key and the remaining fields as the value
302
302
  #
303
303
  def to_h()
304
-
304
+
305
305
  key = self.default_key.to_sym
306
306
  fields = self.fields() - [key]
307
307
  puts 'fields: ' + fields.inspect if @debug
308
-
309
- flat_records.inject({}) do |r, h|
310
-
308
+
309
+ flat_records.inject({}) do |r, h|
310
+
311
311
  puts 'h: ' + h.inspect if @debug
312
-
312
+
313
313
  value = if h.length == 2 then
314
314
  h[fields[0]].to_s
315
315
  else
316
- fields.map {|x| h[x]}
316
+ fields.map {|x| h[x]}
317
317
  end
318
-
318
+
319
319
  r.merge(h[key] => value)
320
320
  end
321
-
321
+
322
322
  end
323
323
 
324
324
  def to_html(domain: '')
@@ -327,32 +327,32 @@ class Dynarex
327
327
  xsl_buffer = RXFHelper.read(domain + @xslt, h).first
328
328
  Rexslt.new(xsl_buffer, self.to_doc).to_s
329
329
 
330
- end
331
-
332
-
333
- # to_json: pretty is set to true because although the file size is larger,
330
+ end
331
+
332
+
333
+ # to_json: pretty is set to true because although the file size is larger,
334
334
  # the file can be load slightly quicker
335
-
335
+
336
336
  def to_json(pretty: true)
337
-
337
+
338
338
  records = self.to_a
339
339
  summary = self.summary.to_h
340
-
340
+
341
341
  root_name = schema()[/^\w+/]
342
342
  record_name = schema()[/(?<=\/)[^\(]+/]
343
-
343
+
344
344
  h = {
345
345
  root_name.to_sym =>
346
346
  {
347
347
  summary: @summary,
348
- records: @records.map {|_, h| {record_name.to_sym => h} }
348
+ records: @records.map {|_, h| {record_name.to_sym => h} }
349
349
  }
350
350
  }
351
-
351
+
352
352
  pretty ? JSON.pretty_generate(h) : h.to_json
353
-
353
+
354
354
  end
355
-
355
+
356
356
  def to_s(header: true, delimiter: @delimiter)
357
357
 
358
358
  xsl_buffer =<<EOF
@@ -373,22 +373,22 @@ EOF
373
373
 
374
374
  raw_summary_fields = self.summary[:schema][/^\w+\[([^\]]+)\]/,1]
375
375
  sumry = ''
376
-
376
+
377
377
  if raw_summary_fields then
378
- summary_fields = raw_summary_fields.split(',') # .map(&:to_sym)
378
+ summary_fields = raw_summary_fields.split(',') # .map(&:to_sym)
379
379
  sumry = summary_fields.map {|x| x.strip!; x + ': ' + \
380
380
  self.summary[x.to_sym].to_s}.join("\n") + "\n\n"
381
381
  end
382
-
382
+
383
383
  if @raw_header then
384
384
  declaration = @raw_header
385
385
  else
386
386
 
387
- smry_fields = %i(schema)
387
+ smry_fields = %i(schema)
388
388
  smry_fields << :order if self.summary[:order] == 'descending'
389
-
389
+
390
390
  if delimiter.length > 0 then
391
- smry_fields << :delimiter
391
+ smry_fields << :delimiter
392
392
  else
393
393
  smry_fields << :format_mask unless self.summary[:rawdoc_type] == 'rowx'
394
394
  end
@@ -406,44 +406,44 @@ EOF
406
406
  <xsl:text>\n</xsl:text>%s:<xsl:text> </xsl:text><xsl:value-of select='%s'/>
407
407
  </xsl:if>" % ([field]*3)
408
408
  end
409
-
409
+
410
410
  puts ('a: ' + a.inspect).debug if @debug
411
411
 
412
- xslt_format = a.join
412
+ xslt_format = a.join
413
413
 
414
414
  xsl_buffer.sub!(/\[!regex_values\]/, xslt_format)
415
-
415
+
416
416
  if @debug then
417
417
  File.write '/tmp/foo.xsl', xsl_buffer
418
418
  File.write '/tmp/foo.xml', @doc.xml
419
419
  puts 'xsl_buffer: ' + xsl_buffer.inspect
420
420
  end
421
-
421
+
422
422
  out = Rexslt.new(xsl_buffer, @doc).to_s
423
-
423
+
424
424
  docheader + "\n--+\n" + out
425
- elsif self.summary[:rawdoc_type] == 'sectionx' then
426
-
425
+ elsif self.summary[:rawdoc_type] == 'sectionx' then
426
+
427
427
  a = (self.fields - [:uid, 'uid']).map do |field|
428
428
  "<xsl:if test=\"%s != ''\">
429
429
  <xsl:text>\n</xsl:text><xsl:value-of select='%s'/>
430
430
  </xsl:if>" % ([field]*2)
431
431
  end
432
432
 
433
- xslt_format = a.join
433
+ xslt_format = a.join
434
434
 
435
435
  xsl_buffer.sub!(/\[!regex_values\]/, xslt_format)
436
436
  puts 'xsl_buffer: ' + xsl_buffer.inspect if @debug
437
437
 
438
438
  out = Rexslt.new(xsl_buffer, @doc).to_s
439
-
439
+
440
440
  header ? docheader + "--#\n" + out : out
441
-
441
+
442
442
  elsif self.delimiter.length > 0 then
443
443
  puts 'dinddd'
444
444
  tfo = TableFormatter.new border: false, wrap: false, \
445
445
  divider: self.delimiter
446
- tfo.source = self.to_a.map{|x| x.values}
446
+ tfo.source = self.to_a.map{|x| x.values}
447
447
  docheader + tfo.display.strip
448
448
 
449
449
  else
@@ -454,7 +454,7 @@ EOF
454
454
  s1, s2 = '<xsl:text>', '</xsl:text>'
455
455
  xslt_format = s1 + format_mask\
456
456
  .gsub(/(?:\[!(\w+)\])/, s2 + '<xsl:value-of select="\1"/>' + s1) + s2
457
-
457
+
458
458
  xsl_buffer.sub!(/\[!regex_values\]/, xslt_format)
459
459
 
460
460
  puts 'xsl_buffer: ' + xsl_buffer if @debug
@@ -466,7 +466,7 @@ EOF
466
466
  end
467
467
 
468
468
  def to_table(fields: nil, markdown: false, innermarkdown: false, heading: true)
469
-
469
+
470
470
  tfo = TableFormatter.new markdown: markdown, innermarkdown: innermarkdown
471
471
  tfo.source = self.to_a.map {|h| fields ? fields.map {|x| h[x]} : h.values }
472
472
 
@@ -475,59 +475,59 @@ EOF
475
475
  fields = raw_headings.split(self.delimiter) if raw_headings and fields.nil?
476
476
  tfo.labels = (fields ? fields : self.fields.map{|x| x.to_s.capitalize })
477
477
  end
478
-
478
+
479
479
  tfo
480
-
480
+
481
481
  end
482
-
483
- def to_xml(opt={})
482
+
483
+ def to_xml(opt={})
484
484
  opt = {pretty: true} if opt == :pretty
485
485
  display_xml(opt)
486
486
  end
487
-
488
- # Save the document to a file.
489
-
487
+
488
+ # Save the document to a file.
489
+
490
490
  def save(filepath=@local_filepath, options={})
491
-
491
+
492
492
  if @debug then
493
- puts 'inside Dynarex::save'
493
+ puts 'inside Dynarex::save'
494
494
  puts 'filepath: ' + filepath.inspect
495
495
 
496
496
  end
497
-
497
+
498
498
  return unless filepath
499
-
499
+
500
500
  opt = {pretty: true}.merge options
501
501
 
502
502
  @local_filepath = filepath || 'dx.xml'
503
503
  xml = display_xml(opt)
504
504
  buffer = block_given? ? yield(xml) : xml
505
-
505
+
506
506
  if @debug then
507
507
  puts 'before write; filepath: ' + filepath.inspect
508
508
  puts 'buffer: ' + buffer.inspect
509
509
  end
510
-
510
+
511
511
  FileX.write filepath, buffer
512
512
  FileX.write(filepath.sub(/\.xml$/,'.json'), self.to_json) if @json_out
513
513
  end
514
-
514
+
515
515
  #Parses 1 or more lines of text to create or update existing records.
516
516
 
517
517
  def parse(x=nil)
518
518
 
519
519
  @dirty_flag = true
520
-
520
+
521
521
  if x.is_a? Array then
522
-
522
+
523
523
  unless @schema then
524
- cols = x.first.keys.map {|c| c == 'id' ? 'uid' : c}
524
+ cols = x.first.keys.map {|c| c == 'id' ? 'uid' : c}
525
525
  self.schema = "items/item(%s)" % cols.join(', ')
526
526
  end
527
-
527
+
528
528
  x.each {|record| self.create record }
529
- return self
530
-
529
+ return self
530
+
531
531
  end
532
532
  raw_buffer, type = RXFHelper.read(x, auto: false)
533
533
 
@@ -535,15 +535,15 @@ EOF
535
535
 
536
536
  buffer = block_given? ? yield(raw_buffer) : raw_buffer.clone
537
537
  string_parse buffer
538
-
538
+
539
539
  else
540
540
  foreign_import x
541
541
  end
542
-
543
- end
542
+
543
+ end
544
544
 
545
545
 
546
- alias import parse
546
+ alias import parse
547
547
 
548
548
  #Create a record from a hash containing the field name, and the field value.
549
549
  # dynarex = Dynarex.new 'contacts/contact(name,age,dob)'
@@ -553,8 +553,8 @@ EOF
553
553
 
554
554
  puts 'inside create' if @debug
555
555
  raise 'Dynarex#create(): input error: no arg provided' unless obj
556
-
557
- case obj.class.to_s.downcase.to_sym
556
+
557
+ case obj.class.to_s.downcase.to_sym
558
558
  when :hash
559
559
  hash_create obj, id, attr: custom_attributes
560
560
  when :string
@@ -566,7 +566,7 @@ EOF
566
566
  end
567
567
 
568
568
  @dirty_flag = true
569
-
569
+
570
570
  puts 'before save ' + @autosave.inspect if @debug
571
571
  save() if @autosave
572
572
 
@@ -575,13 +575,13 @@ EOF
575
575
 
576
576
  #Create a record from a string, given the dynarex document contains a format mask.
577
577
  # dynarex = Dynarex.new 'contacts/contact(name,age,dob)'
578
- # dynarex.create_from_line 'Tracy 37 15-Jun-1972'
579
-
578
+ # dynarex.create_from_line 'Tracy 37 15-Jun-1972'
579
+
580
580
  def create_from_line(line, id=nil, attr: '')
581
581
  t = @format_mask.to_s.gsub(/\[!(\w+)\]/, '(.*)').sub(/\[/,'\[')\
582
582
  .sub(/\]/,'\]')
583
583
  line.match(/#{t}/).captures
584
-
584
+
585
585
  a = line.match(/#{t}/).captures
586
586
  h = Hash[@fields.zip(a)]
587
587
  create h
@@ -596,8 +596,8 @@ EOF
596
596
 
597
597
 
598
598
  #Updates a record from an id and a hash containing field name and field value.
599
- # dynarex.update 4, name: Jeff, age: 38
600
-
599
+ # dynarex.update 4, name: Jeff, age: 38
600
+
601
601
  def update(id, obj)
602
602
 
603
603
  params = if obj.is_a? Hash then
@@ -605,32 +605,32 @@ EOF
605
605
  elsif obj.is_a? RecordX
606
606
  obj.to_h
607
607
  end
608
-
608
+
609
609
  fields = capture_fields(params)
610
610
 
611
611
  # for each field update each record field
612
- record = @doc.root.element("records/#{@record_name}[@id='#{id.to_s}']")
612
+ record = @doc.root.element("records/#{@record_name}[@id='#{id.to_s}']")
613
613
 
614
614
  fields.each do |k,v|
615
615
  puts "updating ... %s = '%s'" % [k,v] if @debug
616
616
  record.element(k.to_s).text = v if v
617
617
  end
618
-
618
+
619
619
  record.add_attribute(last_modified: Time.now.to_s)
620
620
 
621
621
  @dirty_flag = true
622
622
 
623
623
  save() if @autosave
624
-
624
+
625
625
  self
626
626
 
627
627
  end
628
628
 
629
-
629
+
630
630
  #Delete a record.
631
631
  # dyarex.delete 3 # deletes record with id 3
632
-
633
- def delete(x)
632
+
633
+ def delete(x)
634
634
 
635
635
  return x.each {|id| self.delete id} if x.is_a? Array
636
636
 
@@ -639,86 +639,86 @@ EOF
639
639
  else
640
640
  @doc.delete x
641
641
  end
642
-
642
+
643
643
  @dirty_flag = true
644
644
  save() if @autosave
645
-
645
+
646
646
  self
647
647
  end
648
648
 
649
649
  def element(x)
650
650
  @doc.root.element x
651
- end
652
-
651
+ end
652
+
653
653
  def sort_by!(field=nil, &element_blk)
654
654
 
655
655
  blk = field ? ->(x){ x.text(field.to_s).to_s} : element_blk
656
656
  r = sort_records_by! &blk
657
- @dirty_flag = true
657
+ @dirty_flag = true
658
658
  r
659
659
 
660
- end
660
+ end
661
+
661
662
 
662
-
663
663
  def record(id)
664
- e = @doc.root.element("records/*[@id='#{id}']")
664
+ e = @doc.root.element("records/*[@id='#{id}']")
665
665
  recordx_to_record e if e
666
666
  end
667
-
667
+
668
668
  alias find record
669
669
  alias find_by_id record
670
670
 
671
671
  def record_exists?(id)
672
672
  !@doc.root.element("records/*[@id='#{id}']").nil?
673
673
  end
674
-
674
+
675
675
  def refresh()
676
676
  @dirty_flag = true
677
677
  end
678
-
678
+
679
679
  def refresh!()
680
- (load_records; rebuild_doc) if @dirty_flag == true
680
+ (load_records; rebuild_doc) if @dirty_flag == true
681
681
  end
682
-
682
+
683
683
  # used internally by to_rss()
684
684
  #
685
685
  def rss_xslt(opt={})
686
-
686
+
687
687
  h = {limit: 11}.merge(opt)
688
688
  doc = Rexle.new(self.to_xslt)
689
689
  e = doc.element('//xsl:apply-templates[2]')
690
-
690
+
691
691
  e2 = doc.root.element('xsl:template[3]')
692
692
  item = e2.element('item')
693
693
  new_item = item.deep_clone
694
694
  item.delete
695
-
695
+
696
696
  pubdate = @xslt_schema[/pubDate:/]
697
697
  xslif = Rexle.new("<xsl:if test='position() &lt; #{h[:limit]}'/>").root
698
698
 
699
699
  if pubdate.nil? then
700
700
  pubdate = Rexle.new("<pubDate><xsl:value-of select='pubDate'>" + \
701
701
  "</xsl:value-of></pubDate>").root
702
- new_item.add pubdate
702
+ new_item.add pubdate
703
703
  end
704
704
 
705
- xslif.add new_item
705
+ xslif.add new_item
706
706
  e2.add xslif.root
707
- xslt = doc.xml
707
+ xslt = doc.xml
708
+
709
+ xslt
708
710
 
709
- xslt
710
-
711
711
  end
712
-
712
+
713
713
  def filter(&blk)
714
-
714
+
715
715
  dx = Dynarex.new @schema
716
716
  self.all.select(&blk).each {|x| dx.create x}
717
717
  dx
718
-
718
+
719
719
  end
720
720
 
721
- def to_xslt(opt={})
721
+ def to_xslt(opt={})
722
722
 
723
723
  h = {limit: -1}.merge(opt)
724
724
  @xslt_schema = @xslt_schema || self.summary[:xslt_schema]
@@ -728,47 +728,47 @@ EOF
728
728
 
729
729
  return xslt
730
730
  end
731
-
731
+
732
732
  def to_rss(opt={}, xslt=nil)
733
-
733
+
734
734
  puts 'inside to_rss'.info if @debug
735
-
735
+
736
736
  unless xslt then
737
-
737
+
738
738
  h = {limit: 11}.merge(opt)
739
739
  doc = Rexle.new(self.to_xslt)
740
740
  e = doc.element('//xsl:apply-templates[2]')
741
-
741
+
742
742
  e2 = doc.root.element('xsl:template[3]')
743
743
  item = e2.element('item')
744
744
  new_item = item.deep_clone
745
745
  item.delete
746
-
746
+
747
747
  pubdate = @xslt_schema[/pubDate:/]
748
748
  xslif = Rexle.new("<xsl:if test='position() &lt; #{h[:limit]}'/>").root
749
-
750
-
749
+
750
+
751
751
  if pubdate.nil? then
752
752
  pubdate2 = Rexle.new("<pubDate><xsl:value-of select='pubDate'></xsl:value-of></pubDate>").root
753
- new_item.add pubdate2
753
+ new_item.add pubdate2
754
754
  end
755
755
 
756
- xslif.add new_item
756
+ xslif.add new_item
757
757
  e2.add xslif
758
- xslt = doc.xml
758
+ xslt = doc.xml
759
759
 
760
760
  xslt
761
761
  end
762
-
762
+
763
763
  doc = Rexle.new(self.to_xml)
764
-
764
+
765
765
  puts ('pubdate: ' + pubdate.inspect).debug if @debug
766
-
766
+
767
767
  if pubdate.nil? then
768
768
  doc.root.xpath('records/*').each do |x|
769
769
  raw_dt = DateTime.parse x.attributes[:created]
770
770
  dt = raw_dt.strftime("%a, %d %b %Y %H:%M:%S %z")
771
- x.add Rexle::Element.new('pubDate').add_text dt.to_s
771
+ x.add Rexle::Element.new('pubDate').add_text dt.to_s
772
772
  end
773
773
  end
774
774
 
@@ -776,7 +776,7 @@ EOF
776
776
  File.write '/tmp/blog.xml', doc.root.xml
777
777
  puts ('xslt:' + xslt.inspect) if @debug
778
778
  File.write '/tmp/blog.xslt', xslt
779
-
779
+
780
780
  out = Rexslt.new(xslt, doc).to_s(declaration: false)
781
781
 
782
782
  #Rexle.new("<rss version='2.0'>%s</rss>" % xml).xml(pretty: true)
@@ -786,23 +786,23 @@ EOF
786
786
  xml = doc.xml(pretty: true)
787
787
  xml
788
788
  end
789
-
789
+
790
790
  def unique=(bool)
791
791
  self.summary.merge!({unique: bool})
792
792
  @dirty_flag = true
793
793
  @unique = bool
794
794
  end
795
-
795
+
796
796
  def xpath(x)
797
797
  @doc.root.xpath x
798
798
  end
799
799
 
800
800
  def xslt=(value)
801
-
801
+
802
802
  self.summary.merge!({xslt: value})
803
803
  @dirty_flag = true
804
804
  @xslt = value
805
- end
805
+ end
806
806
 
807
807
  private
808
808
 
@@ -810,7 +810,7 @@ EOF
810
810
  @default_key = :uid
811
811
  @summary[:default_key] = 'uid'
812
812
  @fields << :uid
813
- a.each.with_index{|x,i| x << (i+1).to_s}
813
+ a.each.with_index{|x,i| x << (i+1).to_s}
814
814
  end
815
815
 
816
816
  def create_find(fields)
@@ -823,21 +823,42 @@ EOF
823
823
  end
824
824
 
825
825
  def findx_by(field, value)
826
+
826
827
  #@logger.debug "field: #{field.inspect}, value: #{value.inspect}"
827
828
  (load_records; rebuild_doc) if @dirty_flag == true
828
- r = @doc.root.element("records/*[#{field}=\"#{value}\"]")
829
- r ? recordx_to_record(r) : nil
829
+
830
+ if value.is_a? String then
831
+
832
+ r = @doc.root.element("records/*[#{field}=\"#{value}\"]")
833
+ r ? recordx_to_record(r) : nil
834
+
835
+ elsif value.is_a? Regexp
836
+
837
+ found = all.select {|x| x.method(field).call =~ /#{value}/i}
838
+ found.first if found.any?
839
+
840
+ end
841
+
830
842
  end
831
843
 
832
844
  def findx_all_by(field, value)
833
- @doc.root.xpath("records/*[#{field}=\"#{value}\"]")\
845
+
846
+ if value.is_a? String then
847
+
848
+ @doc.root.xpath("records/*[#{field}=\"#{value}\"]")\
834
849
  .map {|x| recordx_to_record x}
850
+
851
+ elsif value.is_a? Regexp
852
+
853
+ all.select {|x| x.method(field).call =~ /#{value}/i}
854
+
855
+ end
835
856
  end
836
857
 
837
858
  def recordx_to_record(recordx)
838
-
859
+
839
860
  h = recordx.attributes
840
-
861
+
841
862
  records = recordx.xpath("*").map {|x| x.text ? x.text.unescape.to_s : '' }
842
863
  hash = @fields.zip(records).to_h
843
864
  RecordX.new(hash, self, h[:id], h[:created], h[:last_modified])
@@ -859,21 +880,21 @@ EOF
859
880
  fields.keys.each {|key| fields[key] = params[key.to_sym] if params.has_key? key.to_sym}
860
881
  fields
861
882
  end
862
-
883
+
863
884
  def display_xml(options={})
864
885
  #@logger.debug 'inside display_xml'
865
886
  opt = {unescape_html: false}.merge options
866
-
887
+
867
888
  state = :external
868
889
  #@logger.debug 'before diry'
869
890
  if @dirty_flag == true then
870
- load_records
891
+ load_records
871
892
  state = :internal
872
893
  end
873
894
  #@logger.debug 'before rebuilt'
874
895
  doc = rebuild_doc(state)
875
896
  #@logger.debug 'after rebuild_doc'
876
-
897
+
877
898
  if opt[:unescape_html] == true then
878
899
  doc.content(opt)
879
900
  else
@@ -887,15 +908,15 @@ EOF
887
908
  raw_params.merge!(uid: id) if @default_key.to_sym == :uid
888
909
  params = Hash[raw_params.keys.map(&:to_sym).zip(raw_params.values)]
889
910
 
890
- fields = capture_fields(params)
911
+ fields = capture_fields(params)
891
912
  record = Rexle::Element.new @record_name
892
913
 
893
914
  fields.each do |k,v|
894
- element = Rexle::Element.new(k.to_s)
915
+ element = Rexle::Element.new(k.to_s)
895
916
  element.root.text = v.to_s.gsub('<','&lt;').gsub('>','&gt;') if v
896
917
  record.add element if record
897
918
  end
898
-
919
+
899
920
  attributes = {id: id.to_s, created: Time.now.to_s, last_modified: nil}\
900
921
  .merge attr
901
922
  attributes.each {|k,v| record.add_attribute(k, v)}
@@ -912,7 +933,7 @@ EOF
912
933
  buffer = RXFHelper.read(line.chomp, auto: false).first
913
934
 
914
935
  doc = Rexle.new buffer
915
-
936
+
916
937
  if doc.root.name == 'kvx' then
917
938
 
918
939
  kvx = Kvx.new doc
@@ -924,17 +945,17 @@ EOF
924
945
  end
925
946
 
926
947
  end
927
-
948
+
928
949
  def rebuild_doc(state=:internal)
929
-
950
+
930
951
  puts 'inside rebuild_doc'.info if @debug
931
952
 
932
- reserved_keywords = (
953
+ reserved_keywords = (
933
954
  Object.public_methods | \
934
955
  Kernel.public_methods | \
935
956
  public_methods + [:method_missing]
936
957
  )
937
-
958
+
938
959
  xml = RexleBuilder.new
939
960
 
940
961
  a = xml.send @root_name do
@@ -960,30 +981,33 @@ EOF
960
981
  #jr160315records.reverse! if @order == 'descending' and state == :external
961
982
 
962
983
  xml.records do
963
-
984
+
964
985
  records.each do |k, item|
965
-
986
+
966
987
  attributes = {}
967
-
988
+
968
989
  item.keys.each do |key|
969
990
  attributes[key] = item[key] || '' unless key == :body
970
991
  end
971
-
992
+
972
993
  if @record_name.nil? then
973
994
  raise DynarexException, 'record_name can\'t be nil. Check the schema'
974
995
  end
975
-
996
+
997
+ puts 'attributes: ' + attributes.inspect if @debug
998
+ puts '@record_name: ' + @record_name.inspect
999
+
976
1000
  xml.send(@record_name, attributes) do
977
- item[:body].each do |name,value|
1001
+ item[:body].each do |name,value|
978
1002
 
979
1003
  if reserved_keywords.include? name then
980
- name = ('._' + name.to_s).to_sym
1004
+ name = ('._' + name.to_s).to_sym
981
1005
  end
982
-
1006
+
983
1007
  val = value.send(value.is_a?(String) ? :to_s : :to_yaml)
984
1008
  xml.send(name, val.gsub('>','&gt;')\
985
1009
  .gsub('<','&lt;')\
986
- .gsub(/(&\s|&[a-zA-Z\.]+;?)/) do |x|
1010
+ .gsub(/(&\s|&[a-zA-Z\.]+;?)/) do |x|
987
1011
  x[-1] == ';' ? x : x.sub('&','&amp;')
988
1012
  end
989
1013
  )
@@ -998,22 +1022,22 @@ EOF
998
1022
  end
999
1023
 
1000
1024
  doc = Rexle.new(a)
1001
-
1025
+
1002
1026
  puts ('@xslt: ' + @xslt.inspect).debug if @debug
1003
-
1027
+
1004
1028
  if @xslt then
1005
- doc.instructions = [['xml-stylesheet',
1029
+ doc.instructions = [['xml-stylesheet',
1006
1030
  "title='XSL_formatting' type='text/xsl' href='#{@xslt}'"]]
1007
1031
  end
1008
1032
 
1009
1033
  return doc if state != :internal
1010
1034
  @doc = doc
1011
- end
1012
-
1035
+ end
1036
+
1013
1037
  def string_parse(buffer)
1014
-
1038
+
1015
1039
  if @spaces_delimited then
1016
- buffer = buffer.lines.map{|x| x.gsub(/\s{2,}/,' # ')}.join
1040
+ buffer = buffer.lines.map{|x| x.gsub(/\s{2,}/,' # ')}.join
1017
1041
  end
1018
1042
 
1019
1043
  buffer.gsub!("\r",'')
@@ -1024,25 +1048,25 @@ EOF
1024
1048
  buffer.gsub!(/<./) {|x| x[1] != '?' ? x.sub(/</,'&lt;') : x }
1025
1049
 
1026
1050
  @raw_header = buffer[/<\?dynarex[^>]+>/]
1027
-
1051
+
1028
1052
  if buffer[/<\?/] then
1029
1053
 
1030
1054
  raw_stylesheet = buffer.slice!(/<\?xml-stylesheet[^>]+>/)
1031
1055
  @xslt = raw_stylesheet[/href=["']([^"']+)/,1] if raw_stylesheet
1032
1056
  @raw_header = buffer.slice!(/<\?dynarex[^>]+>/) + "\n"
1033
-
1057
+
1034
1058
  header = @raw_header[/<?dynarex (.*)?>/,1]
1035
1059
 
1036
1060
  r1 = /([\w\-]+\s*\=\s*'[^']*)'/
1037
1061
  r2 = /([\w\-]+\s*\=\s*"[^"]*)"/
1038
1062
 
1039
- r = header.scan(/#{r1}|#{r2}/).map(&:compact).flatten
1063
+ r = header.scan(/#{r1}|#{r2}/).map(&:compact).flatten
1040
1064
 
1041
1065
  r.each do |x|
1042
1066
 
1043
1067
  attr, val = x.split(/\s*=\s*["']/,2)
1044
1068
  name = (attr + '=').to_sym
1045
-
1069
+
1046
1070
  if self.public_methods.include? name then
1047
1071
  self.method(name).call(unescape val)
1048
1072
  else
@@ -1062,7 +1086,7 @@ EOF
1062
1086
  if raw_summary then
1063
1087
 
1064
1088
  a_summary = raw_summary.split(',').map(&:strip)
1065
-
1089
+
1066
1090
  @summary ||= {}
1067
1091
  raw_lines.shift while raw_lines.first.strip.empty?
1068
1092
 
@@ -1082,7 +1106,7 @@ EOF
1082
1106
  @summary[:schema] = @schema
1083
1107
  @summary[:format_mask] = @format_mask
1084
1108
  @summary[:unique] = @unique if @unique
1085
-
1109
+
1086
1110
  raw_lines.shift while raw_lines.first.strip.empty?
1087
1111
 
1088
1112
  lines = case raw_lines.first.rstrip
@@ -1092,10 +1116,10 @@ EOF
1092
1116
  yaml = YAML.load raw_lines.join("\n")
1093
1117
 
1094
1118
  yamlize = lambda {|x| (x.is_a? Array) ? x.to_yaml : x}
1095
-
1119
+
1096
1120
  yprocs = {
1097
1121
  Hash: lambda {|y|
1098
- y.map do |k,v|
1122
+ y.map do |k,v|
1099
1123
  procs = {Hash: proc {|x| x.values}, Array: proc {v}}
1100
1124
  values = procs[v.class.to_s.to_sym].call(v).map(&yamlize)
1101
1125
  [k, *values]
@@ -1104,23 +1128,23 @@ EOF
1104
1128
  Array: lambda {|y| y.map {|x2| x2.map(&yamlize)} }
1105
1129
  }
1106
1130
 
1107
- yprocs[yaml.class.to_s.to_sym].call yaml
1108
-
1131
+ yprocs[yaml.class.to_s.to_sym].call yaml
1132
+
1109
1133
  when '--+'
1110
1134
 
1111
1135
  rowx(raw_lines)
1112
-
1136
+
1113
1137
  when '--#'
1114
1138
 
1115
1139
  self.summary[:rawdoc_type] = 'sectionx'
1116
1140
  raw_lines.shift
1117
1141
 
1118
1142
  raw_lines.join.lstrip.split(/(?=^#[^#])/).map {|x| [x.rstrip]}
1119
-
1143
+
1120
1144
  else
1121
1145
 
1122
1146
  raw_lines = raw_lines.join("\n").gsub(/^(\s*#[^\n]+|\n)/,'').lines.to_a
1123
-
1147
+
1124
1148
  if @linked then
1125
1149
 
1126
1150
  parse_links(raw_lines)
@@ -1129,42 +1153,42 @@ EOF
1129
1153
  a2 = raw_lines.map.with_index do |x,i|
1130
1154
 
1131
1155
  next if x[/^\s+$|\n\s*#/]
1132
-
1156
+
1133
1157
  begin
1134
-
1158
+
1135
1159
  field_names, field_values = RXRawLineParser.new(@format_mask).parse(x)
1136
1160
  rescue
1137
1161
  raise "input file parser error at line " + (i + 1).to_s + ' --> ' + x
1138
1162
  end
1139
1163
  field_values
1140
1164
  end
1141
-
1165
+
1142
1166
  a2.compact!
1143
1167
  a3 = a2.compact.map(&:first)
1144
-
1168
+
1145
1169
  if a3 != a3.uniq then
1146
-
1170
+
1147
1171
  if @unique then
1148
1172
  raise DynarexException, "Duplicate id found"
1149
1173
  else
1150
- add_id(a2)
1174
+ add_id(a2)
1151
1175
  end
1152
-
1176
+
1153
1177
  end
1154
-
1178
+
1155
1179
  a2
1156
- end
1180
+ end
1157
1181
 
1158
1182
  end
1159
1183
 
1160
- a = lines.map.with_index do |x,i|
1161
-
1184
+ a = lines.map.with_index do |x,i|
1185
+
1162
1186
  created = Time.now.to_s
1163
1187
 
1164
1188
  h = Hash[
1165
1189
  @fields.zip(
1166
1190
  x.map do |t|
1167
-
1191
+
1168
1192
  t.to_s[/^---(?:\s|\n)/] ? YAML.load(t[/^---(?:\s|\n)(.*)/,1]) : unescape(t.to_s)
1169
1193
  end
1170
1194
  )
@@ -1186,12 +1210,12 @@ EOF
1186
1210
  item[:body].each do |k,v|
1187
1211
  h[key][:body][k.to_sym] = v
1188
1212
  end
1189
- else
1213
+ else
1190
1214
  item[:id] = (@order == 'descending' ? (h2.count) - i : i+ 1).to_s
1191
1215
  i += 1
1192
1216
  h[key] = item.clone
1193
- end
1194
- end
1217
+ end
1218
+ end
1195
1219
 
1196
1220
  h.each {|key, item| h.delete(key) if not h2.has_key? key}
1197
1221
 
@@ -1200,9 +1224,9 @@ EOF
1200
1224
  rebuild_doc
1201
1225
  self
1202
1226
  end
1203
-
1227
+
1204
1228
  def sort_records_by!(&element_blk)
1205
-
1229
+
1206
1230
  refresh_doc
1207
1231
  a = @doc.root.xpath('records/*').sort_by &element_blk
1208
1232
  @doc.root.delete('records')
@@ -1215,33 +1239,36 @@ EOF
1215
1239
 
1216
1240
  load_records if @dirty_flag
1217
1241
  self
1218
- end
1242
+ end
1219
1243
 
1220
1244
  def unescape(s)
1221
1245
  s.gsub('&lt;', '<').gsub('&gt;','>')
1222
1246
  end
1223
1247
 
1224
1248
  def dynarex_new(s, default_key: nil)
1225
-
1249
+
1226
1250
  @schema = schema = s
1227
1251
  @default_key = default_key if default_key
1228
-
1252
+
1229
1253
  ptrn = %r((\w+)\[?([^\]]+)?\]?\/(\w+)\(([^\)]+)\))
1230
1254
 
1231
1255
  if s.match(ptrn) then
1232
-
1233
- @root_name, raw_summary, record_name, raw_fields = s.match(ptrn).captures
1256
+
1257
+ @root_name, raw_summary, record_name, raw_fields = s.match(ptrn).captures
1258
+ reserved = %w(require parent gem)
1259
+
1260
+ raise 'reserved keyword: ' + record_name if reserved.include? record_name
1234
1261
  summary, fields = [raw_summary || '',raw_fields].map {|x| x.split(/,/).map &:strip}
1235
-
1262
+
1236
1263
  if fields.include? 'id' then
1237
- raise 'Dynarex#dynarex_new: schema field id is a reserved keyword'
1264
+ raise 'Dynarex#dynarex_new: schema field id is a reserved keyword'
1238
1265
  end
1239
-
1266
+
1240
1267
  create_find fields
1241
-
1242
- reserved = %w(require parent)
1268
+
1269
+
1243
1270
  raise 'reserved keyword' if (fields & reserved).any?
1244
-
1271
+
1245
1272
  else
1246
1273
  ptrn = %r((\w+)\[?([^\]]+)?\]?)
1247
1274
  @root_name, raw_summary = s.match(ptrn).captures
@@ -1264,36 +1291,36 @@ EOF
1264
1291
  def attach_record_methods()
1265
1292
  create_find @fields
1266
1293
  end
1267
-
1294
+
1268
1295
  def openx(s)
1269
1296
  #@logger.debug 'inside openx'
1270
1297
  if s[/</] then # xml
1271
1298
  #@logger.debug 'regular string'
1272
1299
  #@logger.debug 's: ' + s.inspect
1273
1300
  buffer = s
1274
-
1301
+
1275
1302
  elsif s[/[\[\(]/] # schema
1276
1303
 
1277
1304
  dynarex_new(s)
1278
-
1305
+
1279
1306
  elsif s[/^https?:\/\//] then # url
1280
- buffer, type = RXFHelper.read s, {username: @username,
1281
- password: @password, auto: false}
1282
- elsif s[/^dfs?:\/\//] then
1283
-
1284
- @local_filepath = s
1307
+ buffer, type = RXFHelper.read s, {username: @username,
1308
+ password: @password, auto: false}
1309
+ elsif s[/^dfs?:\/\//] then
1310
+
1311
+ @local_filepath = s
1285
1312
 
1286
1313
  if FileX.exists? s then
1287
- buffer = FileX.read s
1314
+ buffer = FileX.read(s).force_encoding("UTF-8")
1288
1315
  elsif @schema
1289
- dynarex_new @schema, default_key: @default_key
1290
- end
1291
-
1316
+ dynarex_new @schema, default_key: @default_key
1317
+ end
1318
+
1292
1319
  else # local file
1293
-
1320
+
1294
1321
  @local_filepath = s
1295
-
1296
- if File.exists? s then
1322
+
1323
+ if File.exists? s then
1297
1324
  buffer = File.read s
1298
1325
  elsif @schema
1299
1326
  dynarex_new @schema, default_key: @default_key
@@ -1302,18 +1329,18 @@ EOF
1302
1329
  end
1303
1330
  end
1304
1331
  #@logger.debug 'buffer: ' + buffer[0..120]
1305
-
1332
+
1306
1333
  return import(buffer) if buffer =~ /^<\?dynarex\b/
1307
1334
 
1308
1335
  if buffer then
1309
1336
 
1310
1337
  raw_stylesheet = buffer.slice!(/<\?xml-stylesheet[^>]+>/)
1311
1338
  @xslt = raw_stylesheet[/href=["']([^"']+)/,1] if raw_stylesheet
1312
-
1313
- @doc = Rexle.new(buffer) unless @doc
1339
+
1340
+ @doc = Rexle.new(buffer) unless @doc
1314
1341
  #@logger.debug 'openx/@doc : ' + @doc.xml.inspect
1315
1342
  end
1316
-
1343
+
1317
1344
  return if @doc.root.nil?
1318
1345
  e = @doc.root.element('summary')
1319
1346
 
@@ -1322,20 +1349,20 @@ EOF
1322
1349
  @summary = summary_to_h
1323
1350
 
1324
1351
  summary_methods = (@summary.keys - self.public_methods)
1325
-
1352
+
1326
1353
  summary_methods.each do |x|
1327
-
1354
+
1328
1355
  instance_eval "
1329
-
1356
+
1330
1357
  def #{x.to_sym}()
1331
1358
  @summary[:#{x}]
1332
1359
  end
1333
-
1360
+
1334
1361
  def #{x.to_s}=(v)
1335
1362
  @summary[:#{x}] = v
1336
1363
  @doc.root.element('summary/#{x.to_s}').text = v
1337
1364
  end
1338
- "
1365
+ "
1339
1366
  end
1340
1367
 
1341
1368
  @order = @summary[:order] if @summary.has_key? :order
@@ -1357,7 +1384,7 @@ EOF
1357
1384
 
1358
1385
  if @fields then
1359
1386
 
1360
- @default_key = @fields[0] unless @default_key
1387
+ @default_key = @fields[0] unless @default_key
1361
1388
  # load the record query handler methods
1362
1389
  attach_record_methods
1363
1390
  else
@@ -1365,46 +1392,46 @@ EOF
1365
1392
  #jr080912 @default_key = @doc.root.xpath('records/*/*').first.name
1366
1393
  @default_key = @doc.root.element('records/./.[1]').name
1367
1394
  end
1368
-
1395
+
1369
1396
  @summary[:default_key] = @default_key.to_s
1370
-
1397
+
1371
1398
  if @doc.root.xpath('records/*').length > 0 then
1372
- @record_name = @doc.root.element('records/*[1]').name
1399
+ @record_name = @doc.root.element('records/*[1]').name
1373
1400
  #jr240913 load_records
1374
1401
  @dirty_flag = true
1375
1402
  end
1376
1403
 
1377
- end
1404
+ end
1378
1405
 
1379
1406
  def load_records
1380
-
1407
+
1381
1408
  puts 'inside load_records'.info if @debug
1382
-
1409
+
1383
1410
  @dirty_flag = false
1384
-
1411
+
1385
1412
  if @summary[:order] then
1386
- orderfield = @summary[:order][/(\w+)\s+(?:ascending|descending)/,1]
1413
+ orderfield = @summary[:order][/(\w+)\s+(?:ascending|descending)/,1]
1387
1414
  sort_records_by! {|x| x.element(orderfield).text } if orderfield
1388
1415
  end
1389
-
1416
+
1390
1417
  @records = records_to_h
1391
-
1418
+
1392
1419
  @records.instance_eval do
1393
1420
  def delete_item(i)
1394
1421
  self.delete self.keys[i]
1395
1422
  end
1396
1423
  end
1397
-
1424
+
1398
1425
  #Returns a ready-only snapshot of records as a simple Hash.
1399
1426
  @flat_records = @records.values.map{|x| x[:body]}
1400
1427
 
1401
1428
  end
1402
-
1429
+
1403
1430
 
1404
1431
  def display()
1405
1432
  puts @doc.to_s
1406
1433
  end
1407
-
1434
+
1408
1435
  def records_to_h(order=:ascending)
1409
1436
 
1410
1437
  i = @doc.root.xpath('max(records/*/attribute::id)') || 0
@@ -1425,25 +1452,25 @@ EOF
1425
1452
  end
1426
1453
 
1427
1454
  body = (@fields - ['uid']).inject({}) do |r,field|
1428
-
1455
+
1429
1456
  node = row.element field.to_s
1430
1457
 
1431
1458
  if node then
1432
1459
  text = node.text ? node.text.unescape : ''
1433
1460
 
1434
- r.merge node.name.to_sym => (text[/^---(?:\s|\n)/] ?
1461
+ r.merge node.name.to_sym => (text[/^---(?:\s|\n)/] ?
1435
1462
  YAML.load(text[/^---(?:\s|\n)(.*)/,1]) : text)
1436
1463
  else
1437
1464
  r
1438
1465
  end
1439
1466
  end
1440
-
1467
+
1441
1468
  body[:uid] = id if @default_key == 'uid'
1442
1469
 
1443
1470
  attributes = row.attributes
1444
1471
  result.merge body[@default_key.to_sym] => attributes.merge({id: id, body: body})
1445
1472
  end
1446
-
1473
+
1447
1474
  puts 'records_to_h a: ' + a.inspect if @debug
1448
1475
  #@logger.debug 'a: ' + a.inspect
1449
1476
  a
@@ -1459,56 +1486,56 @@ EOF
1459
1486
 
1460
1487
  # get the fields
1461
1488
  a4 = a3.map{|x| x.scan(/^\w+(?=:)/)}.flatten(1).uniq
1462
-
1489
+
1463
1490
  abbrv_fields = a4.all? {|x| x.length == 1}
1464
-
1491
+
1465
1492
  a5 = a3.map do |xlines|
1466
-
1493
+
1467
1494
  puts 'xlines: ' + xlines.inspect if @debug
1468
-
1495
+
1469
1496
  missing_fields = a4 - xlines.scan(/^\w+(?=:)/)
1470
1497
 
1471
1498
  r = xlines.split(/\n(\w+:.*)/m)
1472
1499
  puts 'r: ' + r.inspect if @debug
1473
-
1500
+
1474
1501
  missing_fields.map!{|x| x + ":"}
1475
1502
  key = (abbrv_fields ? @fields[0].to_s[0] : @fields.first.to_s) + ':'
1476
-
1503
+
1477
1504
  if missing_fields.include? key
1478
1505
  r.unshift key
1479
1506
  missing_fields.delete key
1480
1507
  end
1481
-
1508
+
1482
1509
  r += missing_fields
1483
1510
  r.join("\n")
1484
-
1511
+
1485
1512
  end
1486
1513
  puts 'a5: ' + a5.inspect if @debug
1487
-
1514
+
1488
1515
  xml = RowX.new(a5.join("\n").strip, level: 0).to_xml
1489
1516
  puts 'xml: ' + xml.inspect if @debug
1490
-
1491
- a2 = Rexle.new(xml).root.xpath('item').inject([]) do |r,x|
1517
+
1518
+ a2 = Rexle.new(xml).root.xpath('item').inject([]) do |r,x|
1492
1519
 
1493
1520
  r << @fields.map do |field|
1494
1521
  x.text(abbrv_fields ? field.to_s.chr : field.to_s )
1495
1522
  end
1496
-
1523
+
1497
1524
  end
1498
1525
 
1499
- a2.compact!
1500
-
1501
- # if there is no field value for the first field then
1526
+ a2.compact!
1527
+
1528
+ # if there is no field value for the first field then
1502
1529
  # the default_key is invalid. The default_key is changed to an ID.
1503
1530
  if a2.detect {|x| x.first == ''} then
1504
1531
  add_id(a2)
1505
1532
  else
1506
1533
 
1507
1534
  a3 = a2.map(&:first)
1508
- add_id(a2) if a3 != a3.uniq
1509
-
1535
+ add_id(a2) if a3 != a3.uniq
1536
+
1510
1537
  end
1511
-
1538
+
1512
1539
  a2
1513
1540
 
1514
1541
  end
@@ -1544,13 +1571,13 @@ XSL
1544
1571
  @doc = Rexle.new(Rexslt.new(xsl, self.to_xml).to_s)
1545
1572
  @dirty_flag = true
1546
1573
  end
1547
-
1574
+
1548
1575
  def summary_to_h
1549
1576
 
1550
1577
  h = {recordx_type: 'dynarex'}
1551
-
1578
+
1552
1579
  @doc.root.xpath('summary/*').inject(h) do |r,node|
1553
- r.merge node.name.to_s.to_sym =>
1580
+ r.merge node.name.to_s.to_sym =>
1554
1581
  node.text ? node.text.unescape : node.text.to_s
1555
1582
  end
1556
1583
  end