asip-meteor 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/meteor.rb ADDED
@@ -0,0 +1,4221 @@
1
+ # -* coding: UTF-8 -*-
2
+ # Meteor - A lightweight (X)HTML & XML parser
3
+ #
4
+ # Copyright (C) 2008 Yasumasa Ashida.
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #
20
+ # @author Yasumasa Ashida
21
+ # @version 0.9.0
22
+ #
23
+ if RUBY_VERSION < '1.9.0' then
24
+ require 'kconv'
25
+ end
26
+
27
+
28
+ module Meteor
29
+
30
+ VERSION = "0.9.0"
31
+
32
+ #
33
+ # 要素クラス
34
+ #
35
+ class Element
36
+
37
+ #
38
+ # イニシャライザ
39
+ # @param [Array] args 引数配列
40
+ #
41
+ def initialize(*args)
42
+ case args.length
43
+ when 1
44
+ if args[0].kind_of?(String) then
45
+ initialize_s(args[0])
46
+ elsif args[0].kind_of?(Meteor::Element)
47
+ initialize_e(args[0])
48
+ else
49
+ raise ArgumentError
50
+ end
51
+ else
52
+ raise ArgumentError
53
+ end
54
+ end
55
+
56
+ #
57
+ # イニシャライザ
58
+ # @param [String] name タグ名
59
+ #
60
+ def initialize_s(name)
61
+ @name = name
62
+ #@attributes = nil
63
+ #@mixed_content = nil
64
+ #@pattern = nil
65
+ #@document = nil
66
+ #@parser=nil
67
+ #@empty = false
68
+ #@cx = false
69
+ #@mono = false
70
+ #@parent = false
71
+ @arguments = AttributeMap.new
72
+ end
73
+
74
+ #
75
+ # イニシャライザ
76
+ # @param [Meteor::Element] elm 要素
77
+ #
78
+ def initialize_e(elm)
79
+ @name = elm.name
80
+ @attributes = String.new(elm.attributes)
81
+ @mixed_content = String.new(elm.mixed_content)
82
+ @pattern = String.new(elm.pattern)
83
+ @document = String.new(elm.document)
84
+ @empty = elm.empty
85
+ @cx = elm.cx
86
+ @mono = elm.mono
87
+ @parent = elm.parent
88
+ @parser = elm.parser
89
+ @arguments = AttributeMap.new(elm.arguments)
90
+ end
91
+
92
+ attr_accessor :name
93
+ attr_accessor :attributes
94
+ attr_accessor :mixed_content
95
+ attr_accessor :pattern
96
+ attr_accessor :document
97
+ attr_accessor :empty
98
+ attr_accessor :cx
99
+ attr_accessor :mono
100
+ attr_accessor :parent
101
+ attr_accessor :parser
102
+ attr_accessor :type_value
103
+ attr_accessor :arguments
104
+
105
+ #
106
+ # 属性を編集する or 属性の値を取得する
107
+ #
108
+ # @param [Array] args 引数配列
109
+ # @return [String] 属性値
110
+ #
111
+ def attribute(*args)
112
+ @parser.attribute(self,*args)
113
+ end
114
+
115
+ #
116
+ # 属性マップを取得する
117
+ #
118
+ # @return [Meteor::AttributeMap] 属性マップ
119
+ #
120
+ def attributeMap
121
+ @parser.attributeMap(self)
122
+ end
123
+
124
+ #
125
+ # 内容をセットする or 内容を取得する
126
+ #
127
+ # @param [Array] args 引数配列
128
+ # @return [String] 内容
129
+ #
130
+ def content(*args)
131
+ @parser.content(self,*args)
132
+ end
133
+
134
+ #
135
+ # 属性を編集するor内容をセットする
136
+ #
137
+ # @param [String] name 属性の名前
138
+ # @param [String] value 属性の値or内容
139
+ #
140
+ def []=(name,value)
141
+ if !name.kind_of?(String) || name != ':content' then
142
+ attribute(name,value)
143
+ else
144
+ content(value)
145
+ end
146
+ end
147
+
148
+ #
149
+ # 属性の値or内容を取得する
150
+ #
151
+ # @param [String] name 属性の名前
152
+ # @return [String] 属性の値or内容
153
+ #
154
+ def [](name)
155
+ if !name.kind_of?(String) || name != ':content' then
156
+ getAttributeValue(name)
157
+ else
158
+ content()
159
+ end
160
+ end
161
+
162
+ #
163
+ # 属性を削除する
164
+ #
165
+ # @param args 引数配列
166
+ #
167
+ def removeAttribute(*args)
168
+ @parser.removeAttribute(self,*args)
169
+ end
170
+
171
+ #
172
+ # 要素を削除する
173
+ #
174
+ def remove
175
+ @parser.removeElement(self)
176
+ end
177
+
178
+ end
179
+
180
+ #
181
+ # ルート要素クラス
182
+ #
183
+ class RootElement
184
+
185
+ #
186
+ # イニシャライザ
187
+ #
188
+ def initialize()
189
+ #コンテントタイプ
190
+ @contentType = ''
191
+ #改行コード
192
+ @kaigyoCode = ''
193
+ #文字コード
194
+ @characterEncoding=''
195
+
196
+ #フックドキュメント
197
+ @hookDocument =''
198
+ #フック判定フラグ
199
+ #@hook = false
200
+ #単一要素フック判定フラグ
201
+ #@monoHook = false
202
+ #要素
203
+ #@element = nil
204
+ #変更可能要素
205
+ #@mutableElement = nil
206
+ end
207
+
208
+ attr_accessor :contentType
209
+ attr_accessor :kaigyoCode
210
+ attr_accessor :characterEncoding
211
+ attr_accessor :hookDocument
212
+ attr_accessor :hook;
213
+ attr_accessor :monoHook
214
+ attr_accessor :element
215
+ attr_accessor :mutableElement
216
+ attr_accessor :document
217
+ end
218
+
219
+ #
220
+ # 属性マップクラス
221
+ #
222
+ class AttributeMap
223
+
224
+ def initialize(*args)
225
+ case args.length
226
+ when 0
227
+ initialize_0
228
+ when 1
229
+ initialize_1(args[0])
230
+ else
231
+ raise ArgumentError
232
+ end
233
+ end
234
+
235
+ #
236
+ # イニシャライザ
237
+ #
238
+ def initialize_0
239
+ @map = Hash.new
240
+ if RUBY_VERSION < '1.9.0'
241
+ @names = Array.new
242
+ end
243
+ @recordable = false
244
+ end
245
+
246
+ #
247
+ # イニシャライザ
248
+ #
249
+ def initialize_1(attrMap)
250
+ #@map = Marshal.load(Marshal.dump(attrMap.map))
251
+ @map = attrMap.map.dup
252
+ if RUBY_VERSION < '1.9.0'
253
+ @names = Array.new(attrMap.names)
254
+ end
255
+ @recordable = attrMap.recordable
256
+ end
257
+
258
+ #
259
+ # 属性名と属性値を対としてセットする
260
+ #
261
+ # @param [String] name 属性名
262
+ # @param [String] value 属性値
263
+ #
264
+ def store(name,value)
265
+
266
+ if !@map[name] then
267
+ attr = Attribute.new
268
+ attr.name = name
269
+ attr.value = value
270
+ if @recordable then
271
+ attr.changed = true
272
+ attr.removed = false
273
+ end
274
+ @map[name] = attr
275
+ if RUBY_VERSION < "1.9.0"
276
+ @names << name
277
+ end
278
+ else
279
+ attr = @map[name]
280
+ if @recordable && attr.value != value then
281
+ attr.changed = true
282
+ attr.removed = false
283
+ end
284
+ attr.value = value
285
+ #@map[name] = attr
286
+ end
287
+ end
288
+
289
+ #
290
+ # 属性名配列を取得する
291
+ #
292
+ # @return [Array] 属性名配列
293
+ #
294
+ def names
295
+ if RUBY_VERSION < "1.9.0"
296
+ @names
297
+ else
298
+ @map.keys
299
+ end
300
+ end
301
+
302
+ #
303
+ # 属性名で属性値を取得する
304
+ #
305
+ # @param [String] name 属性名
306
+ # @return [String] 属性値
307
+ #
308
+ def fetch(name)
309
+ if @map[name] && !@map[name].removed then
310
+ @map[name].value
311
+ end
312
+ end
313
+
314
+ #
315
+ # 属性名に対応した属性を削除する
316
+ #
317
+ # @param name 属性名
318
+ #
319
+ def delete(name)
320
+ if @map[name] && @recordable then
321
+ @map[name].removed = true
322
+ @map[name].changed = false
323
+ end
324
+ end
325
+
326
+ #
327
+ # 属性名で属性の変更状況を取得する
328
+ #
329
+ # @return [TrueClass][FalseClass] 属性の変更状況
330
+ #
331
+ def changed(name)
332
+ if @map[name] then
333
+ @map[name].changed
334
+ end
335
+ end
336
+
337
+ #
338
+ # 属性名で属性の削除状況を取得する
339
+ #
340
+ # @return [TrueClass][FalseClass] 属性の削除状況
341
+ #
342
+ def removed(name)
343
+ if @map[name] then
344
+ @map[name].removed
345
+ end
346
+ end
347
+
348
+ attr_accessor :map
349
+ attr_accessor :recordable
350
+
351
+ #
352
+ # 属性名と属性値を対としてセットする
353
+ #
354
+ # @param [String] name 属性名
355
+ # @param [String] value 属性値
356
+ #
357
+ def [](name,value)
358
+ store(name,value)
359
+ end
360
+
361
+ #
362
+ # 属性名で属性値を取得する
363
+ #
364
+ # @param [String] name 属性名
365
+ # @return [String] 属性値
366
+ #
367
+ def [](name)
368
+ fetch(name)
369
+ end
370
+ end
371
+
372
+ #
373
+ # 属性クラス
374
+ #
375
+ class Attribute
376
+
377
+ #
378
+ # イニシャライザ
379
+ #
380
+ def initialize
381
+ #@name = nil
382
+ #@value = nil
383
+ #@changed = false
384
+ #@removed = false
385
+ end
386
+
387
+ attr_accessor :name
388
+ attr_accessor :value
389
+ attr_accessor :changed
390
+ attr_accessor :removed
391
+
392
+ end
393
+
394
+ #
395
+ # パーサ共通クラス
396
+ #
397
+ class Parser
398
+ HTML = 0
399
+ XHTML = 1
400
+ XML = 2
401
+ end
402
+
403
+ #
404
+ # パーサファクトリクラス
405
+ #
406
+ class ParserFactory
407
+
408
+ #
409
+ # パーサファクトリを生成する
410
+ #
411
+ # @param [Array] args 引数配列
412
+ # @return [Meteor::ParserFactory] パーサファクトリ
413
+ #
414
+ def self.build(*args)
415
+ case args.length
416
+ when 3
417
+ build_3(args[0],args[1],args[2])
418
+ when 2
419
+ build_2(args[0],args[1])
420
+ else
421
+ raise ArgumentError
422
+ end
423
+ end
424
+
425
+ #
426
+ # パーサファクトリを生成する
427
+ #
428
+ # @param [Fixnum] type パーサのタイプ
429
+ # @param [String] path ファイルパス
430
+ # @param [String] encoding エンコーディング
431
+ # @return [Meteor::ParserFactory] パーサファクトリ
432
+ #
433
+ def self.build_3(type,path,encoding)
434
+ psf = ParserFactory.new
435
+
436
+ case type
437
+ when Parser::HTML then
438
+ html = Meteor::Core::Html::ParserImpl.new()
439
+ html.read(path, encoding)
440
+ psf.setParser(html)
441
+ when Parser::XHTML then
442
+ xhtml = Meteor::Core::Xhtml::ParserImpl.new()
443
+ xhtml.read(path, encoding)
444
+ psf.setParser(xhtml)
445
+ when Parser::XML then
446
+ xml = Meteor::Core::Xml::ParserImpl.new()
447
+ xml.read(path, encoding)
448
+ psf.setParser(xml)
449
+ end
450
+
451
+ psf
452
+ end
453
+ #protected :build_3
454
+
455
+ #
456
+ # パーサファクトリを生成する
457
+ #
458
+ # @param [Fixnum] type パーサのタイプ
459
+ # @param [String] document ドキュメント
460
+ # @return [Meteor::ParserFactory] パーサファクトリ
461
+ #
462
+ def self.build_2(type,document)
463
+ psf = ParserFactory.new
464
+
465
+ case type
466
+ when Parser::HTML then
467
+ html = Meteor::Core::Html::ParserImpl.new()
468
+ html.parse(document)
469
+ psf.setParser(html)
470
+ when Parser::XHTML then
471
+ xhtml = Meteor::Core::Xhtml::ParserImpl.new()
472
+ xhtml.parse(document)
473
+ psf.setParser(xhtml)
474
+ when Parser::XML then
475
+ xml = Meteor::Core::Xml::ParserImpl.new()
476
+ xml.parse(document)
477
+ psf.setParser(xml)
478
+ end
479
+
480
+ psf
481
+ end
482
+ #protected :build_2
483
+
484
+ #
485
+ # パーサをセットする
486
+ #
487
+ # @param [Meteor::Parser] パーサ
488
+ #
489
+ def setParser(pif)
490
+ @pif = pif
491
+ end
492
+
493
+ #
494
+ # パーサを取得する
495
+ #
496
+ # @return [Meteor::Parser] パーサ
497
+ #
498
+ def getParser
499
+
500
+ if @pif.instance_of?(Meteor::Core::Html::ParserImpl) then
501
+ Meteor::Core::Html::ParserImpl.new(@pif)
502
+ elsif @pif.instance_of?(Meteor::Core::Xhtml::ParserImpl) then
503
+ Meteor::Core::Xhtml::ParserImpl.new(@pif)
504
+ elsif @pif.instance_of?(Meteor::Core::Xml::ParserImpl) then
505
+ Meteor::Core::Xml::ParserImpl.new(@pif)
506
+ end
507
+ end
508
+
509
+ end
510
+
511
+ module Hook
512
+
513
+ #
514
+ # フッククラス
515
+ #
516
+ class Hooker
517
+
518
+ #
519
+ # イニシャライザ
520
+ #
521
+ def initialize
522
+ end
523
+
524
+ def doAction(elm,pif)
525
+ #内容あり要素の場合
526
+ if elm.empty then
527
+ pif2 = pif.child(elm)
528
+ execute(pif2)
529
+ pif2.flush
530
+ end
531
+ end
532
+
533
+ def execute(pif)
534
+ end
535
+ end
536
+
537
+ #
538
+ # ループフッククラス
539
+ #
540
+ class Looper
541
+
542
+ #
543
+ # イニシャライザ
544
+ #
545
+ def initialize
546
+ end
547
+
548
+ def doAction(elm,pif,list)
549
+ #内容あり要素の場合
550
+ if elm.empty then
551
+ pif2 = pif.child(elm)
552
+
553
+ list.each { |item|
554
+ if pif2.rootElement.hook then
555
+ pif2.rootElement.document = elm.mixed_content
556
+ #elsif pif2.rootElement.monoHook then
557
+ end
558
+ execute(pif2,item)
559
+ }
560
+ pif2.flush
561
+ end
562
+ end
563
+
564
+ def execute(pif,item)
565
+ end
566
+ end
567
+ end
568
+
569
+ module Core
570
+
571
+ #
572
+ # パーサコアクラス
573
+ #
574
+ class Kernel < Meteor::Parser
575
+
576
+ EMPTY = ''
577
+ SPACE = " "
578
+ DOUBLE_QUATATION = "\""
579
+ TAG_OPEN = "<"
580
+ TAG_OPEN3 = "</"
581
+ TAG_OPEN4 = "<\\\\/"
582
+ TAG_CLOSE = ">"
583
+ TAG_CLOSE2 = "\\/>"
584
+ TAG_CLOSE3 = "/>"
585
+ ATTR_EQ = "=\""
586
+ #element
587
+ #TAG_SEARCH_1_1 = "([^<>]*)>(((?!(<\\/"
588
+ TAG_SEARCH_1_1 = "(\\s?[^<>]*)>(((?!("
589
+ #TAG_SEARCH_1_2 = ")).)*)<\\/";
590
+ TAG_SEARCH_1_2 = "[^<>]*>)).)*)<\\/"
591
+ TAG_SEARCH_1_3 = "(\\s?[^<>]*)\\/>"
592
+ #TAG_SEARCH_1_4 = "([^<>\\/]*)>"
593
+ TAG_SEARCH_1_4 = "(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
594
+ TAG_SEARCH_1_4_2 = "(\\s[^<>]*)>"
595
+
596
+ TAG_SEARCH_NC_1_1 = "\\s?[^<>]*>((?!("
597
+ TAG_SEARCH_NC_1_2 = "[^<>]*>)).)*<\\/"
598
+ TAG_SEARCH_NC_1_3 = "\\s?[^<>]*\\/>"
599
+ TAG_SEARCH_NC_1_4 = "(?:\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
600
+ TAG_SEARCH_NC_1_4_2 = "\\s[^<>]*>"
601
+
602
+ #TAG_SEARCH_2_1 = "\\s([^<>]*"
603
+ TAG_SEARCH_2_1 = "(\\s[^<>]*"
604
+ TAG_SEARCH_2_1_2 = "(\\s[^<>]*(?:"
605
+ #TAG_SEARCH_2_2 = "\"[^<>]*)>(((?!(<\\/"
606
+ TAG_SEARCH_2_2 = "\"[^<>]*)>(((?!("
607
+ TAG_SEARCH_2_2_2 = "\")[^<>]*)>(((?!("
608
+ TAG_SEARCH_2_3 = "\"[^<>]*)"
609
+ TAG_SEARCH_2_3_2 = "\"[^<>]*)\\/>"
610
+ TAG_SEARCH_2_3_2_2 = "\")[^<>]*)\\/>"
611
+ #TAG_SEARCH_2_4 = "\"[^<>\\/]*>"
612
+ TAG_SEARCH_2_4 = "(?:[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
613
+ #TAG_SEARCH_2_4_2 = "\"[^<>\\/]*)>"
614
+ TAG_SEARCH_2_4_2 = "(?:[^<>\\/]*>|(?:(?!([^<>]*\\/>))[^<>]*>)))"
615
+ TAG_SEARCH_2_4_2_2 = "\")([^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>)))"
616
+ TAG_SEARCH_2_4_2_3 = "\""
617
+ TAG_SEARCH_2_4_3 = "\"[^<>]*)>"
618
+ TAG_SEARCH_2_4_3_2 = "\")[^<>]*)>"
619
+ TAG_SEARCH_2_4_4 = "\"[^<>]*>"
620
+
621
+ TAG_SEARCH_2_6 = "\"[^<>]*"
622
+ TAG_SEARCH_2_7 = "\"|"
623
+
624
+ TAG_SEARCH_NC_2_1 = "\\s[^<>]*"
625
+ TAG_SEARCH_NC_2_1_2 = "\\s[^<>]*(?:"
626
+ TAG_SEARCH_NC_2_2 = "\"[^<>]*>((?!("
627
+ TAG_SEARCH_NC_2_2_2 = "\")[^<>]*>((?!("
628
+ TAG_SEARCH_NC_2_3 = "\"[^<>]*)"
629
+ TAG_SEARCH_NC_2_3_2 = "\"[^<>]*\\/>"
630
+ TAG_SEARCH_NC_2_3_2_2 = "\")[^<>]*\\/>"
631
+ TAG_SEARCH_NC_2_4 = "(?:[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
632
+ TAG_SEARCH_NC_2_4_2 = "(?:[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
633
+ TAG_SEARCH_NC_2_4_2_2 = "\")(?:[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
634
+ TAG_SEARCH_NC_2_4_2_3 = "\""
635
+ TAG_SEARCH_NC_2_4_3 = "\"[^<>]*>"
636
+ TAG_SEARCH_NC_2_4_3_2 = "\")[^<>]*>"
637
+ TAG_SEARCH_NC_2_4_4 = "\"[^<>]*>"
638
+ TAG_SEARCH_NC_2_6 = "\"[^<>]*"
639
+ TAG_SEARCH_NC_2_7 = "\"|"
640
+
641
+ TAG_SEARCH_3_1 = "<([^<>\"]*)\\s[^<>]*"
642
+ TAG_SEARCH_3_1_2 = "<([^<>\"]*)\\s([^<>]*"
643
+ TAG_SEARCH_3_1_2_2 = "<([^<>\"]*)\\s([^<>]*("
644
+
645
+ TAG_SEARCH_3_2 = "\"[^<>]*\\/>"
646
+ TAG_SEARCH_3_2_2 = "\"[^<>]*)\\/>"
647
+ TAG_SEARCH_3_2_2_2 = "\")[^<>]*)\\/>"
648
+
649
+ TAG_SEARCH_4_1 = "(\\s[^<>\\/]*)>("
650
+ TAG_SEARCH_4_2 = ".*?<"
651
+ #TAG_SEARCH_4_3 = "\\s[^<>\\/]*>"
652
+ TAG_SEARCH_4_3 = "(\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
653
+ TAG_SEARCH_4_4 = "<\\/"
654
+ TAG_SEARCH_4_5 = ".*?<\/"
655
+ TAG_SEARCH_4_6 = ".*?)<\/"
656
+ #TAG_SEARCH_4_7 = "\"[^<>\\/]*)>("
657
+ TAG_SEARCH_4_7 = "\"(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))("
658
+ TAG_SEARCH_4_7_2 = "\")(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))("
659
+
660
+ TAG_SEARCH_NC_3_1 = "<[^<>\"]*\\s[^<>]*"
661
+ TAG_SEARCH_NC_3_1_2 = "<([^<>\"]*)\\s(?:[^<>]*"
662
+ TAG_SEARCH_NC_3_1_2_2 = "<([^<>\"]*)\\s(?:[^<>]*("
663
+ TAG_SEARCH_NC_3_2 = "\"[^<>]*\\/>"
664
+ TAG_SEARCH_NC_3_2_2 = "\"[^<>]*)\\/>"
665
+ TAG_SEARCH_NC_3_2_2_2 = "\")[^<>]*)\\/>"
666
+ #TAG_SEARCH_NC_4_1 = "(?:\\s[^<>\\/]*)>("
667
+ #TAG_SEARCH_NC_4_2 = ".*?<"
668
+ #TAG_SEARCH_NC_4_3 = "(?:\\s[^<>\\/]*>|((?!([^<>]*\\/>))[^<>]*>))"
669
+ #TAG_SEARCH_NC_4_4 = "<\\/"
670
+ #TAG_SEARCH_NC_4_5 = ".*?<\/"
671
+ #TAG_SEARCH_NC_4_6 = ".*?<\/"
672
+ #TAG_SEARCH_NC_4_7 = "\"(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))("
673
+ #TAG_SEARCH_NC_4_7_2 = "\")(?:[^<>\\/]*>|(?!([^<>]*\\/>))[^<>]*>))("
674
+
675
+ #setAttribute
676
+ SET_ATTR_1 = "=\"[^\"]*\""
677
+ #getAttributeValue
678
+ GET_ATTR_1 = "=\"([^\"]*)\""
679
+ #attributeMap
680
+ #todo
681
+ GET_ATTRS_MAP = "([^\\s]*)=\"([^\"]*)\""
682
+ #removeAttribute
683
+ ERASE_ATTR_1 = "=\"[^\"]*\"\\s"
684
+
685
+ #cxtag
686
+ SEARCH_CX_1 = "<!--\\s@"
687
+ SEARCH_CX_2 = "\\s([^<>]*id=\""
688
+ SEARCH_CX_3 = "\"[^<>]*)-->(((?!(<!--\\s\\/@"
689
+ SEARCH_CX_4 = ")).)*)<!--\\s\\/@"
690
+ SEARCH_CX_5 = "\\s-->"
691
+ SEARCH_CX_6 = "<!--\\s@([^<>]*)\\s[^<>]*id=\""
692
+
693
+ #setElementToCXTag
694
+ SET_CX_1 = "<!-- @"
695
+ SET_CX_2 = "-->"
696
+ SET_CX_3 = "<!-- /@"
697
+ SET_CX_4 = " -->"
698
+
699
+ #setMonoInfo
700
+ SET_MONO_1 = "\\A[^<>]*\\Z"
701
+
702
+ #clean
703
+ CLEAN_1 = "<!--\\s@[^<>]*\\s[^<>]*(\\s)*-->"
704
+ CLEAN_2 = "<!--\\s\\/@[^<>]*(\\s)*-->"
705
+ #escape
706
+ AND_1 = '&'
707
+ AND_2 = '&amp;'
708
+ LT_1 = '<'
709
+ LT_2 = '&lt;'
710
+ GT_1 = '>'
711
+ GT_2 = '&gt;'
712
+ QO_2 = '&quot;'
713
+ AP_1 = '\''
714
+ AP_2 = '&apos;'
715
+ #EN_1 = "\\\\"
716
+ EN_1 = "\\"
717
+ #EN_2 = "\\\\\\\\"
718
+ #DOL_1 = "\\\$"
719
+ #DOL_2 = "\\\\\\$"
720
+ #PLUS_1 = "\\\+"
721
+ #PLUS_2 = "\\\\\\+"
722
+
723
+ SUB_REGEX1 = "(\\\\*)\\\\([0-9]+)"
724
+ SUB_REGEX2 = "\\1\\1\\\\\\\\\\2"
725
+ SUB_REGEX3 = "\\1\\1\\1\\1\\\\\\\\\\\\\\\\\\2"
726
+
727
+ @@pattern_get_attrs_map = Regexp.new(GET_ATTRS_MAP)
728
+
729
+ #BRAC_OPEN_1 = "\\\("
730
+ #BRAC_OPEN_2 = "\\\\\\("
731
+ #BRAC_CLOSE_1 = "\\\)"
732
+ #BRAC_CLOSE_2 = "\\\\\\)"
733
+ #SBRAC_OPEN_1 = "\\\["
734
+ #SBRAC_OPEN_2 = "\\\\\\["
735
+ #SBRAC_CLOSE_1 = "\\\]"
736
+ #SBRAC_CLOSE_2 = "\\\\\\]"
737
+ #CBRAC_OPEN_1 = "\\\{"
738
+ #CBRAC_OPEN_2 = "\\\\\\{"
739
+ #CBRAC_CLOSE_1 = "\\\}"
740
+ #CBRAC_CLOSE_2 = "\\\\\\}"
741
+ #COMMA_1 = "\\\."
742
+ #COMMA_2 = "\\\\\\."
743
+ #VLINE_1 = "\\\|"
744
+ #VLINE_2 = "\\\\\\|"
745
+ #QMARK_1 = "\\\?"
746
+ #QMARK_2 = "\\\\\\?"
747
+ #ASTERISK_1 = "\\\*"
748
+ #ASTERISK_2 = "\\\\\\*"
749
+
750
+ #@@pattern_en = Regexp.new(EN_1)
751
+ #@@pattern_dol = Regexp.new(DOL_1)
752
+ #@@pattern_plus = Regexp.new(PLUS_1)
753
+ #@@pattern_brac_open = Regexp.new(BRAC_OPEN_1)
754
+ #@@pattern_brac_close = Regexp.new(BRAC_CLOSE_1)
755
+ #@@pattern_sbrac_open = Regexp.new(SBRAC_OPEN_1)
756
+ #@@pattern_sbrac_close = Regexp.new(SBRAC_CLOSE_1)
757
+ #@@pattern_cbrac_open = Regexp.new(CBRAC_OPEN_1)
758
+ #@@pattern_cbrac_close = Regexp.new(CBRAC_CLOSE_1)
759
+ #@@pattern_comma = Regexp.new(COMMA_1)
760
+ #@@pattern_vline = Regexp.new(VLINE_1)
761
+ #@@pattern_qmark = Regexp.new(QMARK_1)
762
+ #@@pattern_asterisk = Regexp.new(ASTERISK_1)
763
+
764
+ @@pattern_sub_regex1 = Regexp.new(SUB_REGEX1)
765
+
766
+ @@pattern_clean1 = Regexp.new(CLEAN_1)
767
+ @@pattern_clean2 = Regexp.new(CLEAN_2)
768
+
769
+
770
+ #
771
+ # イニシャライザ
772
+ # @param [Array] args 引数配列
773
+ #
774
+ def initialize(*args)
775
+ #親要素
776
+ #@parent = nil;
777
+
778
+ #正規表現パターン
779
+ #@pattern = nil
780
+ #ルート要素
781
+ @root = RootElement.new
782
+ if RUBY_VERSION >= '1.9.0' then
783
+ @e_cache = Hash.new()
784
+ else
785
+ @e_cache = Meteor::Core::Util::OrderHash.new
786
+ end
787
+ #@res = nil
788
+ #@_attributes = nil
789
+ #@_mixed_content = nil
790
+ #@pattern_cc = nil
791
+ #@pattern_cc_1 = nil
792
+ #@pattern_cc_1b = nil
793
+ #@pattern_cc_1_1 = nil
794
+ #@pattern_cc_1_2 = nil
795
+ #@pattern_cc_2 = nil
796
+ #@pattern_cc_2_1 = nil
797
+ #@pattern_cc_2_2 = nil
798
+ #@cnt = 0
799
+ #@position = 0
800
+ #@position2 = 0
801
+ #@_elmName = nil
802
+ #@_attrName = nil
803
+ #@_attrValue = nil
804
+ #@_attrName1 = nil
805
+ #@_attrValue1 = nil
806
+ #@_attrName2 = nil
807
+ #@_attrValue2 = nil
808
+
809
+ #@sbuf = nil;
810
+ #@rx_document = nil;
811
+ #@rx_document2 = nil;
812
+ end
813
+
814
+ #
815
+ # ドキュメントをセットする
816
+ #
817
+ # @param [String] doc ドキュメント
818
+ #
819
+ def document=(doc)
820
+ @root.document = doc
821
+ end
822
+
823
+ #
824
+ # ドキュメントを取得する
825
+ #
826
+ # @return [String] ドキュメント
827
+ #
828
+ def document
829
+ @root.document
830
+ end
831
+
832
+ attr_accessor :parent
833
+
834
+ #
835
+ # フックフラグをセットする
836
+ #
837
+ # @param [TrueClass][FalseClass] hook フックフラグ
838
+ #
839
+ def hook=(hook)
840
+ @root.hook = hook
841
+ end
842
+
843
+ #
844
+ # フックフラグを取得する
845
+ #
846
+ # @return [TrueClass][FalseClass] フックフラグ
847
+ #
848
+ def hook
849
+ @root.hook
850
+ end
851
+
852
+ #
853
+ # 単一要素フックフラグをセットする
854
+ #
855
+ # @pamam [TrueClass][FalseClass] hook 単一要素フックフラグ
856
+ #
857
+ def monoHook=(hook)
858
+ @root.monoHook = hook
859
+ end
860
+
861
+ #
862
+ # 単一要素フックフラグを取得する
863
+ #
864
+ # @return [TrueClass][FalseClass] 単一要素フックフラグ
865
+ #
866
+ def monoHook
867
+ @root.monoHook
868
+ end
869
+
870
+ #
871
+ # フックドキュメントをセットする
872
+ #
873
+ # @param [String] hookDocument フックドキュメント
874
+ #
875
+ def hookDocument=(hookDocument)
876
+ @root.hookDocument = hookDocument
877
+ end
878
+
879
+ #
880
+ # フックドキュメントを取得する
881
+ #
882
+ # @return [String] フックドキュメント
883
+ #
884
+ def hookDocument
885
+ @root.hookDocument
886
+ end
887
+
888
+ #
889
+ # 文字エンコーディングをセットする
890
+ #
891
+ # @param [String] enc 文字エンコーディング
892
+ #
893
+ def characterEncoding=(enc)
894
+ @root.characterEncoding = enc
895
+ end
896
+
897
+ #
898
+ # 文字エンコーディングを取得する
899
+ #
900
+ # @param [String] 文字エンコーディング
901
+ #
902
+ def characterEncoding
903
+ @root.characterEncoding
904
+ end
905
+
906
+ #
907
+ # ルート要素を取得する
908
+ #
909
+ # @return [Meteor::RootElement] ルート要素
910
+ #
911
+ def rootElement
912
+ @root
913
+ end
914
+
915
+ #
916
+ # ファイルを読み込み、パーサにセットする
917
+ #
918
+ # @param [String] filePath 入力ファイルの絶対パス
919
+ # @param [String] encoding 入力ファイルの文字コード
920
+ #
921
+ def read(filePath, encoding)
922
+
923
+ #try {
924
+ @characterEncoding = encoding
925
+ #ファイルのオープン
926
+ if RUBY_VERSION >= '1.9.0' then
927
+ io = File.open(filePath,'r:' << encoding)
928
+ #読込及び格納
929
+ @root.document = io.read
930
+ else
931
+ #読込及び格納
932
+ io = open(filePath,'r')
933
+ @root.document = io.read
934
+ @root.document = @root.document.kconv(get_encoding(), Kconv.guess(@root.document))
935
+ end
936
+
937
+ #ファイルのクローズ
938
+ io.close
939
+
940
+ #@root.document = str
941
+
942
+ #} catch (FileNotFoundException e) {
943
+ #FileNotFoundException時の処理
944
+ #e.printStackTrace();
945
+ #@document = EMPTY;
946
+ #} catch (Exception e) {
947
+ # //上記以外の例外時の処理
948
+ # e.printStackTrace();
949
+ # this.setDocument(EMPTY);
950
+ #}
951
+
952
+ end
953
+
954
+ def get_encoding()
955
+ case @characterEncoding
956
+ when "UTF-8"
957
+ Kconv::UTF8
958
+ when "ISO-2022-JP"
959
+ Kconv::JIS
960
+ when "Shift_JIS"
961
+ Kconv::SJIS
962
+ when "EUC-JP"
963
+ Kconv::EUC
964
+ when "ASCII"
965
+ Kconv::ASCII
966
+ #when "UTF-16"
967
+ # return KConv::UTF16
968
+ else
969
+ KConv::UTF8
970
+ end
971
+ end
972
+ private :get_encoding
973
+
974
+ #
975
+ # 要素を取得する
976
+ #
977
+ # @param [Array] args 引数配列
978
+ # @return [Meteor::Element] 要素
979
+ #
980
+ def element(*args)
981
+ case args.length
982
+ when 1
983
+ element_1(args[0])
984
+ when 2
985
+ element_2(args[0],args[1])
986
+ when 3
987
+ element_3(args[0],args[1],args[2])
988
+ when 4
989
+ element_4(args[0],args[1],args[2],args[3])
990
+ when 5
991
+ element_5(args[0],args[1],args[2],args[3],args[4])
992
+ else
993
+ raise ArgumentError
994
+ end
995
+ end
996
+
997
+ #
998
+ # 要素名で検索し、要素を取得する
999
+ #
1000
+ # @param [String] elmName 要素名
1001
+ # @return [Meteor::Element] 要素
1002
+ #
1003
+ def element_1(elmName)
1004
+
1005
+ @_elmName = escapeRegex(elmName)
1006
+
1007
+ #空要素検索用パターン
1008
+ @pattern_cc_1 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_1_3
1009
+
1010
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
1011
+ #空要素検索
1012
+ @res1 = @pattern.match(@root.document)
1013
+
1014
+ #内容あり要素検索用パターン
1015
+ @pattern_cc_2 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_1_1 << elmName
1016
+ @pattern_cc_2 << TAG_SEARCH_1_2 << @_elmName << TAG_CLOSE
1017
+
1018
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1019
+ #内容あり要素検索
1020
+ @res2 = @pattern.match(@root.document)
1021
+
1022
+ if @res1 && @res2 then
1023
+ if @res1.end(0) < @res2.end(0) then
1024
+ @res = @res1
1025
+ @pattern_cc = @pattern_cc_1
1026
+ @elm_ = elementWithoutContent_1(elmName)
1027
+ elsif @res1.end(0) > @res2.end(0)
1028
+ @res = @res2
1029
+ @pattern_cc = @pattern_cc_2
1030
+ @elm_ = elementWithContent_1(elmName)
1031
+ end
1032
+ elsif @res1 && !@res2 then
1033
+ @res = @res1
1034
+ @pattern_cc = @pattern_cc_1
1035
+ @elm_ = elementWithoutContent_1(elmName)
1036
+ elsif !@res1 && @res2 then
1037
+ @res = @res2
1038
+ @pattern_cc = @pattern_cc_2
1039
+ @elm_ = elementWithContent_1(elmName)
1040
+ elsif !@res1 && !@res2 then
1041
+ @elm_ = nil
1042
+ #raise NoSuchElementException.new(elmName);
1043
+ end
1044
+
1045
+ @elm_
1046
+ end
1047
+ private :element_1
1048
+
1049
+ def elementWithContent_1(elmName)
1050
+
1051
+ @elm_ = Element.new(elmName)
1052
+ #属性
1053
+ @elm_.attributes = @res[1]
1054
+ #内容
1055
+ @elm_.mixed_content = @res[2]
1056
+ #全体
1057
+ @elm_.document = @res[0]
1058
+
1059
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_NC_1_1 << elmName
1060
+ @pattern_cc << TAG_SEARCH_NC_1_2 << @_elmName << TAG_CLOSE
1061
+
1062
+ #内容あり要素検索用パターン
1063
+ @elm_.pattern = @pattern_cc
1064
+
1065
+ @elm_.empty = true
1066
+
1067
+ @elm_.parser = self
1068
+
1069
+ @elm_
1070
+ end
1071
+ private :elementWithContent_1
1072
+
1073
+ def elementWithoutContent_1(elmName)
1074
+ #要素
1075
+ @elm_ = Element.new(elmName)
1076
+ #属性
1077
+ @elm_.attributes = @res[1]
1078
+ #全体
1079
+ @elm_.document = @res[0]
1080
+ #空要素検索用パターン
1081
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_NC_1_3
1082
+ @elm_.pattern = @pattern_cc
1083
+
1084
+ @elm_.empty = false
1085
+
1086
+ @elm_.parser = self
1087
+
1088
+ @elm_
1089
+ end
1090
+ private :elementWithoutContent_1
1091
+
1092
+ #
1093
+ # 要素名と属性で検索し、要素を取得する
1094
+ #
1095
+ # @param [String] elmName 要素名
1096
+ # @param [String] attrName 属性名
1097
+ # @param [String] attrValue 属性値
1098
+ # @return [Meteor::Element] 要素
1099
+ #
1100
+ def element_3(elmName,attrName,attrValue)
1101
+
1102
+ @_elmName = escapeRegex(elmName)
1103
+ @_attrName = escapeRegex(attrName)
1104
+ @_attrValue = escapeRegex(attrValue)
1105
+
1106
+ #空要素検索用パターン
1107
+ @pattern_cc_1 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1 << @_attrName << ATTR_EQ
1108
+ @pattern_cc_1 << @_attrValue << TAG_SEARCH_2_3_2
1109
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
1110
+ #空要素検索
1111
+ @res1 = @pattern.match(@root.document)
1112
+
1113
+ #内容あり要素検索パターン
1114
+ @pattern_cc_2 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1 << @_attrName << ATTR_EQ
1115
+ @pattern_cc_2 << @_attrValue << TAG_SEARCH_2_2 << @_elmName
1116
+ @pattern_cc_2 << TAG_SEARCH_1_2 << @_elmName << TAG_CLOSE
1117
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1118
+ #内容あり要素検索
1119
+ @res2 = @pattern.match(@root.document)
1120
+
1121
+ if !@res2 then
1122
+ @res2 = elementWithContent_3_2(elmName)
1123
+ @pattern_cc_2 = @pattern_cc
1124
+ end
1125
+
1126
+ if @res1 && @res2 then
1127
+ if @res1.begin(0) < @res2.begin(0) then
1128
+ @res = @res1
1129
+ @pattern_cc = @pattern_cc_1
1130
+ elementWithoutContent_3(elmName)
1131
+ elsif @res1.begin(0) > @res2.begin(0)
1132
+ @res = @res2
1133
+ @pattern_cc = @pattern_cc_2
1134
+ elementWithContent_3_1(elmName)
1135
+ end
1136
+ elsif @res1 && !@res2 then
1137
+ @res = @res1
1138
+ @pattern_cc = @pattern_cc_1
1139
+ elementWithoutContent_3(elmName)
1140
+ elsif !@res1 && @res2 then
1141
+ @res = @res2
1142
+ @pattern_cc = @pattern_cc_2
1143
+ elementWithContent_3_1(elmName)
1144
+ elsif !@res1 && !@res2 then
1145
+ @elm_ = nil
1146
+ #raise NoSuchElementException.new(elmName,attrName,attrValue);
1147
+ end
1148
+
1149
+ if @elm_ then
1150
+ @elm_.arguments.store(attrName, attrValue)
1151
+ @elm_.arguments.recordable = true
1152
+ end
1153
+
1154
+ @elm_
1155
+ end
1156
+ private :element_3
1157
+
1158
+ def elementWithContent_3_1(elmName)
1159
+
1160
+ if @res.captures.length == 4 then
1161
+ #要素
1162
+ @elm_ = Element.new(elmName)
1163
+ #属性
1164
+ @elm_.attributes = @res[1]
1165
+ #内容
1166
+ @elm_.mixed_content = @res[2]
1167
+ #全体
1168
+ @elm_.document = @res[0]
1169
+ #内容あり要素検索用パターン
1170
+ @pattern_cc = ''<< TAG_OPEN << @_elmName << TAG_SEARCH_NC_2_1 << @_attrName << ATTR_EQ
1171
+ @pattern_cc << @_attrValue << TAG_SEARCH_NC_2_2 << @_elmName
1172
+ @pattern_cc << TAG_SEARCH_NC_1_2 << @_elmName << TAG_CLOSE
1173
+ @elm_.pattern = @pattern_cc
1174
+
1175
+ @elm_.empty = true
1176
+
1177
+ @elm_.parser = self
1178
+
1179
+ elsif @res.captures.length == 6 then
1180
+ #内容
1181
+ @elm_ = Element.new(elmName)
1182
+ #属性
1183
+ @elm_.attributes = @res[1].chop
1184
+ #内容
1185
+ @elm_.mixed_content = @res[3]
1186
+ #全体
1187
+ @elm_.document = @res[0]
1188
+ #内容あり要素検索用パターン
1189
+ @elm_.pattern = @pattern_cc
1190
+
1191
+ @elm_.empty = true
1192
+
1193
+ @elm_.parser = self
1194
+ end
1195
+ end
1196
+ private :elementWithContent_3_1
1197
+
1198
+ def elementWithContent_3_2(elmName)
1199
+ @cnt = 0
1200
+
1201
+ @pattern_cc_1 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1 << @_attrName << ATTR_EQ
1202
+ @pattern_cc_1 << @_attrValue << TAG_SEARCH_2_4_2
1203
+
1204
+ @pattern_cc_1b = '' << TAG_OPEN << @_elmName << TAG_SEARCH_1_4
1205
+
1206
+ @pattern_cc_1_1 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1 << @_attrName << ATTR_EQ
1207
+ @pattern_cc_1_1 << @_attrValue << TAG_SEARCH_4_7
1208
+
1209
+ @pattern_cc_1_2 = '' << TAG_SEARCH_4_2 << @_elmName << TAG_SEARCH_4_3
1210
+
1211
+ @pattern_cc_2 = '' << TAG_SEARCH_4_4 << @_elmName << TAG_CLOSE
1212
+
1213
+ @pattern_cc_2_1 = '' << TAG_SEARCH_4_5 << @_elmName << TAG_CLOSE
1214
+
1215
+ @pattern_cc_2_2 = '' << TAG_SEARCH_4_6 << @_elmName << TAG_CLOSE
1216
+
1217
+ #内容あり要素検索
1218
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
1219
+
1220
+ @sbuf = '';
1221
+
1222
+ if RUBY_VERSION >= '1.9.0' then
1223
+
1224
+ @position = 0
1225
+
1226
+ while (@res = @pattern.match(@root.document,@position)) || @cnt > 0
1227
+
1228
+ if @res then
1229
+
1230
+ if @cnt > 0 then
1231
+
1232
+ @position2 = @res.end(0)
1233
+
1234
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1235
+ @res = @pattern.match(@root.document,@position)
1236
+
1237
+ if @res then
1238
+
1239
+ @position = @res.end(0)
1240
+
1241
+ if @position > @position2 then
1242
+
1243
+ if @cnt == 0 then
1244
+ @sbuf << @pattern_cc_1_1
1245
+ else
1246
+ @sbuf << @pattern_cc_1_2
1247
+ end
1248
+
1249
+ @cnt += 1
1250
+
1251
+ @position = @position2
1252
+ else
1253
+
1254
+ @cnt -= 1
1255
+
1256
+ if @cnt != 0 then
1257
+ @sbuf << @pattern_cc_2_1
1258
+ else
1259
+ @sbuf << @pattern_cc_2_2
1260
+ end
1261
+
1262
+ if @cnt == 0 then
1263
+ break
1264
+ end
1265
+ end
1266
+ else
1267
+
1268
+ if @cnt == 0 then
1269
+ @sbuf << @pattern_cc_1_1
1270
+ else
1271
+ @sbuf << @pattern_cc_1_2
1272
+ end
1273
+
1274
+ @cnt += 1
1275
+
1276
+ @position = @position2
1277
+ end
1278
+ else
1279
+
1280
+ @position = @res.end(0)
1281
+
1282
+ if @cnt == 0 then
1283
+ @sbuf << @pattern_cc_1_1
1284
+ else
1285
+ @sbuf << @pattern_cc_1_2
1286
+ end
1287
+
1288
+ @cnt += 1
1289
+ end
1290
+ else
1291
+
1292
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1293
+ @res = @pattern.match(@root.document,@position)
1294
+
1295
+ if @res then
1296
+ @cnt -= 1
1297
+
1298
+ if @cnt != 0 then
1299
+ @sbuf << @pattern_cc_2_1
1300
+ else
1301
+ @sbuf << @pattern_cc_2_2
1302
+ end
1303
+
1304
+ @position = @res.end(0)
1305
+ end
1306
+
1307
+ if !@res then
1308
+ break
1309
+ end
1310
+
1311
+ if @cnt == 0 then
1312
+ break
1313
+ end
1314
+ end
1315
+
1316
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1b)
1317
+ end
1318
+ else
1319
+
1320
+ @rx_document = @root.document
1321
+
1322
+ while (@res = @pattern.match(@rx_document)) || @cnt > 0
1323
+
1324
+ if @res then
1325
+
1326
+ if @cnt > 0 then
1327
+
1328
+ @rx_document2 = @res.post_match
1329
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1330
+
1331
+ @res = @pattern.match(@rx_document)
1332
+
1333
+ if @res then
1334
+
1335
+ @rx_document = @res.post_match
1336
+
1337
+ if @rx_document2.length > @rx_document.length then
1338
+
1339
+ if @cnt == 0 then
1340
+ @sbuf << @pattern_cc_1_1
1341
+ else
1342
+ @sbuf << @pattern_cc_1_2
1343
+ end
1344
+
1345
+ @cnt += 1
1346
+
1347
+ @rx_document = @rx_document2
1348
+ else
1349
+
1350
+ @cnt -= 1
1351
+
1352
+ if @cnt != 0 then
1353
+ @sbuf << @pattern_cc_2_1
1354
+ else
1355
+ @sbuf << @pattern_cc_2_2
1356
+ end
1357
+
1358
+ if @cnt == 0 then
1359
+ break
1360
+ end
1361
+ end
1362
+ else
1363
+
1364
+ if @cnt == 0 then
1365
+ @sbuf << @pattern_cc_1_1
1366
+ else
1367
+ @sbuf << @pattern_cc_1_2
1368
+ end
1369
+
1370
+ @cnt += 1
1371
+
1372
+ @rx_document = @rx_document2
1373
+ end
1374
+ else
1375
+
1376
+ @rx_document = @res.post_match
1377
+
1378
+ if @cnt == 0 then
1379
+ @sbuf << @pattern_cc_1_1
1380
+ else
1381
+ @sbuf << @pattern_cc_1_2
1382
+ end
1383
+
1384
+ @cnt += 1
1385
+ end
1386
+ else
1387
+
1388
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1389
+ @res = @pattern.match(@rx_document)
1390
+
1391
+ if @res then
1392
+ @cnt -= 1
1393
+
1394
+ if @cnt != 0 then
1395
+ @sbuf << @pattern_cc_2_1
1396
+ else
1397
+ @sbuf << @pattern_cc_2_2
1398
+ end
1399
+
1400
+ @rx_document = @res.post_match
1401
+ end
1402
+
1403
+ if !@res then
1404
+ break
1405
+ end
1406
+
1407
+ if @cnt == 0 then
1408
+ break
1409
+ end
1410
+ end
1411
+
1412
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1b)
1413
+ end
1414
+ end
1415
+
1416
+ @pattern_cc = @sbuf
1417
+
1418
+ if @sbuf.length == 0 || @cnt != 0 then
1419
+ # raise NoSuchElementException.new(elmName,attrName,attrValue);
1420
+ return nil;
1421
+ end
1422
+
1423
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
1424
+ @res = @pattern.match(@root.document)
1425
+
1426
+ @res
1427
+ end
1428
+ private :elementWithContent_3_2
1429
+
1430
+ def elementWithoutContent_3(elmName)
1431
+ elementWithoutContent_3_1(elmName,TAG_SEARCH_NC_2_3_2)
1432
+ end
1433
+ private :elementWithoutContent_3
1434
+
1435
+ def elementWithoutContent_3_1(elmName,closer)
1436
+
1437
+ #要素
1438
+ @elm_ = Element.new(elmName)
1439
+ #属性
1440
+ @elm_.attributes = @res[1];
1441
+ #全体
1442
+ @elm_.document = @res[0]
1443
+ #空要素検索用パターン
1444
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_NC_2_1 << @_attrName << ATTR_EQ
1445
+ @pattern_cc << @_attrValue << closer
1446
+ @elm_.pattern = @pattern_cc
1447
+
1448
+ @elm_.parser = self
1449
+ end
1450
+ private :elementWithoutContent_3_1
1451
+
1452
+ #
1453
+ # 属性(属性名="属性値")で検索し、要素を取得する
1454
+ #
1455
+ # @param [String] attrName 属性名
1456
+ # @param [String] attrValue 属性値
1457
+ # @return [Meteor::Element] 要素
1458
+ #
1459
+ def element_2(attrName,attrValue)
1460
+
1461
+ @_attrName = escapeRegex(attrName)
1462
+ @_attrValue = escapeRegex(attrValue)
1463
+
1464
+ #@pattern_cc = '' << TAG_SEARCH_3_1 << @_attrName << ATTR_EQ << @_attrValue << TAG_SEARCH_2_4
1465
+ @pattern_cc = '' << TAG_SEARCH_3_1 << @_attrName << ATTR_EQ << @_attrValue << TAG_SEARCH_2_4_2_3
1466
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
1467
+
1468
+ @res = @pattern.match(@root.document)
1469
+
1470
+ if @res then
1471
+ @elm_ = element_3(@res[1], attrName, attrValue)
1472
+ else
1473
+ @elm_ = nil
1474
+ end
1475
+
1476
+ @elm_
1477
+ end
1478
+ private :element_2
1479
+
1480
+ #
1481
+ # 要素名と属性1・属性2で検索し、要素を取得する
1482
+ #
1483
+ # @param [String] elmName 要素の名前
1484
+ # @param [String] attrName1 属性名1
1485
+ # @param [String] attrValue1 属性値2
1486
+ # @param [String] attrName2 属性名2
1487
+ # @param [String] attrValue2 属性値2
1488
+ # @return [Meteor::Element] 要素
1489
+ #
1490
+ def element_5(elmName,attrName1,attrValue1,attrName2,attrValue2)
1491
+
1492
+ @_elmName = escapeRegex(elmName)
1493
+ @_attrName1 = escapeRegex(attrName1)
1494
+ @_attrName2 = escapeRegex(attrName2)
1495
+ @_attrValue1 = escapeRegex(attrValue1)
1496
+ @_attrValue2 = escapeRegex(attrValue2)
1497
+
1498
+ #空要素検索用パターン
1499
+ @pattern_cc_1 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1_2 << @_attrName1 << ATTR_EQ
1500
+ @pattern_cc_1 << @_attrValue1 << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ
1501
+ @pattern_cc_1 << @_attrValue2 << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ
1502
+ @pattern_cc_1 << @_attrValue2 << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ
1503
+ @pattern_cc_1 << @_attrValue1 << TAG_SEARCH_2_3_2_2
1504
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
1505
+ #空要素検索
1506
+ @res1 = @pattern.match(@root.document)
1507
+
1508
+ #内容あり要素検索パターン
1509
+ @pattern_cc_2 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1_2 << @_attrName1 << ATTR_EQ
1510
+ @pattern_cc_2 << @_attrValue1 << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ
1511
+ @pattern_cc_2 << @_attrValue2 << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ
1512
+ @pattern_cc_2 << @_attrValue2 << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ
1513
+ @pattern_cc_2 << @_attrValue1 << TAG_SEARCH_2_2_2 << @_elmName
1514
+ @pattern_cc_2 << TAG_SEARCH_1_2 << @_elmName << TAG_CLOSE
1515
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1516
+ #内容あり要素検索
1517
+ @res2 = @pattern.match(@root.document)
1518
+
1519
+ if !@res2 then
1520
+ @res2 = elementWithContent_5_2(elmName)
1521
+ @pattern_cc_2 = @pattern_cc
1522
+ end
1523
+
1524
+ if @res1 && @res2 then
1525
+ if @res1.begin(0) < @res2.begin(0) then
1526
+ @res = @res1
1527
+ @pattern_cc = @pattern_cc_1
1528
+ elementWithoutContent_5(elmName)
1529
+ elsif @res1.begin(0) > @res2.begin(0)
1530
+ @res = @res2
1531
+ @pattern_cc = @pattern_cc_2
1532
+ elementWithContent_5_1(elmName)
1533
+ end
1534
+ elsif @res1 && !@res2 then
1535
+ @res = @res1
1536
+ @pattern_cc = @pattern_cc_1
1537
+ elementWithoutContent_5(elmName)
1538
+ elsif !@res1 && @res2 then
1539
+ @res = @res2
1540
+ @pattern_cc = @pattern_cc_2
1541
+ elementWithContent_5_1(elmName)
1542
+ elsif !@res1 && !@res2 then
1543
+ @elm_ = nil
1544
+ #raise NoSuchElementException.new(elmName,attrName1,attrValue1,attrName2,attrValue2);
1545
+ end
1546
+
1547
+ if @elm_ then
1548
+ @elm_.arguments.store(attrName1, attrValue1)
1549
+ @elm_.arguments.store(attrName2, attrValue2)
1550
+ @elm_.arguments.recordable = true
1551
+ end
1552
+
1553
+ @elm_
1554
+ end
1555
+ private :element_5
1556
+
1557
+ def elementWithContent_5_1(elmName)
1558
+
1559
+ if @res.captures.length == 4 then
1560
+ #要素
1561
+ @elm_ = Element.new(elmName)
1562
+ #属性
1563
+ @elm_.attributes = @res[1]
1564
+ #内容
1565
+ @elm_.mixed_content = @res[2]
1566
+ #全体
1567
+ @elm_.document = @res[0]
1568
+ #内容あり要素検索用パターン
1569
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_NC_2_1_2 << @_attrName1 << ATTR_EQ
1570
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_NC_2_6 << @_attrName2 << ATTR_EQ
1571
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_NC_2_7 << @_attrName2 << ATTR_EQ
1572
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_NC_2_6 << @_attrName1 << ATTR_EQ
1573
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_NC_2_2_2 << @_elmName
1574
+ @pattern_cc << TAG_SEARCH_NC_1_2 << @_elmName << TAG_CLOSE
1575
+ @elm_.pattern = @pattern_cc
1576
+ #
1577
+ @elm_.empty = true
1578
+
1579
+ @elm_.parser = self
1580
+
1581
+ elsif @res.captures.length == 6 then
1582
+
1583
+ @elm_ = Element.new(elmName)
1584
+ #属性
1585
+ @elm_.attributes = @res[1].chop
1586
+ #要素
1587
+ @elm_.mixed_content = @res[3]
1588
+ #全体
1589
+ @elm_.document = @res[0]
1590
+ #要素ありタグ検索用パターン
1591
+ @elm_.pattern = @pattern_cc
1592
+
1593
+ @elm_.empty = true
1594
+
1595
+ @elm_.parser = self
1596
+ end
1597
+ end
1598
+ private :elementWithContent_5_1
1599
+
1600
+ def elementWithContent_5_2(elmName)
1601
+ @cnt = 0
1602
+
1603
+ @pattern_cc_1 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1_2 << @_attrName1 << ATTR_EQ
1604
+ @pattern_cc_1 << @_attrValue1 << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ
1605
+ @pattern_cc_1 << @_attrValue2 << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ
1606
+ @pattern_cc_1 << @_attrValue2 << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ
1607
+ @pattern_cc_1 << @_attrValue1 << TAG_SEARCH_2_4_2_2
1608
+
1609
+ @pattern_cc_1b = '' << TAG_OPEN << elmName << TAG_SEARCH_1_4
1610
+
1611
+ @pattern_cc_1_1 = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1_2 << @_attrName1 << ATTR_EQ
1612
+ @pattern_cc_1_1 << @_attrValue1 << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ
1613
+ @pattern_cc_1_1 << @_attrValue2 << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ
1614
+ @pattern_cc_1_1 << @_attrValue2 << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ
1615
+ @pattern_cc_1_1 << @_attrValue1 << TAG_SEARCH_4_7_2
1616
+
1617
+ @pattern_cc_1_2 = '' << TAG_SEARCH_4_2 << @_elmName << TAG_SEARCH_4_3
1618
+
1619
+ @pattern_cc_2 = '' << TAG_SEARCH_4_4 << @_elmName << TAG_CLOSE
1620
+
1621
+ @pattern_cc_2_1 = '' << TAG_SEARCH_4_5 << @_elmName << TAG_CLOSE
1622
+
1623
+ @pattern_cc_2_2 = '' << TAG_SEARCH_4_6 << @_elmName << TAG_CLOSE
1624
+
1625
+ #内容あり要素検索
1626
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1)
1627
+
1628
+ @sbuf = ''
1629
+
1630
+ if RUBY_VERSION >= '1.9.0' then
1631
+
1632
+ @position = 0
1633
+
1634
+ while (@res = @pattern.match(@root.document,@position)) || @cnt > 0
1635
+
1636
+ if @res then
1637
+
1638
+ if @cnt > 0 then
1639
+
1640
+ @position2 = @res.end(0)
1641
+
1642
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1643
+ @res = @pattern.match(@root.document,@position)
1644
+
1645
+ if @res then
1646
+
1647
+ @position = @res.end(0)
1648
+
1649
+ if @position > @position2 then
1650
+
1651
+ if @cnt == 0 then
1652
+ @sbuf << @pattern_cc_1_1
1653
+ else
1654
+ @sbuf << @pattern_cc_1_2
1655
+ end
1656
+
1657
+ @cnt << 1
1658
+
1659
+ @position = @position2
1660
+ else
1661
+
1662
+ @cnt -= 1
1663
+
1664
+ if @cnt != 0 then
1665
+ @sbuf << @pattern_cc_2_1
1666
+ else
1667
+ @sbuf << @pattern_cc_2_2
1668
+ end
1669
+
1670
+ if @cnt == 0 then
1671
+ break
1672
+ end
1673
+ end
1674
+ else
1675
+
1676
+ if @cnt == 0 then
1677
+ @sbuf << @pattern_cc_1_1
1678
+ else
1679
+ @sbuf << @pattern_cc_1_2
1680
+ end
1681
+
1682
+ @cnt += 1
1683
+
1684
+ @position = @position2
1685
+ end
1686
+ else
1687
+ @position = @res.end(0)
1688
+
1689
+ if @cnt == 0 then
1690
+ @sbuf << @pattern_cc_1_1
1691
+ else
1692
+ @sbuf << @pattern_cc_1_2
1693
+ end
1694
+
1695
+ @cnt += 1
1696
+ end
1697
+ else
1698
+
1699
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1700
+ @res = @pattern.match(@root.document,@position)
1701
+
1702
+ if @res then
1703
+
1704
+ @cnt -= 1
1705
+
1706
+ if @cnt != 0 then
1707
+ @sbuf << @pattern_cc_2_1
1708
+ else
1709
+ @sbuf << @pattern_cc_2_2
1710
+ end
1711
+
1712
+ @position = @res.end(0)
1713
+ end
1714
+
1715
+ if @cnt == 0 then
1716
+ break
1717
+ end
1718
+
1719
+ if !@res then
1720
+ break
1721
+ end
1722
+ end
1723
+
1724
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1b)
1725
+ end
1726
+ else
1727
+
1728
+ @rx_document = @root.document
1729
+
1730
+ while (@res = @pattern.match(@rx_document)) || @cnt > 0
1731
+
1732
+ if @res then
1733
+
1734
+ if @cnt > 0 then
1735
+
1736
+ @rx_document2 = @res.post_match
1737
+
1738
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1739
+ @res = @pattern.match(@rx_document)
1740
+
1741
+ if @res then
1742
+
1743
+ @rx_document = @res.post_match
1744
+
1745
+ if @rx_document2.length > @rx_document.length then
1746
+
1747
+ if @cnt == 0 then
1748
+ @sbuf << @pattern_cc_1_1
1749
+ else
1750
+ @sbuf << @pattern_cc_1_2
1751
+ end
1752
+
1753
+ @cnt += 1
1754
+
1755
+ @rx_document = @rx_document2
1756
+ else
1757
+
1758
+ @cnt -= 1
1759
+
1760
+ if @cnt != 0 then
1761
+ @sbuf << @pattern_cc_2_1
1762
+ else
1763
+ @sbuf << @pattern_cc_2_2
1764
+ end
1765
+
1766
+ if @cnt == 0 then
1767
+ break
1768
+ end
1769
+ end
1770
+ else
1771
+
1772
+ if @cnt == 0 then
1773
+ @sbuf << @pattern_cc_1_1
1774
+ else
1775
+ @sbuf << @pattern_cc_1_2
1776
+ end
1777
+
1778
+ @cnt += 1
1779
+
1780
+ @rx_document = @rx_document2
1781
+ end
1782
+ else
1783
+ @rx_document = @res.post_match
1784
+
1785
+ if @cnt == 0 then
1786
+ @sbuf << @pattern_cc_1_1
1787
+ else
1788
+ @sbuf << @pattern_cc_1_2
1789
+ end
1790
+
1791
+ @cnt += 1
1792
+ end
1793
+ else
1794
+
1795
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_2)
1796
+ @res = @pattern.match(@rx_document)
1797
+
1798
+ if @res then
1799
+
1800
+ @cnt -= 1
1801
+
1802
+ if @cnt != 0 then
1803
+ @sbuf << @pattern_cc_2_1
1804
+ else
1805
+ @sbuf << @pattern_cc_2_2
1806
+ end
1807
+
1808
+ @rx_document = @res.post_match
1809
+ end
1810
+
1811
+ if @cnt == 0 then
1812
+ break
1813
+ end
1814
+
1815
+ if !@res then
1816
+ break
1817
+ end
1818
+ end
1819
+
1820
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc_1b)
1821
+ end
1822
+ end
1823
+
1824
+ @pattern_cc = @sbuf
1825
+
1826
+ if @sbuf.length == 0 || @cnt != 0 then
1827
+ # raise NoSuchElementException.new(elmName,attrName1,attrValue1,attrName2,attrValue2);
1828
+ return nil
1829
+ end
1830
+
1831
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
1832
+ @res = @pattern.match(@root.document)
1833
+
1834
+ @res
1835
+ end
1836
+ private :elementWithContent_5_2
1837
+
1838
+ def elementWithoutContent_5(elmName)
1839
+ elementWithoutContent_5_1(elmName,TAG_SEARCH_NC_2_3_2_2);
1840
+ end
1841
+ private :elementWithoutContent_5
1842
+
1843
+ def elementWithoutContent_5_1(elmName,closer)
1844
+
1845
+ #要素
1846
+ @elm_ = Element.new(elmName)
1847
+ #属性
1848
+ @elm_.attributes = @res[1]
1849
+ #全体
1850
+ @elm_.document = @res[0]
1851
+ #空要素検索用パターン
1852
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_NC_2_1_2 << @_attrName1 << ATTR_EQ
1853
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_NC_2_6 << @_attrName2 << ATTR_EQ
1854
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_NC_2_7 << @_attrName2 << ATTR_EQ
1855
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_NC_2_6 << @_attrName1 << ATTR_EQ
1856
+ @pattern_cc << @_attrValue1 << closer
1857
+ @elm_.pattern = @pattern_cc
1858
+
1859
+ @elm_.parser = self
1860
+ end
1861
+ private :elementWithoutContent_5_1
1862
+
1863
+ #
1864
+ # 属性1・属性2(属性名="属性値")で検索し、要素を取得する
1865
+ #
1866
+ # @param [String] attrName1 属性名1
1867
+ # @param [String] attrValue1 属性値1
1868
+ # @param [String] attrName2 属性名2
1869
+ # @param [String]attrValue2 属性値2
1870
+ # @return [Meteor::Element] 要素
1871
+ #
1872
+ def element_4(attrName1,attrValue1,attrName2,attrValue2)
1873
+
1874
+ @_attrName1 = escapeRegex(attrName1)
1875
+ @_attrName2 = escapeRegex(attrName2)
1876
+ @_attrValue1 = escapeRegex(attrValue1)
1877
+ @_attrValue2 = escapeRegex(attrValue2)
1878
+
1879
+ @pattern_cc = '' << TAG_SEARCH_3_1_2_2 << @_attrName1 << ATTR_EQ
1880
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ
1881
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ
1882
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ
1883
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_2_4_2_3
1884
+
1885
+ @pattern = PatternCache.get(@pattern_cc)
1886
+
1887
+ @res = @pattern.match(@root.document)
1888
+
1889
+ if @res then
1890
+ @elm_ = element_5(@res[1], attrName1, attrValue1,attrName2, attrValue2);
1891
+ else
1892
+ @elm_ = nil
1893
+ end
1894
+
1895
+ @elm_
1896
+ end
1897
+ private :element_4
1898
+
1899
+ #
1900
+ # 要素の属性をセットする or 属性の値を取得する
1901
+ #
1902
+ # @param [Array] args 引数配列
1903
+ # @return [String] 属性値
1904
+ #
1905
+ def attribute(*args)
1906
+ case args.length
1907
+ when 1
1908
+ getAttributeValue_1(args[0])
1909
+ when 2
1910
+ if args[0].kind_of?(Meteor::Element) && args[1].kind_of?(String) then
1911
+ getAttributeValue_2(args[0],args[1])
1912
+ elsif args[0].kind_of?(String) && args[1].kind_of?(String) then
1913
+ setAttribute_2(args[0],args[1])
1914
+ elsif args[0].kind_of?(Meteor::Element) && args[1].kind_of?(Meteor::AttributeMap) then
1915
+ setAttribute_2_m(args[0],args[1])
1916
+ else
1917
+ raise ArgumentError
1918
+ end
1919
+ when 3
1920
+ setAttribute_3(args[0],args[1],args[2])
1921
+ else
1922
+ raise ArgumentError
1923
+ end
1924
+ end
1925
+
1926
+ #
1927
+ # 要素の属性を編集する
1928
+ #
1929
+ # @param [Meteor::Element] elm 要素
1930
+ # @param [String] attrName 属性名
1931
+ # @param [String] attrValue 属性値
1932
+ #
1933
+ def setAttribute_3(elm,attrName,attrValue)
1934
+ if !elm.cx then
1935
+ #属性群の更新
1936
+ editAttributes_(elm,attrName,attrValue)
1937
+
1938
+ if elm.arguments.map.include?(attrName) then
1939
+ elm.arguments.store(attrName, attrValue)
1940
+ end
1941
+
1942
+ @e_cache.store(elm.object_id, elm)
1943
+ end
1944
+ end
1945
+ private :setAttribute_3
1946
+
1947
+ def editAttributes_(elm,attrName,attrValue)
1948
+
1949
+ attrValue = escape(attrValue)
1950
+
1951
+ @pattern = Meteor::Core::Util::PatternCache.get('' << attrName << SET_ATTR_1)
1952
+
1953
+ #属性検索
1954
+ @res = @pattern.match(elm.attributes)
1955
+
1956
+ #検索対象属性の存在判定
1957
+ if @res then
1958
+
1959
+ @_attrValue = attrValue
1960
+ #replace2Regex(@_attrValue)
1961
+ if elm.parser.rootElement.hook || elm.parser.rootElement.monoHook then
1962
+ replace4Regex(@_attrValue)
1963
+ else
1964
+ replace2Regex(@_attrValue)
1965
+ end
1966
+ #属性の置換
1967
+ elm.attributes.sub!(@pattern,'' << attrName << ATTR_EQ << @_attrValue << DOUBLE_QUATATION)
1968
+ else
1969
+ #属性文字列の最後に新規の属性を追加する
1970
+ if EMPTY != elm.attributes && EMPTY != elm.attributes.strip then
1971
+ elm.attributes = '' << SPACE << elm.attributes.strip
1972
+ else
1973
+ elm.attributes = ''
1974
+ end
1975
+
1976
+ elm.attributes << SPACE << attrName << ATTR_EQ << attrValue << DOUBLE_QUATATION
1977
+ end
1978
+
1979
+ end
1980
+ private :editAttributes_
1981
+
1982
+ def editDocument_1(elm)
1983
+ editDocument_2(elm,TAG_CLOSE3)
1984
+ end
1985
+ private :editDocument_1
1986
+
1987
+ def editDocument_2(elm,closer)
1988
+ if !elm.parent then
1989
+
1990
+ if !elm.cx then
1991
+ @_attributes = elm.attributes
1992
+ replace2Regex(@_attributes)
1993
+
1994
+ if elm.empty then
1995
+ #内容あり要素の場合
1996
+ @_content = elm.mixed_content
1997
+ #replace2Regex(@_content)
1998
+ if elm.parser.rootElement.hook || elm.parser.rootElement.monoHook then
1999
+ replace4Regex(@_content)
2000
+ else
2001
+ replace2Regex(@_content)
2002
+ end
2003
+
2004
+ #タグ検索用パターン
2005
+ @pattern = Meteor::Core::Util::PatternCache.get(elm.pattern)
2006
+ @root.document.sub!(@pattern,'' << TAG_OPEN << elm.name << @_attributes << TAG_CLOSE << @_content << TAG_OPEN3 << elm.name << TAG_CLOSE)
2007
+ #@root.document.sub!(@pattern,"<#{elm.name}#{@_attributes}>#{@_content}</#{elm.name}>")
2008
+ else
2009
+ #空要素の場合
2010
+ #タグ置換用パターン
2011
+ @pattern = Meteor::Core::Util::PatternCache.get(elm.pattern)
2012
+ @root.document.sub!(@pattern,'' << TAG_OPEN << elm.name << @_attributes << closer)
2013
+ end
2014
+ else
2015
+ @_content = elm.mixed_content
2016
+ if elm.parser.rootElement.hook || elm.parser.rootElement.monoHook then
2017
+ replace4Regex(@_content)
2018
+ else
2019
+ replace2Regex(@_content)
2020
+ end
2021
+
2022
+ @pattern = Meteor::Core::Util::PatternCache.get(elm.pattern)
2023
+
2024
+ #タグ置換
2025
+ @pattern_cc = '' << SET_CX_1 << elm.name << SPACE << elm.attributes << SET_CX_2
2026
+ @pattern_cc << @_content << SET_CX_3 << elm.name << SET_CX_4
2027
+ #@pattern_cc = "<!-- @#{elm.name} #{elm.attributes}-->#{@_content}<!-- /@#{elm.name} -->"
2028
+ @root.document.sub!(@pattern,@pattern_cc)
2029
+ end
2030
+ end
2031
+ end
2032
+ private :editDocument_2
2033
+
2034
+ def editPattern_(elm)
2035
+ if !elm.parent then
2036
+
2037
+ elm.arguments.map.each{ |name,attr|
2038
+
2039
+ if attr.changed then
2040
+ @_attrValue = attr.value
2041
+ replace2Regex(@_attrValue)
2042
+
2043
+ @pattern_cc = '' << name << SET_ATTR_1
2044
+ #@pattern_cc = "#{attrName}=\"[^\"]*\""
2045
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
2046
+ elm.pattern.gsub!(@pattern,'' << name << ATTR_EQ << @_attrValue << DOUBLE_QUATATION)
2047
+ #elm.pattern.sub!(@pattern,"#{attrName}=\"#{@_attrValue}\"")
2048
+ elsif attr.removed then
2049
+ @pattern_cc = '' << name << SET_ATTR_1
2050
+ #@pattern_cc = "#{attrName}=\"[^\"]*\""
2051
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
2052
+ elm.pattern.gsub!(@pattern,EMPTY)
2053
+ end
2054
+ }
2055
+ end
2056
+ end
2057
+ private :editPattern_
2058
+
2059
+ #
2060
+ # 要素の属性を編集する
2061
+ #
2062
+ # @param [String] attrName 属性名
2063
+ # @param [String] attrValue 属性値
2064
+ #
2065
+ def setAttribute_2(attrName,attrValue)
2066
+ if @root.hook || @root.monoHook then
2067
+ setAttribute_3(@root.mutableElement, attrName, attrValue)
2068
+ end
2069
+ end
2070
+ private :setAttribute_2
2071
+
2072
+ #
2073
+ # 要素の属性値を取得する
2074
+ #
2075
+ # @param [Meteor::Element] elm 要素
2076
+ # @param [String] attrName 属性名
2077
+ # @return [String] 属性値
2078
+ #
2079
+ def getAttributeValue_2(elm,attrName)
2080
+ getAttributeValue_(elm,attrName)
2081
+ end
2082
+ private :getAttributeValue_2
2083
+
2084
+ def getAttributeValue_(elm,attrName)
2085
+
2086
+ #属性検索用パターン
2087
+ @pattern = Meteor::Core::Util::PatternCache.get('' << attrName << GET_ATTR_1)
2088
+
2089
+ @res = @pattern.match(elm.attributes)
2090
+
2091
+ if @res then
2092
+ unescape(@res[1])
2093
+ else
2094
+ nil
2095
+ end
2096
+ end
2097
+ private :getAttributeValue_
2098
+
2099
+ #
2100
+ # 要素の属性値を取得する
2101
+ #
2102
+ # @param [String] attrName 属性名
2103
+ # @return [String] 属性値
2104
+ #
2105
+ def getAttributeValue_1(attrName)
2106
+ if @root.hook || @root.monoHook then
2107
+ getAttributeValue_2(@root.mutableElement, attrName)
2108
+ else
2109
+ nil
2110
+ end
2111
+ end
2112
+ private :getAttributeValue_1
2113
+
2114
+ #
2115
+ # 属性マップを取得する
2116
+ #
2117
+ # @param [Array] args 引数配列
2118
+ # @return [Meteor::AttributeMap] 属性マップ
2119
+ #
2120
+ def attributeMap(*args)
2121
+ case args.length
2122
+ when 0
2123
+ getAttributeMap_0
2124
+ when 1
2125
+ getAttributeMap_1(args[0])
2126
+ else
2127
+ raise ArgumentError
2128
+ end
2129
+ end
2130
+
2131
+ #
2132
+ # 属性マップを取得する
2133
+ #
2134
+ # @param [Meteor::Element] elm 要素
2135
+ # @return [Meteor::AttributeMap] 属性マップ
2136
+ #
2137
+ def getAttributeMap_1(elm)
2138
+ attrs = Meteor::AttributeMap.new
2139
+
2140
+ elm.attributes.scan(@@pattern_get_attrs_map){ |a,b|
2141
+ attrs.store(a,unescape(b))
2142
+ }
2143
+ attrs.recordable = true
2144
+
2145
+ attrs
2146
+ end
2147
+ private :getAttributeMap_1
2148
+
2149
+ #
2150
+ # 要素の属性マップを取得する
2151
+ #
2152
+ # @return [Meteor::AttributeMap] 属性マップ
2153
+ #
2154
+ def getAttributeMap_0()
2155
+ if @root.hook || @root.monoHook then
2156
+ getAttributeMap_1(@root.mutableElement)
2157
+ else
2158
+ nil
2159
+ end
2160
+ end
2161
+ private :getAttributeMap_0
2162
+
2163
+ #
2164
+ # 要素の属性を編集する
2165
+ #
2166
+ # @param [Meteor::Element] elm 要素
2167
+ # @param [Meteor::AttributeMap] attrMap 属性マップ
2168
+ #
2169
+ def setAttribute_2_m(elm,attrMap)
2170
+ if !elm.cx then
2171
+ attrMap.map.each{|name,attr|
2172
+ if attrMap.changed(name) then
2173
+ editAttributes_(elm,name,attr.value)
2174
+ elsif attrMap.removed(name) then
2175
+ removeAttributes_(elm,name)
2176
+ end
2177
+ }
2178
+
2179
+ @e_cache.store(elm.object_id,elm)
2180
+ end
2181
+ end
2182
+ private :setAttribute_2_m
2183
+
2184
+ #
2185
+ # 要素の内容をセットする or 内容を取得する
2186
+ #
2187
+ # @param [Array] args 引数配列
2188
+ # @return [String] 内容
2189
+ #
2190
+ def content(*args)
2191
+ case args.length
2192
+ when 1
2193
+ if args[0].kind_of?(Meteor::Element) then
2194
+ getContent_1(args[0])
2195
+ elsif args[0].kind_of?(String) then
2196
+ setContent_1(args[0])
2197
+ end
2198
+ when 2
2199
+ if args[0].kind_of?(Meteor::Element) && args[1].kind_of?(String) then
2200
+ setContent_2_s(args[0],args[1])
2201
+ elsif args[0].kind_of?(String) && (args[1].kind_of?(TrueClass) || args[1].kind_of?(FalseClsss)) then
2202
+ setContent_2_b(args[0],args[1])
2203
+ else
2204
+ raise ArgumentError
2205
+ end
2206
+ when 3
2207
+ setContent_3(args[0],args[1],args[2])
2208
+ else
2209
+ raise ArgumentError
2210
+ end
2211
+ end
2212
+
2213
+ #
2214
+ # 要素の内容をセットする
2215
+ #
2216
+ # @param [Meteor::Element] elm 要素
2217
+ # @param [String] mixed_content 要素の内容
2218
+ # @param [TrueClass][FalseClass] entityRef エンティティ参照フラグ
2219
+ #
2220
+ def setContent_3(elm,content,entityRef=true)
2221
+
2222
+ if entityRef then
2223
+ content = escapeContent(content,elm.name)
2224
+ end
2225
+
2226
+ elm.mixed_content = content
2227
+
2228
+ @e_cache.store(elm.object_id,elm)
2229
+
2230
+ end
2231
+ private :setContent_3
2232
+
2233
+ #
2234
+ # 要素の内容を編集する
2235
+ #
2236
+ # @param [Meteor::Element] 要素
2237
+ # @param [String] mixed_content 要素の内容
2238
+ #
2239
+ def setContent_2_s(elm,content)
2240
+ setContent_3(elm, content)
2241
+ end
2242
+ private :setContent_2_s
2243
+
2244
+ #
2245
+ # 要素の内容を編集する
2246
+ #
2247
+ # @param [String] mixed_content 内容
2248
+ #
2249
+ def setContent_1(content)
2250
+ if @root.monoHook then
2251
+ setContent_2_s(@root.mutableElement, content)
2252
+ end
2253
+ end
2254
+ private :setContent_1
2255
+
2256
+ #
2257
+ # 要素の内容を編集する
2258
+ #
2259
+ # @param [String] mixed_content 内容
2260
+ # @param [TrueClass][FalseClass] entityRef エンティティ参照フラグ
2261
+ #
2262
+ def setContent_2_b(content,entityRef)
2263
+ if @root.monoHook then
2264
+ setContent_3(@root.mutableElement, content, entityRef)
2265
+ end
2266
+ end
2267
+ private :setContent_2_b
2268
+
2269
+ def getContent_1(elm)
2270
+ if !elm.cx then
2271
+ if elm.empty then
2272
+ unescapeContent(elm.mixed_content,elm.name)
2273
+ end
2274
+ else
2275
+ nil
2276
+ end
2277
+ end
2278
+ private :getContent_1
2279
+
2280
+ #
2281
+ # 要素の属性を消す
2282
+ #
2283
+ # @param [Array] args 引数配列
2284
+ #
2285
+ def removeAttribute(*args)
2286
+ case args.length
2287
+ when 1
2288
+ removeAttribute_1(args[0])
2289
+ when 2
2290
+ removeAttribute_2(args[0],args[1])
2291
+ else
2292
+ raise ArgumentError
2293
+ end
2294
+ end
2295
+
2296
+ #
2297
+ # 要素の属性を消す
2298
+ #
2299
+ # @param [Meteor::Element] elm 要素
2300
+ # @param [String] attrName 属性名
2301
+ #
2302
+ def removeAttribute_2(elm,attrName)
2303
+ if !elm.cx then
2304
+
2305
+ removeAttributes_(elm,attrName)
2306
+
2307
+ if elm.arguments.map.include?(attrName) then
2308
+ elm.arguments.delete(attrName)
2309
+ end
2310
+
2311
+ @e_cache.store(elm.object_id,elm)
2312
+ end
2313
+ end
2314
+ private :removeAttribute_2
2315
+
2316
+ def removeAttributes_(elm,attrName)
2317
+ #属性検索用パターン
2318
+ @pattern = Meteor::Core::Util::PatternCache.get('' << attrName << ERASE_ATTR_1)
2319
+ #属性の置換
2320
+ elm.attributes.sub!(@pattern,EMPTY)
2321
+ end
2322
+ private :removeAttributes_
2323
+
2324
+ #
2325
+ # 要素の属性を消す
2326
+ #
2327
+ # @param [String] attrName 属性名
2328
+ #
2329
+ def removeAttribute_1(attrName)
2330
+ if @root.hook || @root.monoHook then
2331
+ removeAttribute_2(@root.mutableElement, attrName)
2332
+ end
2333
+ end
2334
+ private :removeAttribute_1
2335
+
2336
+ #
2337
+ # 要素を消す
2338
+ #
2339
+ # @param [Meteor::Element] elm 要素
2340
+ #
2341
+ def removeElement(elm)
2342
+ replace(elm,EMPTY)
2343
+ @e_cache.delete(elm.object_id)
2344
+ end
2345
+
2346
+ #
2347
+ # CX(コメント拡張)タグを取得する
2348
+ #
2349
+ # @param [Array] args 引数配列
2350
+ # @return [Meteor::Element] 要素
2351
+ #
2352
+ def cxtag(*args)
2353
+ case args.length
2354
+ when 1
2355
+ cxtag_1(args[0])
2356
+ when 2
2357
+ cxtag_2(args[0],args[1])
2358
+ else
2359
+ raise ArgumentError
2360
+ end
2361
+ end
2362
+
2363
+ #
2364
+ # 要素名とID属性で検索し、CX(コメント拡張)タグを取得する
2365
+ #
2366
+ # @param [String] elmName 要素名
2367
+ # @param [String] id ID属性値
2368
+ # @return [Meteor::Element] 要素
2369
+ #
2370
+ def cxtag_2(elmName,id)
2371
+
2372
+ #CXタグ検索用パターン
2373
+ @pattern_cc = '' << SEARCH_CX_1 << elmName << SEARCH_CX_2
2374
+ @pattern_cc << id << SEARCH_CX_3 << elmName << SEARCH_CX_4 << elmName << SEARCH_CX_5
2375
+
2376
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
2377
+ #CXタグ検索
2378
+ @res = @pattern.match(@root.document)
2379
+
2380
+ if @res then
2381
+ #要素
2382
+ @elm_ = Element.new(elmName)
2383
+
2384
+ @elm_.cx = true
2385
+ #属性
2386
+ @elm_.attributes = @res[1]
2387
+ #内容
2388
+ @elm_.mixed_content = @res[2]
2389
+ #全体
2390
+ @elm_.document = @res[0]
2391
+ #要素検索パターン
2392
+ @elm_.pattern = @pattern_cc
2393
+
2394
+ @elm_.empty = true
2395
+
2396
+ @elm_.parser = self
2397
+ else
2398
+ @elm_ = nil
2399
+ end
2400
+
2401
+ @elm_
2402
+ end
2403
+ private :cxtag_2
2404
+
2405
+ #
2406
+ # ID属性で検索し、CX(コメント拡張)タグを取得する
2407
+ #
2408
+ # @param [String] id ID属性値
2409
+ # @return [Meteor::Element] 要素
2410
+ #
2411
+ def cxtag_1(id)
2412
+
2413
+ @pattern_cc = '' << SEARCH_CX_6 << id << DOUBLE_QUATATION
2414
+
2415
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
2416
+
2417
+ @res = @pattern.match(@root.document)
2418
+
2419
+ if @res then
2420
+ @elm_ = cxtag(@res[1],id)
2421
+ else
2422
+ @elm_ = nil
2423
+ end
2424
+
2425
+ @elm_
2426
+ end
2427
+ private :cxtag_1
2428
+
2429
+ #
2430
+ # 要素を置換する
2431
+ #
2432
+ # @param [Meteor::Element] elm 要素
2433
+ # @param [String] replaceDocument 置換文字列
2434
+ #
2435
+ def replace(elm,replaceDocument)
2436
+ #文字エスケープ
2437
+ if replaceDocument.size > 0 && elm.parent && elm.mono then
2438
+ replace2Regex(replaceDocument)
2439
+ end
2440
+ #タグ置換パターン
2441
+ @pattern = Meteor::Core::Util::PatternCache.get(elm.pattern)
2442
+ #タグ置換
2443
+ @root.document.sub!(@pattern,replaceDocument)
2444
+ end
2445
+
2446
+ def reflect()
2447
+
2448
+ @e_cache.values.each { |item|
2449
+ editDocument_1(item)
2450
+ editPattern_(item)
2451
+ }
2452
+ @e_cache.clear
2453
+ end
2454
+ protected :reflect
2455
+
2456
+ #
2457
+ # 出力する
2458
+ #
2459
+ def print
2460
+ reflect()
2461
+
2462
+ if @root.hook then
2463
+ @_attributes = @root.mutableElement.attributes
2464
+ replace2Regex(@_attributes)
2465
+ if @root.element.cx then
2466
+ #@root.hookDocument << SET_CX_1 << @root.mutableElement.name << SPACE
2467
+ #@root.hookDocument << @_attributes << SET_CX_2
2468
+ #@root.hookDocument << @root.document << SET_CX_3
2469
+ #@root.hookDocument << @root.mutableElement.name << SET_CX_4
2470
+ @root.hookDocument << "<!-- @#{@root.mutableElement.name} #{@_attributes}-->#{@root.document}<!-- /@#{@root.mutableElement.name} -->"
2471
+ else
2472
+ #@root.hookDocument << TAG_OPEN << @root.mutableElement.name
2473
+ #@root.hookDocument << @_attributes << TAG_CLOSE << @root.document
2474
+ #@root.hookDocument << TAG_OPEN3 << @root.mutableElement.name << TAG_CLOSE
2475
+ @root.hookDocument << "<#{@root.mutableElement.name}#{@_attributes}>#{@root.document}</#{@root.mutableElement.name}>"
2476
+ end
2477
+ @root.mutableElement = Element.new(@root.element)
2478
+ @root.document = String.new(@root.element.mixed_content)
2479
+ else
2480
+ if @root.monoHook then
2481
+ if @root.element.cx then
2482
+ #@root.hookDocument << SET_CX_1 << @root.mutableElement.name << SPACE
2483
+ #@root.hookDocument << @root.mutableElement.attributes << SET_CX_2
2484
+ #@root.hookDocument << @root.mutableElement.mixed_content << SET_CX_3
2485
+ #@root.hookDocument << @root.mutableElement.name << SET_CX_4
2486
+ @root.hookDocument << "<!-- @#{@root.mutableElement.name} #{@root.mutableElement.attributes}-->#{@root.mutableElement.mixed_content}<!-- /@#{@root.mutableElement.name} -->"
2487
+ else
2488
+ #@root.hookDocument << TAG_OPEN << @root.mutableElement.name
2489
+ #@root.hookDocument << @root.mutableElement.attributes << TAG_CLOSE << @root.mutableElement.mixed_content
2490
+ #@root.hookDocument << TAG_OPEN3 << @root.mutableElement.name << TAG_CLOSE
2491
+ @root.hookDocument << "<#{@root.mutableElement.name}#{@root.mutableElement.attributes}>#{@root.mutableElement.mixed_content}</#{@root.mutableElement.name}>"
2492
+ end
2493
+ @root.mutableElement = Element.new(@root.element)
2494
+ else
2495
+ #フック判定がFALSEの場合
2496
+ clean
2497
+ end
2498
+ end
2499
+ end
2500
+
2501
+ def clean
2502
+ #CX開始タグ置換
2503
+ @pattern = @@pattern_clean1
2504
+ @root.document.gsub!(@pattern,EMPTY)
2505
+ #CX終了タグ置換
2506
+ @pattern = @@pattern_clean2
2507
+ @root.document.gsub!(@pattern,EMPTY)
2508
+ #@root.document = @root.document << "<!-- Powered by Meteor (C)Yasumasa Ashida -->"
2509
+ end
2510
+ private :clean
2511
+
2512
+ #
2513
+ # 子パーサを取得する
2514
+ #
2515
+ # @param [Meteor::Element] elm 要素
2516
+ # @return [Meteor::Parser] 子パーサ
2517
+ #
2518
+ def child(elm)
2519
+ if elm.empty then
2520
+ #内容あり要素の場合
2521
+ setMonoInfo(elm)
2522
+
2523
+ pif2 = create(self)
2524
+
2525
+ elm.parent=true
2526
+ pif2.parent = self
2527
+ pif2.rootElement.element = elm
2528
+ pif2.rootElement.mutableElement = Element.new(elm)
2529
+ pif2.rootElement.kaigyoCode = @root.kaigyoCode
2530
+
2531
+ if elm.mono then
2532
+ pif2.rootElement.monoHook = true
2533
+
2534
+ pif2
2535
+ else
2536
+ pif2.rootElement.document = String.new(elm.mixed_content)
2537
+ pif2.rootElement.hook = true
2538
+
2539
+ pif2
2540
+ end
2541
+ end
2542
+ end
2543
+
2544
+ def setMonoInfo(elm)
2545
+ end
2546
+ private :setMonoInfo
2547
+
2548
+ #
2549
+ # 反映する
2550
+ #
2551
+ def flush
2552
+ if @root.hook || @root.monoHook then
2553
+ if @root.element then
2554
+ @parent.reflect
2555
+ @parent.replace(@root.element, @root.hookDocument)
2556
+ end
2557
+ end
2558
+ end
2559
+
2560
+ #
2561
+ #
2562
+ #
2563
+ def execute(*args)
2564
+ case args.length
2565
+ when 1
2566
+ execute_2(args[0],args[1])
2567
+ when 2
2568
+ execute_3(args[0],args[1],args[2])
2569
+ else
2570
+ raise ArgumentError
2571
+ end
2572
+ end
2573
+
2574
+ def execute_2(elm,hook)
2575
+ hook.doAction(elm, self)
2576
+ end
2577
+ private :execute_2
2578
+
2579
+ def execute_3(elm,loop,list)
2580
+ loop.doAction(elm, this, list)
2581
+ end
2582
+ private :execute_3
2583
+
2584
+ #
2585
+ # 正規表現対象文字を置換する
2586
+ #
2587
+ # @param [String] element 入力文字列
2588
+ # @return [String] 出力文字列
2589
+ #
2590
+ def escapeRegex(element)
2591
+ ##「\」->[\\]
2592
+ #element.gsub!(@@pattern_en,EN_2)
2593
+ ##「$」->「\$」
2594
+ #element.gsub!(@@pattern_dol,DOL_2)
2595
+ ##「+」->「\+」
2596
+ #element.gsub!(@@pattern_plus,PLUS_2)
2597
+ #todo
2598
+ ##「(」->「\(」
2599
+ #element.gsub!(@@pattern_brac_open,BRAC_OPEN_2)
2600
+ ##「)」->「\)」
2601
+ #element.gsub!(@@pattern_brac_close,BRAC_CLOSE_2)
2602
+ ##「[」->「\[」
2603
+ #element.gsub!(@@pattern_sbrac_open,SBRAC_OPEN_2)
2604
+ ##「]」->「\]」
2605
+ #element.gsub!(@@pattern_sbrac_close,SBRAC_CLOSE_2)
2606
+ ##「{」->「\{」
2607
+ #element.gsub!(@@pattern_cbrac_open,CBRAC_OPEN_2)
2608
+ ##「}」->「\}」
2609
+ #element.gsub!(@@pattern_cbrac_close,CBRAC_CLOSE_2)
2610
+ ##「.」->「\.」
2611
+ #element.gsub!(@@pattern_comma,COMMA_2)
2612
+ ##「|」->「\|」
2613
+ #element.gsub!(@@pattern_vline,VLINE_2)
2614
+ ##「?」->「\?」
2615
+ #element.gsub!(@@pattern_qmark,QMARK_2)
2616
+ ##「*」->「\*」
2617
+ #element.gsub!(@@pattern_asterisk,ASTERISK_2)
2618
+ Regexp.quote(element)
2619
+
2620
+ end
2621
+ private :escapeRegex
2622
+
2623
+ def replace2Regex(element)
2624
+ if element.include?(EN_1) then
2625
+ element.gsub!(@@pattern_sub_regex1,SUB_REGEX2)
2626
+ end
2627
+ end
2628
+ private :replace2Regex
2629
+
2630
+ def replace4Regex(element)
2631
+ if element.include?(EN_1) then
2632
+ element.gsub!(@@pattern_sub_regex1,SUB_REGEX3)
2633
+ end
2634
+ end
2635
+ private :replace4Regex
2636
+
2637
+ #
2638
+ # @param [String] element 入力文字列
2639
+ # @return [String] 出力文字列
2640
+ #
2641
+ def escape(element)
2642
+ element;
2643
+ end
2644
+ private :escape
2645
+
2646
+ #
2647
+ # @param [String] element 入力文字列
2648
+ # @param [String] elmName 要素名
2649
+ # @return [String] 出力文字列
2650
+ #
2651
+ def escapeContent(element,elmName)
2652
+ element
2653
+ end
2654
+ private :escapeContent
2655
+
2656
+ #
2657
+ # @param [String] element 入力文字列
2658
+ # @return [String] 出力文字列
2659
+ #
2660
+ def unescape(element)
2661
+ element;
2662
+ end
2663
+ private :unescape
2664
+
2665
+ #
2666
+ # @param [String] element 入力文字列
2667
+ # @param [String] elmName 要素名
2668
+ # @return [String] 出力文字列
2669
+ #
2670
+ def unescapeContent(element,elmName)
2671
+ element;
2672
+ end
2673
+ private :unescapeContent
2674
+
2675
+ def isMatch(regex,str)
2676
+ if regex.kind_of?(Regexp) then
2677
+ if regex.match(str.downcase) then
2678
+ true
2679
+ else
2680
+ false
2681
+ end
2682
+ elsif regex.kind_of?(Array) then
2683
+ str = str.downcase
2684
+ regex.each { |item|
2685
+ if item.eql?(str) then
2686
+ return true
2687
+ end
2688
+ }
2689
+ return false
2690
+ elsif regex.kind_of?(String) then
2691
+ if regex.eql?(str.downcase) then
2692
+ true
2693
+ else
2694
+ false
2695
+ end
2696
+ else
2697
+ raise ArgumentError
2698
+ end
2699
+ end
2700
+ private :isMatch
2701
+
2702
+
2703
+ def create(pif)
2704
+ if pif.instance_of?(Meteor::Core::Html::ParserImpl) then
2705
+ pif = Meteor::Core::Html::ParserImpl.new
2706
+ elsif pif.instance_of?(Meteor::Core::Xhtml::ParserImpl) then
2707
+ pif = Meteor::Core::Xhtml::ParserImpl.new
2708
+ elsif pif.instance_of?(Meteor::Core::Xml::ParserImpl) then
2709
+ pif = Meteor::Core::Xml::ParserImpl.new
2710
+ else
2711
+ pif = nil
2712
+ end
2713
+
2714
+ end
2715
+ private :create
2716
+
2717
+ #
2718
+ # 要素の属性or内容をセットする
2719
+ # @param [String] name 属性名
2720
+ # @param [String] value 属性値or内容
2721
+ #
2722
+ def []=(name,value)
2723
+ if !name.kind_of?(String)|| name != ':content' then
2724
+ attribute(name,value)
2725
+ else
2726
+ content(value)
2727
+ end
2728
+ end
2729
+
2730
+ #
2731
+ # 要素の属性値or内容を取得する
2732
+ # @param [String] name 属性名
2733
+ # @return [String] 属性値or内容
2734
+ #
2735
+ def [](name)
2736
+ if !name.kind_of?(String)|| name != ':content' then
2737
+ attribute(name)
2738
+ else
2739
+ content()
2740
+ end
2741
+ end
2742
+ end
2743
+
2744
+ module Util
2745
+
2746
+ #
2747
+ # パターンキャッシュクラス
2748
+ #
2749
+ class PatternCache
2750
+ @@regexCache = Hash.new
2751
+
2752
+ #
2753
+ # イニシャライザ
2754
+ #
2755
+ def initialize
2756
+ end
2757
+
2758
+ def self.get(*args)
2759
+ case args.length
2760
+ when 1
2761
+ get_1(args[0])
2762
+ when 2
2763
+ get_2(args[0],args[1])
2764
+ else
2765
+ raise ArgumentError
2766
+ end
2767
+ end
2768
+
2769
+ #
2770
+ # パターンを取得する
2771
+ # @param [String] regex 正規表現
2772
+ # @return [Regexp] パターン
2773
+ #
2774
+ def self.get_1(regex)
2775
+ #pattern = @@regexCache[regex]
2776
+ #
2777
+ #if pattern == nil then
2778
+ if regex.kind_of?(String) then
2779
+ if !@@regexCache[regex.to_sym] then
2780
+ #pattern = Regexp.new(regex)
2781
+ #@@regexCache[regex] = pattern
2782
+ @@regexCache[regex.to_sym] = Regexp.new(regex,Regexp::MULTILINE)
2783
+ end
2784
+
2785
+ #return pattern
2786
+ @@regexCache[regex.to_sym]
2787
+ elsif regex.kind_of?(Symbol) then
2788
+ if !@@regexCache[regex] then
2789
+ @@regexCache[regex] = Regexp.new(regex.to_s,Regexp::MULTILINE)
2790
+ end
2791
+
2792
+ @@regexCache[regex]
2793
+ end
2794
+ end
2795
+
2796
+ #
2797
+ # パターンを取得する
2798
+ # @param [String] regex 正規表現
2799
+ # @return [Regexp] パターン
2800
+ #
2801
+ def self.get_2(regex,option)
2802
+ #pattern = @@regexCache[regex]
2803
+ #
2804
+ #if pattern == nil then
2805
+ if regex.kind_of?(String) then
2806
+ if !@@regexCache[regex.to_sym] then
2807
+ #pattern = Regexp.new(regex)
2808
+ #@@regexCache[regex] = pattern
2809
+ @@regexCache[regex.to_sym] = Regexp.new(regex,option)
2810
+ end
2811
+
2812
+ #return pattern
2813
+ @@regexCache[regex.to_sym]
2814
+ elsif regex.kind_of?(Symbol) then
2815
+ if !@@regexCache[regex] then
2816
+ @@regexCache[regex] = Regexp.new(regex.to_s,option)
2817
+ end
2818
+
2819
+ @@regexCache[regex]
2820
+ end
2821
+ end
2822
+ end
2823
+
2824
+ class OrderHash <Hash
2825
+
2826
+ def initialize
2827
+ @keys = Array.new
2828
+ @values = Array.new
2829
+ end
2830
+
2831
+ attr_accessor :keys
2832
+ attr_accessor :values
2833
+
2834
+ def store(key, value)
2835
+ super(key, value)
2836
+ unless @keys.include?(key)
2837
+ @keys << key
2838
+ @values << value
2839
+ end
2840
+ end
2841
+
2842
+ def clear
2843
+ @keys.clear
2844
+ @values.clear
2845
+ super
2846
+ end
2847
+
2848
+ def delete(key)
2849
+ if @keys.include?(key)
2850
+ @keys.delete(key)
2851
+ @values.delete(fetch(key))
2852
+ super(key)
2853
+ elsif
2854
+ yield(key)
2855
+ end
2856
+ end
2857
+
2858
+ #superとして、Hash#[]=を呼び出す
2859
+ def []=(key, value)
2860
+ store(key, value)
2861
+ end
2862
+
2863
+ def each
2864
+ @keys.each{|k|
2865
+ arr_tmp = Array.new
2866
+ arr_tmp << k
2867
+ arr_tmp << self[k]
2868
+ yield(arr_tmp)
2869
+ }
2870
+ return self
2871
+ end
2872
+
2873
+ def each_pair
2874
+ @keys.each{|k|
2875
+ yield(k, self[k])
2876
+ }
2877
+ return self
2878
+ end
2879
+
2880
+ def map
2881
+ arr_tmp = Array.new
2882
+ @keys.each{|k|
2883
+ arg_arr = Array.new
2884
+ arg_arr << k
2885
+ arg_arr << self[k]
2886
+ arr_tmp << yield(arg_arr)
2887
+ }
2888
+ return arr_tmp
2889
+ end
2890
+
2891
+ def sort_hash(&block)
2892
+ if block_given?
2893
+ arr_tmp = self.sort(&block)
2894
+ elsif
2895
+ arr_tmp = self.sort
2896
+ end
2897
+ hash_tmp = OrderHash.new
2898
+ arr_tmp.each{|item|
2899
+ hash_tmp[item[0]] = item[1]
2900
+ }
2901
+ return hash_tmp
2902
+ end
2903
+ end
2904
+ end
2905
+
2906
+ module Html
2907
+ #
2908
+ # HTMLパーサ
2909
+ #
2910
+ class ParserImpl < Meteor::Core::Kernel
2911
+
2912
+ KAIGYO_CODE = "(\r?\n|\r)"
2913
+ NBSP_2 = '&nbsp;'
2914
+ BR_1 = "\r?\n|\r"
2915
+ BR_2 = "<br>"
2916
+
2917
+ META = 'META'
2918
+ META_S = 'meta'
2919
+
2920
+ #MATCH_TAG = "br|hr|img|input|meta|base"
2921
+ MATCH_TAG = ['br','hr','img','input','meta','base']
2922
+ #MATCH_TAG_2 = "textarea|option|pre"
2923
+ MATCH_TAG_2 =['textarea','option','pre']
2924
+
2925
+ HTTP_EQUIV = 'http-equiv'
2926
+ CONTENT_TYPE = 'Content-Type'
2927
+ CONTENT = 'content'
2928
+
2929
+ ATTR_LOGIC = ['disabled','readonly','checked','selected','multiple']
2930
+ OPTION = 'option'
2931
+ SELECTED = 'selected'
2932
+ INPUT = 'input'
2933
+ CHECKED = 'checked'
2934
+ RADIO = 'radio'
2935
+ #DISABLE_ELEMENT = "input|textarea|select|optgroup"
2936
+ DISABLE_ELEMENT = ['input','textarea','select','optgroup']
2937
+ DISABLED = 'disabled'
2938
+ #READONLY_TYPE = "text|password"
2939
+ READONLY_TYPE = ['text','password']
2940
+ TEXTAREA = 'textarea'
2941
+ READONLY='readonly'
2942
+ SELECT = 'select'
2943
+ MULTIPLE = 'multiple'
2944
+
2945
+ #@@pattern_option = Regexp.new(OPTION)
2946
+ #@@pattern_selected = Regexp.new(SELECTED)
2947
+ #@@pattern_input = Regexp.new(INPUT)
2948
+ #@@pattern_checked = Regexp.new(CHECKED)
2949
+ #@@pattern_radio = Regexp.new(RADIO)
2950
+ #@@pattern_disable_element = Regexp.new(DISABLE_ELEMENT)
2951
+ #@@pattern_disabled = Regexp.new(DISABLED)
2952
+ #@@pattern_readonly_type = Regexp.new(READONLY_TYPE)
2953
+ #@@pattern_textarea = Regexp.new(TEXTAREA)
2954
+ #@@pattern_readonly = Regexp.new(READONLY)
2955
+ #@@pattern_select = Regexp.new(SELECT)
2956
+ #@@pattern_multiple = Regexp.new(MULTIPLE)
2957
+
2958
+ SELECTED_M = "\\sselected\\s|\\sselected$|\\sSELECTED\\s|\\sSELECTED$"
2959
+ SELECTED_R = "selected\\s|selected$|SELECTED\\s|SELECTED$"
2960
+ CHECKED_M = "\\schecked\\s|\\schecked$|\\sCHECKED\\s|\\sCHECKED$"
2961
+ CHECKED_R = "checked\\s|checked$|CHECKED\\s|CHECKED$"
2962
+ DISABLED_M = "\\sdisabled\\s|\\sdisabled$|\\sDISABLED\\s|\\sDISABLED$"
2963
+ DISABLED_R = "disabled\\s|disabled$|DISABLED\\s|DISABLED$"
2964
+ READONLY_M = "\\sreadonly\\s|\\sreadonly$|\\sREADONLY\\s|\\sREADONLY$"
2965
+ READONLY_R = "readonly\\s|readonly$|READONLY\\s|READONLY$"
2966
+ MULTIPLE_M = "\\smultiple\\s|\\smultiple$|\\sMULTIPLE\\s|\\sMULTIPLE$"
2967
+ MULTIPLE_R = "multiple\\s|multiple$|MULTIPLE\\s|MULTIPLE$"
2968
+
2969
+ @@pattern_selected_m = Regexp.new(SELECTED_M)
2970
+ @@pattern_selected_r = Regexp.new(SELECTED_R)
2971
+ @@pattern_checked_m = Regexp.new(CHECKED_M)
2972
+ @@pattern_checked_r = Regexp.new(CHECKED_R)
2973
+ @@pattern_disabled_m = Regexp.new(DISABLED_M)
2974
+ @@pattern_disabled_r = Regexp.new(DISABLED_R)
2975
+ @@pattern_readonly_m = Regexp.new(READONLY_M)
2976
+ @@pattern_readonly_r = Regexp.new(READONLY_R)
2977
+ @@pattern_multiple_m = Regexp.new(MULTIPLE_M)
2978
+ @@pattern_multiple_r = Regexp.new(MULTIPLE_R)
2979
+
2980
+ TRUE = 'true'
2981
+ FALSE = 'false'
2982
+
2983
+ #@@pattern_true = Regexp.new(TRUE)
2984
+ #@@pattern_false = Regexp.new(FALSE)
2985
+
2986
+ TYPE_L = 'type'
2987
+ TYPE_U = 'TYPE'
2988
+
2989
+ @@pattern_and_1 = Regexp.new(AND_1)
2990
+ @@pattern_lt_1 = Regexp.new(LT_1)
2991
+ @@pattern_gt_1 = Regexp.new(GT_1)
2992
+ @@pattern_dq_1 = Regexp.new(DOUBLE_QUATATION)
2993
+ @@pattern_space_1 = Regexp.new(SPACE)
2994
+ @@pattern_br_1 = Regexp.new(BR_1)
2995
+ @@pattern_lt_2 = Regexp.new(LT_2)
2996
+ @@pattern_gt_2 = Regexp.new(GT_2)
2997
+ @@pattern_dq_2 = Regexp.new(QO_2)
2998
+ @@pattern_space_2 = Regexp.new(NBSP_2)
2999
+ @@pattern_and_2 = Regexp.new(AND_2)
3000
+ @@pattern_br_2 = Regexp.new(BR_2)
3001
+
3002
+ #@@pattern_match_tag = Regexp.new(MATCH_TAG)
3003
+ @@pattern_set_mono1 = Regexp.new(SET_MONO_1)
3004
+ #@@pattern_match_tag2 = Regexp.new(MATCH_TAG_2)
3005
+
3006
+ GET_ATTRS_MAP2="\\s(disabled|readonly|checked|selected|multiple)"
3007
+ @@pattern_get_attrs_map2 = Regexp.new(GET_ATTRS_MAP2)
3008
+
3009
+ #
3010
+ # イニシャライザ
3011
+ #
3012
+ # @param [Array] args 引数配列
3013
+ #
3014
+ def initialize(*args)
3015
+ super(args)
3016
+ case args.length
3017
+ when 0
3018
+ initialize_0
3019
+ when 1
3020
+ initialize_1(args[0])
3021
+ else
3022
+ raise ArgumentError
3023
+ end
3024
+ end
3025
+
3026
+ #
3027
+ # イニシャライザ
3028
+ #
3029
+ def initialize_0
3030
+ end
3031
+ private :initialize_0
3032
+
3033
+ #
3034
+ # イニシャライザ
3035
+ # @param [Meteor::Parser] ps パーサ
3036
+ #
3037
+ def initialize_1(ps)
3038
+ @root.document = String.new(ps.document)
3039
+ @root.hookDocument = String.new(ps.hookDocument)
3040
+ @root.hook = ps.hook
3041
+ @root.monoHook = ps.monoHook
3042
+ @root.contentType = String.new(ps.contentType);
3043
+ end
3044
+ private :initialize_1
3045
+
3046
+ #
3047
+ # ドキュメントをパーサにセットする
3048
+ #
3049
+ # @param [String] document ドキュメント
3050
+ #
3051
+ def parse(document)
3052
+ @root.document = document
3053
+ analyzeML()
3054
+ end
3055
+
3056
+ #
3057
+ # ファイルを読み込み、パーサにセットする
3058
+ #
3059
+ # @param [String] filePath ファイルパス
3060
+ # @param [String] encoding エンコーディング
3061
+ #
3062
+ def read(filePath,encoding)
3063
+ super(filePath,encoding)
3064
+ analyzeML()
3065
+ end
3066
+
3067
+ #
3068
+ # ドキュメントをパースする
3069
+ #
3070
+ def analyzeML()
3071
+ #content-typeの取得
3072
+ analyzeContentType()
3073
+ #改行コードの取得
3074
+ analyzeKaigyoCode()
3075
+
3076
+ @res = nil
3077
+ end
3078
+ private :analyzeML
3079
+
3080
+ # コンテントタイプを取得する
3081
+ #
3082
+ # @return [Streing]コンテントタイプ
3083
+ #
3084
+ def contentType()
3085
+ @root.contentType
3086
+ end
3087
+
3088
+ #
3089
+ # ドキュメントをパースし、コンテントタイプをセットする
3090
+ #
3091
+ def analyzeContentType()
3092
+ @elm_ = element(META_S,HTTP_EQUIV,CONTENT_TYPE)
3093
+
3094
+ if !@elm_ then
3095
+ @elm_ = element(META,HTTP_EQUIV,CONTENT_TYPE)
3096
+ end
3097
+
3098
+ if @elm_ then
3099
+ @root.contentType = @elm_.attribute(CONTENT)
3100
+ else
3101
+ @root.contentType = EMPTY
3102
+ end
3103
+ end
3104
+ private :analyzeContentType
3105
+
3106
+ #
3107
+ # ドキュメントをパースし、改行コードをセットする
3108
+ #
3109
+ def analyzeKaigyoCode()
3110
+ #改行コード取得
3111
+ @pattern = Regexp.new(KAIGYO_CODE)
3112
+ @res = @pattern.match(@root.document)
3113
+
3114
+ if @res then
3115
+ @root.kaigyoCode = @res[1]
3116
+ end
3117
+ end
3118
+ private :analyzeKaigyoCode
3119
+
3120
+ #
3121
+ # 要素名で検索し、要素を取得する
3122
+ #
3123
+ # @param [String] elmName 要素名
3124
+ # @return [Meteor::Element] 要素
3125
+ #
3126
+ def element_1(elmName)
3127
+ @_elmName = escapeRegex(elmName)
3128
+
3129
+ #空要素の場合(<->内容あり要素の場合)
3130
+ if isMatch(MATCH_TAG,elmName) then
3131
+ #空要素検索用パターン
3132
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_1_4_2
3133
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
3134
+ @res = @pattern.match(@root.document)
3135
+ if @res then
3136
+ elementWithoutContent_1(elmName)
3137
+ else
3138
+ @elm_ = nil
3139
+ end
3140
+ else
3141
+ #内容あり要素検索用パターン
3142
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_1_1 << elmName
3143
+ @pattern_cc << TAG_SEARCH_1_2 << @_elmName << TAG_CLOSE
3144
+
3145
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
3146
+ #内容あり要素検索
3147
+ @res = @pattern.match(@root.document)
3148
+ #内容あり要素の場合
3149
+ if @res then
3150
+ elementWithContent_1(elmName)
3151
+ else
3152
+ @elm_ = nil
3153
+ end
3154
+ end
3155
+
3156
+ @elm_
3157
+ end
3158
+ private :element_1
3159
+
3160
+ def elementWithoutContent_1(elmName)
3161
+ @elm_ = Element.new(elmName)
3162
+ #属性
3163
+ @elm_.attributes = @res[1]
3164
+ #空要素検索用パターン
3165
+ @elm_.pattern = @pattern_cc
3166
+
3167
+ @elm_.document = @res[0]
3168
+
3169
+ @elm.parser = self
3170
+ end
3171
+ private :elementWithoutContent_1
3172
+
3173
+ #
3174
+ # 要素名、属性(属性名="属性値")で検索し、要素を取得する
3175
+ #
3176
+ # @param [String] elmName 要素名
3177
+ # @param [String] attrName 属性名
3178
+ # @param [String] attrValue 属性値
3179
+ # @return [Meteor::Element] 要素
3180
+ #
3181
+ def element_3(elmName,attrName,attrValue)
3182
+
3183
+ @_elmName = escapeRegex(elmName)
3184
+ @_attrName = escapeRegex(attrName)
3185
+ @_attrValue = escapeRegex(attrValue)
3186
+ #空要素の場合(<->内容あり要素の場合)
3187
+ if isMatch(MATCH_TAG,elmName) then
3188
+ #空要素検索パターン
3189
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1 << @_attrName << ATTR_EQ
3190
+ @pattern_cc << @_attrValue << TAG_SEARCH_2_4_3
3191
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
3192
+ #空要素検索
3193
+ @res = @pattern.match(@root.document)
3194
+ if @res then
3195
+ elementWithoutContent_3(elmName)
3196
+ else
3197
+ @elm_ = nil
3198
+ end
3199
+ else
3200
+ #内容あり要素検索パターン
3201
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1 << @_attrName << ATTR_EQ
3202
+ @pattern_cc << @_attrValue << TAG_SEARCH_2_2 << @_elmName
3203
+ @pattern_cc << TAG_SEARCH_1_2 << @_elmName << TAG_CLOSE
3204
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
3205
+ #内容あり要素検索
3206
+ @res = @pattern.match(@root.document)
3207
+
3208
+ if !@res then
3209
+ @res = elementWithContent_3_2(elmName)
3210
+ end
3211
+
3212
+ if @res then
3213
+ elementWithContent_3_1(elmName)
3214
+ else
3215
+ @elm_ = nil
3216
+ end
3217
+ end
3218
+
3219
+ if @elm_ then
3220
+ @elm_.arguments.store(attrName, attrValue)
3221
+ @elm_.arguments.recordable = true
3222
+ end
3223
+
3224
+ @elm_
3225
+ end
3226
+ private :element_3
3227
+
3228
+ def elementWithoutContent_3(elmName)
3229
+ elementWithoutContent_3_1(elmName,TAG_SEARCH_NC_2_4_3)
3230
+ end
3231
+ private :elementWithoutContent_3
3232
+
3233
+ #
3234
+ # 属性(属性名="属性値")で検索し、要素を取得する
3235
+ #
3236
+ # @param [String] attrName 属性名
3237
+ # @param [String] attrValue 属性値
3238
+ # @return [Meteor::Element] 要素
3239
+ #
3240
+ def element_2(attrName,attrValue)
3241
+ @_attrName = escapeRegex(attrName)
3242
+ @_attrValue = escapeRegex(attrValue)
3243
+
3244
+ @pattern_cc = '' << TAG_SEARCH_3_1 << @_attrName << ATTR_EQ << @_attrValue
3245
+ @pattern_cc << TAG_SEARCH_2_4_4
3246
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
3247
+ @res = @pattern.match(@root.document)
3248
+
3249
+ if @res then
3250
+ @elm_ = element_3(@res[1],attrName,attrValue)
3251
+ else
3252
+ @elm_ = nil
3253
+ end
3254
+
3255
+ @elm_
3256
+ end
3257
+ private :element_2
3258
+
3259
+ #
3260
+ # 要素名と属性1・属性2(属性名="属性値")で検索し、要素を取得する
3261
+ #
3262
+ # @param [String] elmName 要素名
3263
+ # @param attrName1 属性名1
3264
+ # @param attrValue1 属性値1
3265
+ # @param attrName2 属性名2
3266
+ # @param attrValue2 属性値2
3267
+ # @return [Meteor::Element] 要素
3268
+ #
3269
+ def element_5(elmName,attrName1,attrValue1,attrName2,attrValue2)
3270
+
3271
+ @_elmName = escapeRegex(elmName)
3272
+ @_attrName1 = escapeRegex(attrName1)
3273
+ @_attrValue1 = escapeRegex(attrValue1)
3274
+ @_attrName2 = escapeRegex(attrName2)
3275
+ @_attrValue2 = escapeRegex(attrValue2)
3276
+
3277
+ #空要素の場合(<->内容あり要素の場合)
3278
+ if isMatch(MATCH_TAG,elmName) then
3279
+ #空要素検索パターン
3280
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1_2 << @_attrName1 << ATTR_EQ
3281
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ
3282
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ
3283
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ
3284
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_2_4_3_2
3285
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
3286
+ #空要素検索
3287
+ @res = @pattern.match(@root.document)
3288
+
3289
+ if @res then
3290
+ elementWithoutContent_5(elmName)
3291
+ else
3292
+ @elm_ = nil
3293
+ end
3294
+ else
3295
+ #内容あり要素検索パターン
3296
+ @pattern_cc = '' << TAG_OPEN << @_elmName << TAG_SEARCH_2_1_2 << @_attrName1 << ATTR_EQ
3297
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ
3298
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ
3299
+ @pattern_cc << @_attrValue2 << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ
3300
+ @pattern_cc << @_attrValue1 << TAG_SEARCH_2_2_2 << @_elmName
3301
+ @pattern_cc << TAG_SEARCH_1_2 << @_elmName << TAG_CLOSE
3302
+ @pattern = Meteor::Core::Util::PatternCache.get(@pattern_cc)
3303
+ #内容あり要素検索
3304
+ @res = @pattern.match(@root.document)
3305
+
3306
+ if !@res then
3307
+ @res = elementWithContent_5_2(elmName)
3308
+ end
3309
+
3310
+ if @res then
3311
+ elementWithContent_5_1(elmName)
3312
+ else
3313
+ @elm_ = nil
3314
+ end
3315
+ end
3316
+
3317
+ if @elm_ then
3318
+ @elm_.arguments.store(attrName1, attrValue1)
3319
+ @elm_.arguments.store(attrName2, attrValue2)
3320
+ @elm_.arguments.recordable = true
3321
+ end
3322
+
3323
+ @elm_
3324
+ end
3325
+ private :element_5
3326
+
3327
+ def elementWithoutContent_5(elmName)
3328
+ elementWithoutContent_5_1(elmName,TAG_SEARCH_NC_2_4_3_2)
3329
+ end
3330
+ private :elementWithoutContent_5
3331
+
3332
+ #
3333
+ # 属性1・属性2(属性名="属性値")で検索し、要素を取得する
3334
+ #
3335
+ # @param [String] attrName1 属性名1
3336
+ # @param [String] attrValue1 属性値1
3337
+ # @param [String] attrName2 属性名2
3338
+ # @param [String] attrValue2 属性値2
3339
+ # @return [Meteor::Element] 要素
3340
+ #
3341
+ def element_4(attrName1,attrValue1,attrName2,attrValue2)
3342
+ @_attrName1 = escapeRegex(attrName1)
3343
+ @_attrValue1 = escapeRegex(attrValue1)
3344
+ @_attrName2 = escapeRegex(attrName2)
3345
+ @_attrValue2 = escapeRegex(attrValue2)
3346
+
3347
+ @pattern_cc = '' << TAG_SEARCH_3_1_2_2 << @_attrName1 << ATTR_EQ << @_attrValue1
3348
+ @pattern_cc << TAG_SEARCH_2_6 << @_attrName2 << ATTR_EQ << @_attrValue2
3349
+ @pattern_cc << TAG_SEARCH_2_7 << @_attrName2 << ATTR_EQ << @_attrValue2
3350
+ @pattern_cc << TAG_SEARCH_2_6 << @_attrName1 << ATTR_EQ << @_attrValue1
3351
+ @pattern_cc << TAG_SEARCH_2_4_3_2
3352
+
3353
+ @pattern = Patterncache.get(@pattern_cc)
3354
+
3355
+ @res = @pattern.match(@root.document)
3356
+
3357
+ if @res then
3358
+ @elm_ = element_5(@res[1],attrName1,attrValue1,attrName2,attrValue2)
3359
+ else
3360
+ @elm_ = nil
3361
+ end
3362
+
3363
+ @elm_
3364
+ end
3365
+ private :element_4
3366
+
3367
+ def editAttributes_(elm,attrName,attrValue)
3368
+ if isMatch(SELECTED, attrName) && isMatch(OPTION,elm.name) then
3369
+ editAttributes_5(elm,attrName,attrValue,@@pattern_selected_m,@@pattern_selected_r)
3370
+ elsif isMatch(MULTIPLE, attrName) && isMatch(SELECT,elm.name)
3371
+ editAttributes_5(elm,attrName,attrValue,@@pattern_multiple_m,@@pattern_multiple_r)
3372
+ elsif isMatch(DISABLED, attrName) && isMatch(DISABLE_ELEMENT, elm.name) then
3373
+ editAttributes_5(elm,attrName,attrValue,@@pattern_disabled_m,@@pattern_disabled_r)
3374
+ elsif isMatch(CHECKED, attrName) && isMatch(INPUT,elm.name) && isMatch(RADIO, getType(elm)) then
3375
+ editAttributes_5(elm,attrName,attrValue,@@pattern_checked_m,@@pattern_checked_r)
3376
+ elsif isMatch(READONLY, attrName) && (isMatch(TEXTAREA,elm.name) || (isMatch(INPUT,elm.name) && isMatch(READONLY_TYPE, getType(elm)))) then
3377
+ editAttributes_5(elm,attrName,attrValue,@@pattern_readonly_m,@@pattern_readonly_r)
3378
+ else
3379
+ super(elm,attrName,attrValue)
3380
+ end
3381
+ end
3382
+ private :editAttributes_
3383
+
3384
+ def editAttributes_5(elm,attrName,attrValue,match_p,replace)
3385
+ #attrValue = escape(attrValue)
3386
+
3387
+ if isMatch(TRUE, attrValue) then
3388
+ @res = match_p.match(elm.attributes)
3389
+
3390
+ if !@res then
3391
+ if !EMPTY.eql?(elm.attributes) && !EMPTY.eql?(elm.attributes.strip) then
3392
+ elm.attributes = '' << SPACE << elm.attributes.strip
3393
+ else
3394
+ elm.attributes = ''
3395
+ end
3396
+ elm.attributes << SPACE << attrName
3397
+ #else
3398
+ end
3399
+ elsif isMatch(FALSE, attrValue) then
3400
+ elm.attributes.sub!(replace,EMPTY)
3401
+ end
3402
+
3403
+ end
3404
+ private :editAttributes_5
3405
+
3406
+ def editDocument_1(elm)
3407
+ editDocument_2(elm,TAG_CLOSE)
3408
+ end
3409
+ private :editDocument_1
3410
+
3411
+ def getAttributeValue_(elm,attrName)
3412
+ if isMatch(SELECTED, attrName) && isMatch(OPTION,elm.name) then
3413
+ getAttributeValue_2_r(elm,@@pattern_selected_m)
3414
+ elsif isMatch(MULTIPLE, attrName) && isMatch(SELECT,elm.name)
3415
+ getAttributeValue_2_r(elm,@@pattern_multiple_m)
3416
+ elsif isMatch(DISABLED, attrName) && isMatch(DISABLE_ELEMENT, elm.name) then
3417
+ getAttributeValue_2_r(elm,@@pattern_disabled_m)
3418
+ elsif isMatch(CHECKED, attrName) && isMatch(INPUT,elm.name) && isMatch(RADIO, getType(elm)) then
3419
+ getAttributeValue_2_r(elm,@@pattern_checked_m)
3420
+ elsif isMatch(READONLY, attrName) && (isMatch(TEXTAREA,elm.name) || (isMatch(INPUT,elm.name) && isMatch(READONLY_TYPE, getType(elm)))) then
3421
+ getAttributeValue_2_r(elm,@@pattern_readonly_m)
3422
+ else
3423
+ super(elm,attrName)
3424
+ end
3425
+ end
3426
+ private :getAttributeValue_
3427
+
3428
+ def getType(elm)
3429
+ if !elm.type_value
3430
+ elm.type_value = getAttributeValue_2(elm, TYPE_L)
3431
+ if !elm.type_value then
3432
+ elm.type_value = getAttributeValue_2(elm, TYPE_U)
3433
+ end
3434
+ end
3435
+ elm.type_value
3436
+ end
3437
+ private :getType
3438
+
3439
+ def getAttributeValue_2_r(elm,match_p)
3440
+
3441
+ @res = match_p.match(elm.attributes)
3442
+
3443
+ if @res then
3444
+ TRUE
3445
+ else
3446
+ FALSE
3447
+ end
3448
+ end
3449
+ private :getAttributeValue_2_r
3450
+
3451
+ #
3452
+ # 要素の属性マップを取得する
3453
+ #
3454
+ # @param [Meteor::Element] elm 要素
3455
+ # @return [Meteor::AttributeMap] 属性マップ
3456
+ #
3457
+ def getAttributeMap_1(elm)
3458
+ attrs = Meteor::AttributeMap.new
3459
+
3460
+ elm.attributes.scan(@@pattern_get_attrs_map){ |a,b|
3461
+ attrs.store(a,unescape(b))
3462
+ }
3463
+
3464
+ elm.attributes.scan(@@pattern_get_attrs_map2){ |a|
3465
+ attrs.store(a, TRUE)
3466
+ }
3467
+
3468
+ attrs.recordable = true
3469
+
3470
+ attrs
3471
+ end
3472
+ private :getAttributeMap_1
3473
+
3474
+ def removeAttributes_(elm,attrName)
3475
+ #検索対象属性の論理型是非判定
3476
+ if !isMatch(ATTR_LOGIC,attrName) then
3477
+ #属性検索用パターン
3478
+ @pattern = Meteor::Core::Util::PatternCache.get('' << attrName << ERASE_ATTR_1)
3479
+ elm.attributes.sub!(@pattern, EMPTY)
3480
+ else
3481
+ #属性検索用パターン
3482
+ @pattern = Meteor::Core::Util::PatternCache.get(attrName)
3483
+ elm.attributes.sub!(@pattern, EMPTY)
3484
+ #end
3485
+ end
3486
+ end
3487
+ private :removeAttributes_
3488
+
3489
+ def setMonoInfo(elm)
3490
+
3491
+ @res = @@pattern_set_mono1.match(elm.mixed_content)
3492
+
3493
+ if @res then
3494
+ elm.mono = true
3495
+ if elm.cx then
3496
+ @pattern_cc = '' << SET_CX_1 << elm.name << SPACE << elm.attributes << SET_CX_2 << elm.mixed_content << SET_CX_3 << elm.name << SET_CX_4
3497
+ else
3498
+ if elm.empty then
3499
+ @pattern_cc = '' << TAG_OPEN << elm.name << elm.attributes << TAG_CLOSE << elm.mixed_content << TAG_OPEN3 << elm.name << TAG_CLOSE
3500
+ else
3501
+ @pattern_cc = '' << TAG_OPEN << elm.name << elm.attributes << TAG_CLOSE
3502
+ end
3503
+ end
3504
+ elm.document = @pattern_cc
3505
+ end
3506
+ end
3507
+ private :setMonoInfo
3508
+
3509
+ def escape(element)
3510
+ #特殊文字の置換
3511
+ #「&」->「&amp;」
3512
+ if element.include?(AND_1) then
3513
+ element.gsub!(@@pattern_and_1,AND_2)
3514
+ end
3515
+ #「<」->「&lt;」
3516
+ if element.include?(LT_1) then
3517
+ element.gsub!(@@pattern_lt_1,LT_2)
3518
+ end
3519
+ #「>」->「&gt;」
3520
+ if element.include?(GT_1) then
3521
+ element.gsub!(@@pattern_gt_1,GT_2)
3522
+ end
3523
+ #「"」->「&quotl」
3524
+ if element.include?(DOUBLE_QUATATION) then
3525
+ element.gsub!(@@pattern_dq_1,QO_2)
3526
+ end
3527
+ #「 」->「&nbsp;」
3528
+ if element.include?(SPACE) then
3529
+ element.gsub!(@@pattern_space_1,NBSP_2)
3530
+ end
3531
+
3532
+ element
3533
+ end
3534
+ private :escape
3535
+
3536
+ def escapeContent(element,elmName)
3537
+ element = escape(element)
3538
+
3539
+ if !isMatch(MATCH_TAG_2,elmName) then
3540
+ #「¥r?¥n」->「<br>」
3541
+ element.gsub!(@@pattern_br_1, BR_2)
3542
+ end
3543
+
3544
+ element
3545
+ end
3546
+ private :escapeContent
3547
+
3548
+ def unescape(element)
3549
+ #特殊文字の置換
3550
+ #「<」<-「&lt;」
3551
+ if element.include?(LT_2) then
3552
+ element.gsub!(@@pattern_lt_2,LT_1)
3553
+ end
3554
+ #「>」<-「&gt;」
3555
+ if element.include?(GT_2) then
3556
+ element.gsub!(@@pattern_gt_2,GT_1)
3557
+ end
3558
+ #「"」<-「&quotl」
3559
+ if element.include?(QO_2) then
3560
+ element.gsub!(@@pattern_dq_2,DOUBLE_QUATATION)
3561
+ end
3562
+ #「 」<-「&nbsp;」
3563
+ if element.include?(NBSP_2) then
3564
+ element.gsub!(@@pattern_space_2,SPACE)
3565
+ end
3566
+ #「&」<-「&amp;」
3567
+ if element.include?(AND_2) then
3568
+ element.gsub!(@@pattern_and_2,AND_1)
3569
+ end
3570
+ element
3571
+ end
3572
+ private :unescape
3573
+
3574
+ def unescapeContent(element,elmName)
3575
+ element = unescape(element)
3576
+
3577
+ if !isMatch(@@pattern_match_tag2,elmName) then
3578
+ #「<br>」->「¥r?¥n」
3579
+ if element.include?(BR_2) then
3580
+ element.gsub!(@@pattern_br_2, @root.kaigyoCode)
3581
+ end
3582
+ end
3583
+
3584
+ element
3585
+ end
3586
+ private :unescapeContent
3587
+
3588
+ end
3589
+ end
3590
+
3591
+ module Xhtml
3592
+
3593
+ #
3594
+ # XHTMLパーサ
3595
+ #
3596
+ class ParserImpl < Meteor::Core::Kernel
3597
+
3598
+ KAIGYO_CODE = "(\r?\n|\r)"
3599
+ NBSP_2 = '&nbsp;'
3600
+ BR_1 = "\r?\n|\r"
3601
+ BR_2 = '<br/>'
3602
+ BR_3 = "<br\\/>"
3603
+
3604
+ META = 'META'
3605
+ META_S = 'meta'
3606
+
3607
+ #MATCH_TAG_2 = "textarea|option|pre"
3608
+ MATCH_TAG_2 = ['textarea','option','pre']
3609
+
3610
+ ATTR_LOGIC = ['disabled','readonly','checked','selected','multiple']
3611
+ OPTION = 'option'
3612
+ SELECTED = 'selected'
3613
+ INPUT = 'input'
3614
+ CHECKED = 'checked'
3615
+ RADIO = 'radio'
3616
+ #DISABLE_ELEMENT = "input|textarea|select|optgroup"
3617
+ DISABLE_ELEMENT = ['input','textarea','select','optgroup']
3618
+ DISABLED = 'disabled'
3619
+ #READONLY_TYPE = "text|password"
3620
+ READONLY_TYPE = ['text','password']
3621
+ TEXTAREA = 'textarea'
3622
+ READONLY='readonly'
3623
+ SELECT = 'select'
3624
+ MULTIPLE = 'multiple'
3625
+
3626
+ #@@pattern_option = Regexp.new(OPTION)
3627
+ #@@pattern_selected = Regexp.new(SELECTED)
3628
+ #@@pattern_input = Regexp.new(INPUT)
3629
+ #@@pattern_checked = Regexp.new(CHECKED)
3630
+ #@@pattern_radio = Regexp.new(RADIO)
3631
+ #@@pattern_disable_element = Regexp.new(DISABLE_ELEMENT)
3632
+ #@@pattern_disabled = Regexp.new(DISABLED)
3633
+ #@@pattern_readonly_type = Regexp.new(READONLY_TYPE)
3634
+ #@@pattern_textarea = Regexp.new(TEXTAREA)
3635
+ #@@pattern_readonly = Regexp.new(READONLY)
3636
+ #@@pattern_select = Regexp.new(SELECT)
3637
+ #@@pattern_multiple = Regexp.new(MULTIPLE)
3638
+
3639
+ SELECTED_M = "\\sselected=\"[^\"]*\"\\s|\\sselected=\"[^\"]*\"$|\\sSELECTED=\"[^\"]*\"\\s|\\sSELECTED=\"[^\"]*\"$"
3640
+ SELECTED_M1 = "\\sselected=\"([^\"]*)\"\\s|\\sselected=\"([^\"]*)\"$|\\sSELECTED=\"([^\"]*)\"\\s|\\sSELECTED=\"([^\"]*)\"$"
3641
+ SELECTED_R = "selected=\"[^\"]*\"|SELECTED=\"[^\"]*\""
3642
+ SELECTED_U = "selected=\"selected\""
3643
+ CHECKED_M = "\\schecked=\"[^\"]*\"\\s|\\schecked=\"[^\"]*\"$|\\sCHECKED=\"[^\"]*\"\\s|\\sCHECKED=\"[^\"]*\"$"
3644
+ CHECKED_M1 = "\\schecked=\"([^\"]*)\"\\s|\\schecked=\"([^\"]*)\"$|\\sCHECKED=\"([^\"]*)\"\\s|\\sCHECKED=\"([^\"]*)\"$"
3645
+ CHECKED_R = "checked=\"[^\"]*\"|CHECKED=\"[^\"]*\""
3646
+ CHECKED_U = "checked=\"checked\""
3647
+ DISABLED_M = "\\sdisabled=\"[^\"]*\"\\s|\\sdisabled=\"[^\"]*\"$|\\sDISABLED=\"[^\"]*\"\\s|\\sDISABLED=\"[^\"]*\"$"
3648
+ DISABLED_M1 = "\\sdisabled=\"([^\"]*)\"\\s|\\sdisabled=\"([^\"]*)\"$|\\sDISABLED=\"([^\"]*)\"\\s|\\sDISABLED=\"([^\"]*)\"$"
3649
+ DISABLED_R = "disabled=\"[^\"]*\"|DISABLED=\"[^\"]*\""
3650
+ DISABLED_U = "disabled=\"disabled\""
3651
+ READONLY_M = "\\sreadonly=\"[^\"]*\"\\s|\\sreadonly=\"[^\"]*\"$|\\sREADONLY=\"[^\"]*\"\\s|\\sREADONLY=\"[^\"]*\"$"
3652
+ READONLY_M1 = "\\sreadonly=\"([^\"]*)\"\\s|\\sreadonly=\"([^\"]*)\"$|\\sREADONLY=\"([^\"]*)\"\\s|\\sREADONLY=\"([^\"]*)\"$"
3653
+ READONLY_R = "readonly=\"[^\"]*\"|READONLY=\"[^\"]*\""
3654
+ READONLY_U = "readonly=\"readonly\""
3655
+ MULTIPLE_M = "\\smultiple=\"[^\"]*\"\\s|\\smultiple=\"[^\"]*\"$|\\sMULTIPLE=\"[^\"]*\"\\s|\\sMULTIPLE=\"[^\"]*\"$"
3656
+ MULTIPLE_M1 = "\\smultiple=\"([^\"]*)\"\\s|\\smultiple=\"([^\"]*)\"$|\\sMULTIPLE=\"([^\"]*)\"\\s|\\sMULTIPLE=\"([^\"]*)\"$"
3657
+ MULTIPLE_R = "multiple=\"[^\"]*\"|MULTIPLE=\"[^\"]*\""
3658
+ MULTIPLE_U = "multiple=\"multiple\""
3659
+
3660
+ HTTP_EQUIV = 'http-equiv'
3661
+ CONTENT_TYPE = 'Content-Type'
3662
+ CONTENT = 'content'
3663
+
3664
+ @@pattern_selected_m = Regexp.new(SELECTED_M)
3665
+ @@pattern_selected_m1 = Regexp.new(SELECTED_M1)
3666
+ @@pattern_selected_r = Regexp.new(SELECTED_R)
3667
+ @@pattern_checked_m = Regexp.new(CHECKED_M)
3668
+ @@pattern_checked_m1 = Regexp.new(CHECKED_M1)
3669
+ @@pattern_checked_r = Regexp.new(CHECKED_R)
3670
+ @@pattern_disabled_m = Regexp.new(DISABLED_M)
3671
+ @@pattern_disabled_m1 = Regexp.new(DISABLED_M1)
3672
+ @@pattern_disabled_r = Regexp.new(DISABLED_R)
3673
+ @@pattern_readonly_m = Regexp.new(READONLY_M)
3674
+ @@pattern_readonly_m1 = Regexp.new(READONLY_M1)
3675
+ @@pattern_readonly_r = Regexp.new(READONLY_R)
3676
+ @@pattern_multiple_m = Regexp.new(MULTIPLE_M)
3677
+ @@pattern_multiple_m1 = Regexp.new(MULTIPLE_M1)
3678
+ @@pattern_multiple_r = Regexp.new(MULTIPLE_R)
3679
+
3680
+ TRUE = 'true'
3681
+ FALSE = 'false'
3682
+
3683
+ TYPE_L = 'type'
3684
+ TYPE_U = 'TYPE'
3685
+
3686
+ @@pattern_and_1 = Regexp.new(AND_1)
3687
+ @@pattern_lt_1 = Regexp.new(LT_1)
3688
+ @@pattern_gt_1 = Regexp.new(GT_1)
3689
+ @@pattern_dq_1 = Regexp.new(DOUBLE_QUATATION)
3690
+ @@pattern_space_1 = Regexp.new(SPACE)
3691
+ @@pattern_br_1 = Regexp.new(BR_1)
3692
+ @@pattern_lt_2 = Regexp.new(LT_2)
3693
+ @@pattern_gt_2 = Regexp.new(GT_2)
3694
+ @@pattern_dq_2 = Regexp.new(QO_2)
3695
+ @@pattern_space_2 = Regexp.new(NBSP_2)
3696
+ @@pattern_and_2 = Regexp.new(AND_2)
3697
+ @@pattern_br_2 = Regexp.new(BR_3)
3698
+
3699
+ #@@pattern_match_tag = Regexp.new(MATCH_TAG)
3700
+ @@pattern_set_mono1 = Regexp.new(SET_MONO_1)
3701
+ #@@pattern_match_tag2 = Regexp.new(MATCH_TAG_2)
3702
+
3703
+ #
3704
+ # イニシャライザ
3705
+ # @param [Array] args 引数配列
3706
+ #
3707
+ def initialize(*args)
3708
+ super(args)
3709
+ case args.length
3710
+ when 0
3711
+ initialize_0
3712
+ when 1
3713
+ initialize_1(args[0])
3714
+ else
3715
+ raise ArgumentError
3716
+ end
3717
+ end
3718
+
3719
+ #
3720
+ # イニシャライザ
3721
+ #
3722
+ def initialize_0
3723
+ end
3724
+ private :initialize_0
3725
+
3726
+ #
3727
+ # イニシャライザ
3728
+ #
3729
+ # @param [Meteor::Parser] ps パーサ
3730
+ #
3731
+ def initialize_1(ps)
3732
+ @root.document = String.new(ps.document)
3733
+ @root.hookDocument = String.new(ps.hookDocument)
3734
+ @root.hook = ps.hook
3735
+ @root.monoHook = ps.monoHook
3736
+ @root.contentType = String.new(ps.contentType);
3737
+ end
3738
+ private :initialize_1
3739
+
3740
+ #
3741
+ # ドキュメントをパーサにセットする
3742
+ #
3743
+ # @param [String] document ドキュメント
3744
+ #
3745
+ def parse(document)
3746
+ @root.document = document
3747
+ analyzeML()
3748
+ end
3749
+
3750
+ #
3751
+ # ファイルを読み込み、パーサにセットする
3752
+ #
3753
+ # @param filePath ファイルパス
3754
+ # @param encoding エンコーディング
3755
+ #
3756
+ def read(filePath,encoding)
3757
+ super(filePath,encoding)
3758
+ analyzeML()
3759
+ end
3760
+
3761
+ #
3762
+ # ドキュメントをパースする
3763
+ #
3764
+ def analyzeML()
3765
+ #mixed_content-typeの取得
3766
+ analyzeContentType()
3767
+ #改行コードの取得
3768
+ analyzeKaigyoCode()
3769
+ @res = nil
3770
+ end
3771
+ private :analyzeML
3772
+
3773
+ #
3774
+ # コンテントタイプを取得する
3775
+ #
3776
+ # @return [String] コンテントタイプ
3777
+ #
3778
+ def contentType()
3779
+ @root.contentType
3780
+ end
3781
+
3782
+ #
3783
+ # ドキュメントをパースし、コンテントタイプをセットする
3784
+ #
3785
+ def analyzeContentType()
3786
+ @elm_ = element(META_S,HTTP_EQUIV,CONTENT_TYPE)
3787
+
3788
+ if !@elm_ then
3789
+ @elm_ = element(META,HTTP_EQUIV,CONTENT_TYPE)
3790
+ end
3791
+
3792
+ if @elm_ then
3793
+ @root.contentType = @elm_.attribute(CONTENT)
3794
+ else
3795
+ @root.contentType = EMPTY
3796
+ end
3797
+ end
3798
+ private :analyzeContentType
3799
+
3800
+ #
3801
+ # ドキュメントをパースし、改行コードをセットする
3802
+ #
3803
+ def analyzeKaigyoCode()
3804
+ #改行コード取得
3805
+ @pattern = Regexp.new(KAIGYO_CODE)
3806
+ @res = @pattern.match(@root.document)
3807
+
3808
+ if @res then
3809
+ @root.kaigyoCode = @res[1]
3810
+ end
3811
+ end
3812
+ private :analyzeKaigyoCode
3813
+
3814
+ def editAttributes_(elm,attrName,attrValue)
3815
+
3816
+ if isMatch(SELECTED, attrName) && isMatch(OPTION,elm.name) then
3817
+ editAttributes_5(elm,attrValue,@@pattern_selected_m,@@pattern_selected_r,SELECTED_U)
3818
+ elsif isMatch(MULTIPLE, attrName) && isMatch(SELECT,elm.name)
3819
+ editAttributes_5(elm,attrValue,@@pattern_multiple_m,@@pattern_multiple_r,MULTIPLE_U)
3820
+ elsif isMatch(DISABLED, attrName) && isMatch(DISABLE_ELEMENT, elm.name) then
3821
+ editAttributes_5(elm,attrValue,@@pattern_disabled_m,@@pattern_disabled_r,DISABLED_U)
3822
+ elsif isMatch(CHECKED, attrName) && isMatch(INPUT,elm.name) && isMatch(RADIO,getType(elm)) then
3823
+ editAttributes_5(elm,attrValue,@@pattern_checked_m,@@pattern_checked_r,CHECKED_U)
3824
+ elsif isMatch(READONLY, attrName) && (isMatch(TEXTAREA,elm.name) || (isMatch(INPUT,elm.name) && isMatch(READONLY_TYPE, getType(elm)))) then
3825
+ editAttributes_5(elm,attrValue,@@pattern_readonly_m,@@pattern_readonly_r,READONLY_U)
3826
+ else
3827
+ super(elm,attrName,attrValue)
3828
+ end
3829
+
3830
+ end
3831
+ private :editAttributes_
3832
+
3833
+ def editAttributes_5(elm,attrValue,match_p,replaceRegex,replaceUpdate)
3834
+
3835
+ #attrValue = escape(attrValue)
3836
+
3837
+ if isMatch(TRUE,attrValue) then
3838
+
3839
+ @res = match_p.match(elm.attributes)
3840
+
3841
+ if !@res then
3842
+ #属性文字列の最後に新規の属性を追加する
3843
+ if elm.attributes != EMPTY then
3844
+ elm.attributes = '' << SPACE << elm.attributes.strip
3845
+ #else
3846
+ end
3847
+ elm.attributes << SPACE << replaceUpdate
3848
+ else
3849
+ #属性の置換
3850
+ elm.attributes.gsub!(replaceRegex,replaceUpdate)
3851
+ end
3852
+ elsif isMatch(FALSE,attrValue) then
3853
+ #attrName属性が存在するなら削除
3854
+ #属性の置換
3855
+ elm.attributes.gsub!(replaceRegex, EMPTY)
3856
+ end
3857
+
3858
+ end
3859
+ private :editAttributes_5
3860
+
3861
+ def getAttributeValue_(elm,attrName)
3862
+ if isMatch(SELECTED, attrName) && isMatch(OPTION,elm.name) then
3863
+ getAttributeValue_2_r(elm,attrName,@@pattern_selected_m1)
3864
+ elsif isMatch(MULTIPLE, attrName) && isMatch(SELECT,elm.name)
3865
+ getAttributeValue_2_r(elm,attrName,@@pattern_multiple_m1)
3866
+ elsif isMatch(DISABLED, attrName) && isMatch(DISABLE_ELEMENT, elm.name) then
3867
+ getAttributeValue_2_r(elm,attrName,@@pattern_disabled_m1)
3868
+ elsif isMatch(CHECKED, attrName) && isMatch(INPUT,elm.name) && isMatch(RADIO, getType(elm)) then
3869
+ getAttributeValue_2_r(elm,attrName,@@pattern_checked_m1)
3870
+ elsif isMatch(READONLY, attrName) && (isMatch(TEXTAREA,elm.name) || (isMatch(INPUT,elm.name) && isMatch(READONLY_TYPE, getType(elm)))) then
3871
+ getAttributeValue_2_r(elm,attrName,@@pattern_readonly_m1)
3872
+ else
3873
+ super(elm,attrName)
3874
+ end
3875
+ end
3876
+ private :getAttributeValue_
3877
+
3878
+ def getType(elm)
3879
+ if !elm.type_value
3880
+ elm.type_value = getAttributeValue_2(elm, TYPE_L)
3881
+ if !elm.type_value then
3882
+ elm.type_value = getAttributeValue_2(elm, TYPE_U)
3883
+ end
3884
+ end
3885
+ elm.type_value
3886
+ end
3887
+ private :getType
3888
+
3889
+ def getAttributeValue_2_r(elm,attrName,match_p)
3890
+
3891
+ @res = match_p.match(elm.attributes)
3892
+
3893
+ if @res then
3894
+ if @res[1] then
3895
+ if attrName == @res[1] then
3896
+ TRUE
3897
+ else
3898
+ @res[1]
3899
+ end
3900
+ elsif @res[2] then
3901
+ if attrName == @res[2] then
3902
+ TRUE
3903
+ else
3904
+ @res[2]
3905
+ end
3906
+ elsif @res[3] then
3907
+ if attrName == @res[3] then
3908
+ TRUE
3909
+ else
3910
+ @res[3]
3911
+ end
3912
+ elsif @res[4] then
3913
+ if attrName == @res[4] then
3914
+ TRUE
3915
+ else
3916
+ @res[4]
3917
+ end
3918
+ end
3919
+ else
3920
+ FALSE
3921
+ end
3922
+ end
3923
+ private :getAttributeValue_2_r
3924
+
3925
+ #
3926
+ # 属性マップを取得する
3927
+ #
3928
+ # @param [Meteor::Element] elm 要素
3929
+ # @return [Meteor::AttributeMap] 属性マップ
3930
+ #
3931
+ def getAttributeMap_1(elm)
3932
+ attrs = Meteor::AttributeMap.new
3933
+
3934
+ elm.attributes.scan(@@pattern_get_attrs_map){ |a,b|
3935
+ if isMatch(ATTR_LOGIC,a) && a==b then
3936
+ attrs.store(a,TRUE)
3937
+ else
3938
+ attrs.store(a,unescape(b))
3939
+ end
3940
+ }
3941
+ attrs.recordable = true
3942
+
3943
+ attrs
3944
+ end
3945
+ private :getAttributeMap_1
3946
+
3947
+ def setMonoInfo(elm)
3948
+
3949
+ @res = @@pattern_set_mono1.match(elm.mixed_content)
3950
+
3951
+ if @res then
3952
+ elm.mono = true
3953
+ if elm.cx then
3954
+ @pattern_cc = '' << SET_CX_1 << elm.name << SPACE << elm.attributes << SET_CX_2 << elm.mixed_content << SET_CX_3 << elm.name << SET_CX_4
3955
+ else
3956
+ if elm.empty then
3957
+ @pattern_cc = '' << TAG_OPEN << elm.name << elm.attributes << TAG_CLOSE << elm.mixed_content << TAG_OPEN3 << elm.name << TAG_CLOSE
3958
+ else
3959
+ @pattern_cc = '' << TAG_OPEN << elm.name << elm.attributes << TAG_CLOSE3
3960
+ end
3961
+ end
3962
+ elm.document = @pattern_cc
3963
+ end
3964
+ end
3965
+ private :setMonoInfo
3966
+
3967
+ def escape(element)
3968
+ #特殊文字の置換
3969
+ #「&」->「&amp;」
3970
+ if element.include?(AND_1) then
3971
+ element.gsub!(@@pattern_and_1,AND_2)
3972
+ end
3973
+ #「<」->「&lt;」
3974
+ if element.include?(LT_1) then
3975
+ element.gsub!(@@pattern_lt_1,LT_2)
3976
+ end
3977
+ #「>」->「&gt;」
3978
+ if element.include?(GT_1) then
3979
+ element.gsub!(@@pattern_gt_1,GT_2)
3980
+ end
3981
+ #「"」->「&quotl」
3982
+ if element.include?(DOUBLE_QUATATION) then
3983
+ element.gsub!(@@pattern_dq_1,QO_2)
3984
+ end
3985
+ #「 」->「&nbsp;」
3986
+ if element.include?(SPACE) then
3987
+ element.gsub!(@@pattern_space_1,NBSP_2)
3988
+ end
3989
+
3990
+ element
3991
+ end
3992
+ private :escape
3993
+
3994
+ def escapeContent(element,elmName)
3995
+ element = escape(element)
3996
+
3997
+ if !isMatch(MATCH_TAG_2,elmName) then
3998
+ #「¥r?¥n」->「<br>」
3999
+ element.gsub!(@@pattern_br_1, BR_2)
4000
+ end
4001
+
4002
+ element
4003
+ end
4004
+ private :escapeContent
4005
+
4006
+ def unescape(element)
4007
+ #特殊文字の置換
4008
+ #「<」<-「&lt;」
4009
+ if element.include?(LT_2) then
4010
+ element.gsub!(@@pattern_lt_2,LT_1)
4011
+ end
4012
+ #「>」<-「&gt;」
4013
+ if element.include?(GT_2) then
4014
+ element.gsub!(@@pattern_gt_2,GT_1)
4015
+ end
4016
+ #「"」<-「&quotl」
4017
+ if element.include?(QO_2) then
4018
+ element.gsub!(@@pattern_dq_2,DOUBLE_QUATATION)
4019
+ end
4020
+ #「 」<-「&nbsp;」
4021
+ if element.include?(NBSP_2) then
4022
+ element.gsub!(@@pattern_space_2,SPACE)
4023
+ end
4024
+ #「&」<-「&amp;」
4025
+ if element.include?(AND_2) then
4026
+ element.gsub!(@@pattern_and_2,AND_1)
4027
+ end
4028
+
4029
+ element
4030
+ end
4031
+ private :unescape
4032
+
4033
+ def unescapeContent(element,elmName)
4034
+ element = unescape(element)
4035
+
4036
+ if !isMatch(MATCH_TAG_2,elmName) then
4037
+ #「<br>」->「¥r?¥n」
4038
+ if element.include?(BR_2) then
4039
+ element.gsub!(@@pattern_br_2, @root.kaigyoCode)
4040
+ end
4041
+ end
4042
+
4043
+ element
4044
+ end
4045
+ private :unescapeContent
4046
+
4047
+ end
4048
+ end
4049
+
4050
+ module Xml
4051
+
4052
+ #
4053
+ # XMLパーサ
4054
+ #
4055
+ class ParserImpl < Meteor::Core::Kernel
4056
+
4057
+ @@pattern_and_1 = Regexp.new(AND_1)
4058
+ @@pattern_lt_1 = Regexp.new(LT_1)
4059
+ @@pattern_gt_1 = Regexp.new(GT_1)
4060
+ @@pattern_dq_1 = Regexp.new(DOUBLE_QUATATION)
4061
+ @@pattern_ap_1 = Regexp.new(AP_1)
4062
+ @@pattern_lt_2 = Regexp.new(LT_2)
4063
+ @@pattern_gt_2 = Regexp.new(GT_2)
4064
+ @@pattern_dq_2 = Regexp.new(QO_2)
4065
+ @@pattern_ap_2 = Regexp.new(AP_2)
4066
+ @@pattern_and_2 = Regexp.new(AND_2)
4067
+
4068
+ @@pattern_set_mono1 = Regexp.new(SET_MONO_1)
4069
+
4070
+ #
4071
+ # イニシャライザ
4072
+ #
4073
+ # @param [Array] args 引数配列
4074
+ #
4075
+ def initialize(*args)
4076
+ super(args)
4077
+
4078
+ case args.length
4079
+ when 0
4080
+ initialize_0
4081
+ when 1
4082
+ initialize_1(args[0])
4083
+ else
4084
+ raise ArgumentError
4085
+ end
4086
+ end
4087
+
4088
+ #
4089
+ # イニシャライザ
4090
+ #
4091
+ def initialize_0
4092
+ end
4093
+
4094
+ #
4095
+ # イニシャライザ
4096
+ #
4097
+ # @param [Meteor::Parser] ps パーサ
4098
+ #
4099
+ def initialize_1(ps)
4100
+ @root.document = String.new(ps.document)
4101
+ @root.hookDocument = String.new(ps.hookDocument)
4102
+ @root.hook = ps.hook
4103
+ @root.monoHook = ps.monoHook
4104
+ @root.contentType = String.new(ps.contentType);
4105
+ end
4106
+
4107
+ #
4108
+ # ドキュメントをパーサにセットする
4109
+ #
4110
+ # @param [String] document ドキュメント
4111
+ #
4112
+ def parse(document)
4113
+ @root.document = document
4114
+ end
4115
+
4116
+ #
4117
+ # ファイルを読み込み、パーサにセットする
4118
+ #
4119
+ # @param filePath ファイルパス
4120
+ # @param encoding エンコーディング
4121
+ #
4122
+ def read(filePath,encoding)
4123
+ super(filePath, encoding)
4124
+ end
4125
+
4126
+ # コンテントタイプを取得する
4127
+ #
4128
+ # @return [Streing]コンテントタイプ
4129
+ #
4130
+ def contentType()
4131
+ @root.contentType
4132
+ end
4133
+
4134
+ def setMonoInfo(elm)
4135
+
4136
+ @res = @@pattern_set_mono1.match(elm.mixed_content)
4137
+
4138
+ if @res then
4139
+ elm.mono = true
4140
+ if elm.cx then
4141
+ @pattern_cc = '' << SET_CX_1 << elm.name << SPACE << elm.attributes << SET_CX_2 << elm.mixed_content << SET_CX_3 << elm.name << SET_CX_4
4142
+ else
4143
+ if elm.empty then
4144
+ @pattern_cc = '' << TAG_OPEN << elm.name << elm.attributes << TAG_CLOSE << elm.mixed_content << TAG_OPEN3 << elm.name << TAG_CLOSE
4145
+ else
4146
+ @pattern_cc = '' << TAG_OPEN << elm.name << elm.attributes << TAG_CLOSE3
4147
+ end
4148
+ end
4149
+ elm.document = @pattern_cc
4150
+ end
4151
+ end
4152
+ private :setMonoInfo
4153
+
4154
+ def escape(element)
4155
+ #特殊文字の置換
4156
+ #「&」->「&amp;」
4157
+ if element.include?(AND_1) then
4158
+ element.gsub!(@@pattern_and_1,AND_2)
4159
+ end
4160
+ #「<」->「&lt;」
4161
+ if element.include?(LT_1) then
4162
+ element.gsub!(@@pattern_lt_1,LT_2)
4163
+ end
4164
+ #「>」->「&gt;」
4165
+ if element.include?(GT_1) then
4166
+ element.gsub!(@@pattern_gt_1,GT_2)
4167
+ end
4168
+ #「"」->「&quot;」
4169
+ if element.include?(DOUBLE_QUATATION) then
4170
+ element.gsub!(@@pattern_dq_1,QO_2)
4171
+ end
4172
+ #「'」->「&apos;」
4173
+ if element.include?(AP_1) then
4174
+ element.gsub!(@@pattern_ap_1,AP_2)
4175
+ end
4176
+
4177
+ element
4178
+ end
4179
+ private :escape
4180
+
4181
+ def escapeContent(element,elmName)
4182
+ escape(element)
4183
+ end
4184
+ private :escapeContent
4185
+
4186
+ def unescape(element)
4187
+ #特殊文字の置換
4188
+ #「<」<-「&lt;」
4189
+ if element.include?(LT_2) then
4190
+ element.gsub!(@@pattern_lt_2,LT_1)
4191
+ end
4192
+ #「>」<-「&gt;」
4193
+ if element.include?(GT_2) then
4194
+ element.gsub!(@@pattern_gt_2,GT_1)
4195
+ end
4196
+ #「"」<-「&quot;」
4197
+ if element.include?(QO_2) then
4198
+ element.gsub!(@@pattern_dq_2,DOUBLE_QUATATION)
4199
+ end
4200
+ #「'」<-「&apos;」
4201
+ if element.include?(AP_2) then
4202
+ element.gsub!(@@pattern_ap_2,AP_1)
4203
+ end
4204
+ #「&」<-「&amp;」
4205
+ if element.include?(AND_2) then
4206
+ element.gsub!(@@pattern_and_2,AND_1)
4207
+ end
4208
+
4209
+ element
4210
+ end
4211
+ private :unescape
4212
+
4213
+ def unescapeContent(element,elmName)
4214
+ unescape(element)
4215
+ end
4216
+ private :unescapeContent
4217
+
4218
+ end
4219
+ end
4220
+ end
4221
+ end