cbeta 3.8.0 → 4.0.0

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.
@@ -1,813 +0,0 @@
1
- require 'cgi'
2
- require 'date'
3
- require 'fileutils'
4
- require 'json'
5
- require 'nokogiri'
6
- require 'set'
7
- require_relative 'cbeta_share'
8
-
9
- # Convert CBETA XML P5a to HTML
10
- #
11
- # CBETA XML P5a 可由此取得: https://github.com/cbeta-git/xml-p5a
12
- #
13
- # 轉檔規則請參考: http://wiki.ddbc.edu.tw/pages/CBETA_XML_P5a_轉_HTML
14
- class CBETA::P5aToHTML
15
- # 內容不輸出的元素
16
- PASS=['back', 'teiHeader']
17
-
18
- # 某版用字缺的符號
19
- MISSING = '-'
20
-
21
- private_constant :PASS, :MISSING
22
-
23
- # @param xml_root [String] 來源 CBETA XML P5a 路徑
24
- # @param out_root [String] 輸出 HTML 路徑
25
- def initialize(xml_root, out_root)
26
- @xml_root = xml_root
27
- @out_root = out_root
28
- @cbeta = CBETA.new
29
- @gaijis = CBETA::Gaiji.new
30
- end
31
-
32
- # 將 CBETA XML P5a 轉為 HTML
33
- #
34
- # @example for convert 大正藏第一冊:
35
- #
36
- # x2h = CBETA::P5aToHTML.new('/PATH/TO/CBETA/XML/P5a', '/OUTPUT/FOLDER')
37
- # x2h.convert('T01')
38
- #
39
- # @example for convert 大正藏全部:
40
- #
41
- # x2h = CBETA::P5aToHTML.new('/PATH/TO/CBETA/XML/P5a', '/OUTPUT/FOLDER')
42
- # x2h.convert('T')
43
- #
44
- # @example for convert 大正藏第五冊至第七冊:
45
- #
46
- # x2h = CBETA::P5aToHTML.new('/PATH/TO/CBETA/XML/P5a', '/OUTPUT/FOLDER')
47
- # x2h.convert('T05..T07')
48
- #
49
- # T 是大正藏的 ID, CBETA 的藏經 ID 系統請參考: http://www.cbeta.org/format/id.php
50
- def convert(target=nil)
51
- return convert_all if target.nil?
52
-
53
- arg = target.upcase
54
- if arg.size == 1
55
- handle_collection(arg)
56
- else
57
- if arg.include? '..'
58
- arg.match(/^([^\.]+?)\.\.([^\.]+)$/) {
59
- handle_vols($1, $2)
60
- }
61
- else
62
- handle_vol(arg)
63
- end
64
- end
65
- end
66
-
67
- private
68
-
69
- include CbetaShare
70
-
71
- def convert_all
72
- Dir.foreach(@xml_root) { |c|
73
- next unless c.match(/^[A-Z]$/)
74
- handle_collection(c)
75
- }
76
- end
77
-
78
- def e_anchor(e)
79
- id = e['id']
80
- if e.has_attribute?('id')
81
- if id.start_with?('nkr_note_orig')
82
- note = @notes[id]
83
- note_text = traverse(note)
84
- n = id[/^nkr_note_orig_(.*)$/, 1]
85
- @back[@juan] += "<span class='footnote' id='n#{n}'>#{note_text}</span>\n"
86
- return "<a class='noteAnchor' href='#n#{n}'></a>"
87
- elsif id.start_with? 'fx'
88
- return "<span class='star'>[*]</span>"
89
- end
90
- end
91
-
92
- if e.has_attribute?('type')
93
- if e['type'] == 'circle'
94
- return '◎'
95
- end
96
- end
97
-
98
- ''
99
- end
100
-
101
- def e_app(e)
102
- r = ''
103
- if e['type'] == 'star'
104
- c = e['corresp'][1..-1]
105
- r = "<a class='noteAnchor star' href='#n#{c}'></a>"
106
- end
107
- r + traverse(e)
108
- end
109
-
110
- def e_byline(e)
111
- r = '<p class="byline">'
112
- r += "<span class='lineInfo' line='#{@lb}'></span>"
113
- r += traverse(e)
114
- r + '</p>'
115
- end
116
-
117
- def e_cell(e)
118
- doc = Nokogiri::XML::Document.new
119
- cell = doc.create_element('div')
120
- cell['class'] = 'bip-table-cell'
121
- cell['rowspan'] = e['rows'] if e.key? 'rows'
122
- cell['colspan'] = e['cols'] if e.key? 'cols'
123
- cell.inner_html = traverse(e)
124
- to_html(cell)
125
- end
126
-
127
- def e_corr(e)
128
- r = ''
129
- if e.parent.name == 'choice'
130
- sic = e.parent.at_xpath('sic')
131
- unless sic.nil?
132
- @dila_note += 1
133
- r = "<a class='noteAnchor dila' href='#dila_note#{@dila_note}'></a>"
134
-
135
- note = @orig
136
- sic_text = traverse(sic, 'back')
137
- if sic_text.empty?
138
- note += MISSING
139
- else
140
- note += sic_text
141
- end
142
- @back[@juan] += "<span class='footnote_dila' id='dila_note#{@dila_note}'>#{note}</span>\n"
143
- end
144
- end
145
- r + "<span class='cbeta'>%s</span>" % traverse(e)
146
- end
147
-
148
- def e_div(e)
149
- @div_count += 1
150
- n = @div_count
151
- if e.has_attribute? 'type'
152
- @open_divs << e
153
- r = traverse(e)
154
- @open_divs.pop
155
- return "<!-- begin div#{n}--><div class='div-#{e['type']}'>#{r}</div><!-- end of div#{n} -->"
156
- else
157
- return traverse(e)
158
- end
159
- end
160
-
161
- def e_figure(e)
162
- "<p class='figure'>%s</p>" % traverse(e)
163
- end
164
-
165
- def e_foreign(e)
166
- return '' if e.key?('place') and e['place'].include?('foot')
167
- traverse(e)
168
- end
169
-
170
- def e_g(e, mode)
171
- # if 有 <mapping type="unicode">
172
- # if 不在 Unicode Extension C, D, E 範圍裡
173
- # 直接採用
174
- # else
175
- # 預設呈現 unicode, 但仍包缺字資訊,供點選開 popup
176
- # else if 有 <mapping type="normal_unicode">
177
- # 預設呈現 normal_unicode, 但仍包缺字資訊,供點選開 popup
178
- # else if 有 normalized form
179
- # 預設呈現 normalized form, 但仍包缺字資訊,供點選開 popup
180
- # else
181
- # 預設呈現組字式, 但仍包缺字資訊,供點選開 popup
182
- gid = e['ref'][1..-1]
183
- g = @gaijis[gid]
184
- abort "Line:#{__LINE__} 無缺字資料:#{gid}" if g.nil?
185
- zzs = g['zzs']
186
-
187
- if mode == 'txt'
188
- return g['roman'] if gid.start_with?('SD')
189
- if zzs.nil?
190
- abort "缺組字式:#{g}"
191
- else
192
- return zzs
193
- end
194
- end
195
-
196
- @char_count += 1
197
-
198
- if gid.start_with?('SD')
199
- case gid
200
- when 'SD-E35A'
201
- return '('
202
- when 'SD-E35B'
203
- return ')'
204
- else
205
- return "<span class='siddam' roman='#{g['roman']}' code='#{gid}' char='#{g['sd-char']}'/>"
206
- end
207
- end
208
-
209
- if gid.start_with?('RJ')
210
- return "<span class='ranja' roman='#{g['roman']}' code='#{gid}' char='#{g['rj-char']}'/>"
211
- end
212
-
213
- default = ''
214
- if g.has_key?('unicode')
215
- #if @unicode1.include?(g['unicode'])
216
- # 如果在 unicode ext-C, ext-D, ext-E 範圍內
217
- if (0x2A700..0x2CEAF).include? g['unicode'].hex
218
- default = g['unicode-char']
219
- else
220
- return g['unicode-char'] # 直接採用 unicode
221
- end
222
- end
223
-
224
- nor = ''
225
- if g.has_key?('normal_unicode')
226
- nor = g['normal_unicode']
227
- default = nor if default.empty?
228
- end
229
-
230
- if g.has_key?('normal')
231
- nor += ', ' unless nor==''
232
- nor += g['normal']
233
- default = g['normal'] if default.empty?
234
- end
235
-
236
- default = zzs if default.empty?
237
-
238
- href = 'http://dict.cbeta.org/dict_word/gaiji-cb/%s/%s.gif' % [gid[2, 2], gid]
239
- unless @back[@juan].include?(href)
240
- @back[@juan] += "<span id='#{gid}' class='gaijiInfo' figure_url='#{href}' zzs='#{zzs}' nor='#{nor}'>#{default}</span>\n"
241
- end
242
- "<a class='gaijiAnchor' href='##{gid}'>#{default}</a>"
243
- end
244
-
245
- def e_graphic(e)
246
- url = File.basename(e['url'])
247
- "<span imgsrc='#{url}' class='graphic'></span>"
248
- end
249
-
250
- def e_head(e)
251
- r = ''
252
- unless e['type'] == 'added'
253
- i = @open_divs.size
254
- r = "<p class='head' data-head-level='#{i}'>%s</p>" % traverse(e)
255
- end
256
- r
257
- end
258
-
259
- def e_item(e)
260
- "<li>%s</li>\n" % traverse(e)
261
- end
262
-
263
- def e_juan(e)
264
- "<p class='juan'>%s</p>" % traverse(e)
265
- end
266
-
267
- def e_l(e)
268
- if @lg_type == 'abnormal'
269
- return traverse(e)
270
- end
271
-
272
- @in_l = true
273
-
274
- doc = Nokogiri::XML::Document.new
275
- cell = doc.create_element('div')
276
- cell['class'] = 'lg-cell'
277
- cell.inner_html = traverse(e)
278
-
279
- if e.key? 'rend'
280
- cell['style'] = e['rend']
281
- elsif @first_l
282
- parent = e.parent()
283
- if parent.has_attribute?('rend')
284
- indent = parent['rend'].scan(/text-indent:[^:]*/)
285
- unless indent.empty?
286
- cell['style'] = indent[0]
287
- end
288
- end
289
- end
290
- @first_l = false
291
-
292
- r = to_html(cell)
293
-
294
- unless @lg_row_open
295
- r = "\n<div class='lg-row'>" + r
296
- @lg_row_open = true
297
- end
298
- @in_l = false
299
- r
300
- end
301
-
302
- def e_lb(e)
303
- return '' if e['type']=='old'
304
-
305
- # 卍續藏有 X 跟 R 兩種 lb, 只處理 X
306
- return '' if e['ed'] != @series
307
-
308
- @char_count = 1
309
- @lb = e['n']
310
- line_head = CBETA.get_linehead(@sutra_no, @lb)
311
-
312
- r = ''
313
- #if e.parent.name == 'lg' and $lg_row_open
314
- if @lg_row_open && !@in_l
315
- # 每行偈頌放在一個 lg-row 裡面
316
- # T46n1937, p. 914a01, l 包雙行夾註跨行
317
- # T20n1092, 337c16, lb 在 l 中間,不結束 lg-row
318
- r += "</div><!-- end of lg-row -->"
319
- @lg_row_open = false
320
- end
321
- r += "<span class='lb' \nid='#{line_head}'>#{line_head}</span>"
322
- unless @next_line_buf.empty?
323
- r += @next_line_buf
324
- @next_line_buf = ''
325
- end
326
- r
327
- end
328
-
329
- def e_lem(e)
330
- r = ''
331
- w = e['wit']
332
- if w.include? 'CBETA' and not w.include? @orig
333
- @dila_note += 1
334
- r = "<a class='noteAnchor dila' href='#dila_note#{@dila_note}'></a>"
335
- r += "<span class='cbeta'>%s</span>" % traverse(e)
336
-
337
- note = lem_note_cf(e)
338
- note += lem_note_rdg(e)
339
- @back[@juan] += "<span class='footnote_dila' id='dila_note#{@dila_note}'>#{note}</span>\n"
340
- else
341
- r = traverse(e)
342
- end
343
- r
344
- end
345
-
346
- def e_lg(e)
347
- r = ''
348
- @lg_type = e['type']
349
- if @lg_type == 'abnormal'
350
- r = "<p class='lg-abnormal'>" + traverse(e) + "</p>"
351
- else
352
- @first_l = true
353
- doc = Nokogiri::XML::Document.new
354
- node = doc.create_element('div')
355
- node['class'] = 'lg'
356
- if e.has_attribute?('rend')
357
- rend = e['rend'].gsub(/text-indent:[^:]*/, '')
358
- node['style'] = rend
359
- end
360
- @lg_row_open = false
361
- node.inner_html = traverse(e)
362
- if @lg_row_open
363
- node.inner_html += '</div><!-- end of lg -->'
364
- @lg_row_open = false
365
- end
366
- r = "\n" + to_html(node)
367
- end
368
- r
369
- end
370
-
371
- def e_list(e)
372
- "<ul>%s</ul>" % traverse(e)
373
- end
374
-
375
- def e_milestone(e)
376
- r = ''
377
- if e['unit'] == 'juan'
378
-
379
- r += "</div>" * @open_divs.size # 如果有 div 跨卷,要先結束, ex: T55n2154, p. 680a29, 跨 19, 20 兩卷
380
- @juan = e['n'].to_i
381
- @back[@juan] = @back[0]
382
- r += "<juan #{@juan}>"
383
- @open_divs.each { |d|
384
- r += "<div class='div-#{d['type']}'>"
385
- }
386
- end
387
- r
388
- end
389
-
390
- def e_mulu(e)
391
- r = ''
392
- if e['type'] == '品'
393
- @pass << false
394
- r = "<mulu class='pin' s='%s'/>" % traverse(e, 'txt')
395
- @pass.pop
396
- end
397
- r
398
- end
399
-
400
- def e_note(e)
401
- n = e['n']
402
- if e.has_attribute?('type')
403
- t = e['type']
404
- case t
405
- when 'equivalent'
406
- return ''
407
- when 'orig'
408
- return handle_note_orig(e)
409
- when 'orig_biao'
410
- return handle_note_orig(e, 'biao')
411
- when 'orig_ke'
412
- return handle_note_orig(e, 'ke')
413
- when 'mod'
414
- @pass << false
415
- s = traverse(e)
416
- @pass.pop
417
- @back[@juan] += "<span class='footnote cb' id='n#{n}'>#{s}</span>\n"
418
- return "<a class='noteAnchor cb' href='#n#{n}'></a>"
419
- when 'rest'
420
- return ''
421
- else
422
- return '' if t.start_with?('cf')
423
- end
424
- end
425
-
426
- if e.has_attribute?('resp')
427
- return '' if e['resp'].start_with? 'CBETA'
428
- end
429
-
430
- r = traverse(e)
431
- if e.has_attribute?('place')
432
- if e['place']=='inline'
433
- r = "<span class='doube-line-note'>#{r}</span>"
434
- elsif e['place']=='interlinear'
435
- r = "<span class='interlinear-note'>#{r}</span>"
436
- end
437
- end
438
- r
439
- end
440
-
441
- def e_p(e)
442
- if e.key? 'type'
443
- r = "<p class='%s'>" % e['type']
444
- else
445
- r = '<p>'
446
- end
447
- r += "<span class='lineInfo' line='#{@lb}'></span>"
448
- r += traverse(e)
449
- r + '</p>'
450
- end
451
-
452
- def e_row(e)
453
- "<div class='bip-table-row'>" + traverse(e) + "</div>"
454
- end
455
-
456
- def e_sg(e)
457
- '(' + traverse(e) + ')'
458
- end
459
-
460
- def e_t(e)
461
- if e.has_attribute? 'place'
462
- return '' if e['place'].include? 'foot'
463
- end
464
- r = traverse(e)
465
-
466
- # <tt type="app"> 不是 悉漢雙行對照
467
- return r if @tt_type == 'app'
468
-
469
- # 處理雙行對照
470
- i = e.xpath('../t').index(e)
471
- case i
472
- when 0
473
- return r + ' '
474
- when 1
475
- @next_line_buf += r + ' '
476
- return ''
477
- else
478
- return r
479
- end
480
- end
481
-
482
- def e_tt(e)
483
- @tt_type = e['type']
484
- traverse(e)
485
- end
486
-
487
- def e_table(e)
488
- "<div class='bip-table'>" + traverse(e) + "</div>"
489
- end
490
-
491
- def e_unclear(e)
492
- '▆'
493
- end
494
-
495
- def handle_collection(c)
496
- @series = c
497
- puts 'handle_collection ' + c
498
- folder = File.join(@xml_root, @series)
499
- Dir.entries(folder).sort.each { |vol|
500
- next if ['.', '..', '.DS_Store'].include? vol
501
- handle_vol(vol)
502
- }
503
- end
504
-
505
- def handle_node(e, mode)
506
- return '' if e.comment?
507
- return handle_text(e, mode) if e.text?
508
- return '' if PASS.include?(e.name)
509
- r = case e.name
510
- when 'anchor' then e_anchor(e)
511
- when 'app' then e_app(e)
512
- when 'byline' then e_byline(e)
513
- when 'cell' then e_cell(e)
514
- when 'corr' then e_corr(e)
515
- when 'div' then e_div(e)
516
- when 'figure' then e_figure(e)
517
- when 'foreign' then e_foreign(e)
518
- when 'g' then e_g(e, mode)
519
- when 'graphic' then e_graphic(e)
520
- when 'head' then e_head(e)
521
- when 'item' then e_item(e)
522
- when 'juan' then e_juan(e)
523
- when 'l' then e_l(e)
524
- when 'lb' then e_lb(e)
525
- when 'lem' then e_lem(e)
526
- when 'lg' then e_lg(e)
527
- when 'list' then e_list(e)
528
- when 'mulu' then e_mulu(e)
529
- when 'note' then e_note(e)
530
- when 'milestone' then e_milestone(e)
531
- when 'p' then e_p(e)
532
- when 'rdg' then ''
533
- when 'reg' then ''
534
- when 'row' then e_row(e)
535
- when 'sic' then ''
536
- when 'sg' then e_sg(e)
537
- when 't' then e_t(e)
538
- when 'tt' then e_tt(e)
539
- when 'table' then e_table(e)
540
- when 'unclear' then e_unclear(e)
541
- else traverse(e)
542
- end
543
- r
544
- end
545
-
546
- def handle_note_orig(e, anchor_type=nil)
547
- n = e['n']
548
- @pass << false
549
- s = traverse(e)
550
- @pass.pop
551
-
552
- c = @series
553
-
554
- # 如果 CBETA 沒有修訂,就跟底本的註一樣
555
- c += " cb" unless @mod_notes.include? n
556
-
557
- @back[@juan] += "<span class='footnote #{c}' id='n#{n}'>#{s}</span>\n"
558
-
559
- label = case anchor_type
560
- when 'biao' then " data-label='標#{n[-2..-1]}'"
561
- when 'ke' then " data-label='科#{n[-2..-1]}'"
562
- else ''
563
- end
564
-
565
- return "<a class='noteAnchor #{c}' href='#n#{n}'#{label}></a>"
566
- end
567
-
568
- def handle_sutra(xml_fn)
569
- puts "convert sutra #{xml_fn}"
570
- @back = { 0 => '' }
571
- @char_count = 1
572
- @dila_note = 0
573
- @div_count = 0
574
- @in_l = false
575
- @juan = 0
576
- @lg_row_open = false
577
- @mod_notes = Set.new
578
- @next_line_buf = ''
579
- @open_divs = []
580
- @sutra_no = File.basename(xml_fn, ".xml")
581
-
582
- if @sutra_no.match(/^(T05|T06|T07)n0220/)
583
- @sutra_no = "#{$1}n0220"
584
- end
585
-
586
- text = parse_xml(xml_fn)
587
-
588
- # 註標移到 lg-cell 裡面,不然以 table 呈現 lg 會有問題
589
- text.gsub!(/(<a class='noteAnchor'[^>]*><\/a>)(<div class="lg-cell"[^>]*>)/, '\2\1')
590
-
591
- juans = text.split(/(<juan \d+>)/)
592
- juan_no = nil
593
- buf = ''
594
- # 一卷一檔
595
- juans.each { |j|
596
- if j =~ /<juan (\d+)>$/
597
- juan_no = $1.to_i
598
- elsif juan_no.nil?
599
- buf = j
600
- else
601
- write_juan(juan_no, buf+j)
602
- end
603
- }
604
- end
605
-
606
- def handle_text(e, mode)
607
- s = e.content().chomp
608
- return '' if s.empty?
609
- return '' if e.parent.name == 'app'
610
-
611
- # cbeta xml 文字之間會有多餘的換行
612
- r = s.gsub(/[\n\r]/, '')
613
-
614
- # 把 & 轉為 &amp;
615
- r = CGI.escapeHTML(r)
616
-
617
- # 正文區的文字外面要包 span
618
- if @pass.last and mode=='html'
619
- r = "<span class='t' l='#{@lb}' w='#{@char_count}'>#{r}</span>"
620
- @char_count += r.size
621
- end
622
- r
623
- end
624
-
625
- def handle_vol(vol)
626
- puts "convert volumn: #{vol}"
627
-
628
- @orig = @cbeta.get_canon_abbr(vol[0])
629
- abort "未處理底本" if @orig.nil?
630
-
631
- @vol = vol
632
- @series = CBETA.get_canon_from_vol(vol)
633
- @out_folder = File.join(@out_root, @series, vol)
634
- FileUtils.remove_dir(@out_folder, true)
635
- FileUtils::mkdir_p @out_folder
636
-
637
- source = File.join(@xml_root, @series, vol)
638
- Dir[source+"/*"].each { |f|
639
- handle_sutra(f)
640
- }
641
- end
642
-
643
- def handle_vols(v1, v2)
644
- puts "convert volumns: #{v1}..#{v2}"
645
- @series = CBETA.get_canon_from_vol(v1)
646
- folder = File.join(@xml_root, @series)
647
- Dir.foreach(folder) { |vol|
648
- next if vol < v1
649
- next if vol > v2
650
- handle_vol(vol)
651
- }
652
- end
653
-
654
- def lem_note_cf(e)
655
- # ex: T32n1670A.xml, p. 703a16
656
- # <note type="cf1">K30n1002_p0257a01-a23</note>
657
- refs = []
658
- e.xpath('./note').each { |n|
659
- if n.key?('type') and n['type'].start_with? 'cf'
660
- s = n.content
661
- if linehead_exist_in_cbeta(s)
662
- s = "<span class='note_cf'>#{s}</span>"
663
- end
664
- refs << s
665
- end
666
- }
667
- if refs.empty?
668
- ''
669
- else
670
- '修訂依據:' + refs.join(';') + '。'
671
- end
672
- end
673
-
674
- def lem_note_rdg(lem)
675
- r = ''
676
- app = lem.parent
677
- @pass << false
678
- app.xpath('rdg').each { |rdg|
679
- if rdg['wit'].include? @orig
680
- s = traverse(rdg, 'back')
681
- s = MISSING if s.empty?
682
- r += @orig + s
683
- end
684
- }
685
- @pass.pop
686
- r += '。' unless r.empty?
687
- r
688
- end
689
-
690
- def linehead_exist_in_cbeta(s)
691
- fn = CBETA.linehead_to_xml_file_path(s)
692
- return false if fn.nil?
693
-
694
- path = File.join(@xml_root, fn)
695
- File.exist? path
696
- end
697
-
698
- def open_xml(fn)
699
- s = File.read(fn)
700
-
701
- if fn.include? 'T16n0657'
702
- # 這個地方 雙行夾註 跨兩行偈頌
703
- # 把 lb 移到 note 結束之前
704
- # 讓 lg-row 先結束,再結束雙行夾註
705
- s.sub!(/(<\/note>)(\n<lb n="0206b29" ed="T"\/>)/, '\2\1')
706
- end
707
-
708
- # <milestone unit="juan"> 前面的 lb 屬於新的這一卷
709
- s.gsub!(%r{((?:<pb [^>]+>\n?)?(?:<lb [^>]+>\n?)+)(<milestone [^>]*unit="juan"[^/>]*/>)}, '\2\1')
710
-
711
- begin
712
- doc = Nokogiri::XML(s) { |config| config.strict }
713
- rescue Nokogiri::XML::SyntaxError => e
714
- puts "XML parse error, file: #{fn}"
715
- puts e
716
- abort
717
- end
718
- doc.remove_namespaces!()
719
- doc
720
- end
721
-
722
- def read_mod_notes(doc)
723
- doc.xpath("//note[@type='mod']").each { |e|
724
- n = e['n']
725
- @mod_notes << n
726
-
727
- # 例 T01n0026_p0506b07, 原註標為 7, CBETA 修訂為 7a, 7b
728
- n.match(/[a-z]$/) {
729
- @mod_notes << n[0..-2]
730
- }
731
- }
732
- end
733
-
734
- def parse_xml(xml_fn)
735
- @pass = [false]
736
-
737
- doc = open_xml(xml_fn)
738
-
739
- e = doc.xpath("//titleStmt/title")[0]
740
- @title = traverse(e, 'txt')
741
- @title = @title.split()[-1]
742
-
743
- e = doc.at_xpath("//editionStmt/edition/date")
744
- abort "找不到版本日期" if e.nil?
745
- @edition_date = e.text.sub(/\$Date: (.*?) \$$/, '\1')
746
-
747
- e = doc.at_xpath("//projectDesc/p[@lang='zh']")
748
- abort "找不到貢獻者" if e.nil?
749
- @contributors = e.text
750
-
751
- read_mod_notes(doc)
752
-
753
- root = doc.root()
754
- body = root.xpath("text/body")[0]
755
- @pass = [true]
756
-
757
- text = traverse(body)
758
- text
759
- end
760
-
761
- def traverse(e, mode='html')
762
- r = ''
763
- e.children.each { |c|
764
- s = handle_node(c, mode)
765
- r += s
766
- }
767
- r
768
- end
769
-
770
- def write_juan(juan_no, body)
771
- #if @sutra_no.match(/^(T05|T06|T07)n0220/)
772
- # fn = "#{$1}n0220_%03d.htm" % juan_no
773
- #else
774
- # fn = "#{@sutra_no}_%03d.htm" % juan_no
775
- #end
776
- fn = "#{@sutra_no}_%03d.htm" % juan_no
777
-
778
- html = <<eos
779
- <html>
780
- <head>
781
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
782
- <meta name="filename" content="#{fn}" />
783
- <title>#{@title}</title>
784
- </head>
785
- <body>
786
- <!--
787
- 來源 XML CBETA P5a: https://github.com/cbeta-org/xml-p5a.git
788
- 轉檔程式: https://rubygems.org/gems/cbeta #{Date.today}
789
- 說明文件: http://wiki.ddbc.edu.tw/pages/CBETA_XML_P5a_轉_HTML
790
- -->
791
- <div id='body'>
792
- eos
793
- html += body + "\n</div><!-- end of div[@id='body'] -->\n"
794
- html += "<div id='back'>\n" + @back[juan_no] + "</div>\n"
795
- html += "<div id='cbeta-copyright'><p>\n"
796
-
797
- orig = @cbeta.get_canon_nickname(@series)
798
- v = @vol.sub(/^[A-Z]0*([^0].*)$/, '\1')
799
- n = @sutra_no.sub(/^[A-Z]\d{2,3}n0*([^0].*)$/, '\1')
800
- html += "【經文資訊】#{orig}第 #{v} 冊 No. #{n} #{@title}<br/>\n"
801
- html += "【版本記錄】CBETA 電子佛典 版本日期:#{@edition_date}<br/>\n"
802
- html += "【編輯說明】本資料庫由中華電子佛典協會(CBETA)依#{orig}所編輯<br/>\n"
803
-
804
- html += "【原始資料】#{@contributors}<br/>\n"
805
- html += "【其他事項】本資料庫可自由免費流通,詳細內容請參閱【中華電子佛典協會資料庫版權宣告】\n"
806
- html += "</p></div><!-- end of cbeta-copyright -->\n"
807
- html += '</body></html>'
808
-
809
- output_path = File.join(@out_folder, fn)
810
- File.write(output_path, html)
811
- end
812
-
813
- end