Mercurial > pub > Impl
annotate Lib/IMPL/DOM/XMLReader.pm @ 387:4cc6cc370fb2
DOM refactoring
author | sergey |
---|---|
date | Tue, 11 Feb 2014 01:13:47 +0400 |
parents | 4edd36025051 |
children | 5aff94ba842f |
rev | line source |
---|---|
49 | 1 package IMPL::DOM::XMLReader; |
2 use strict; | |
3 use warnings; | |
4 | |
166 | 5 use parent qw(IMPL::Object IMPL::Object::Autofill); |
263 | 6 |
49 | 7 use IMPL::Class::Property; |
8 use XML::Parser; | |
263 | 9 |
10 use IMPL::require { | |
11 Schema => 'IMPL::DOM::Schema', # IMPL::DOM::Schema references IMPL::DOM::XML::Reader | |
12 Builder => 'IMPL::DOM::Navigator::Builder', | |
13 SimpleBuilder => 'IMPL::DOM::Navigator::SimpleBuilder' | |
14 }; | |
49 | 15 |
16 __PACKAGE__->PassThroughArgs; | |
17 | |
18 BEGIN { | |
19 public _direct property Navigator => prop_get | owner_set; | |
152 | 20 public _direct property SkipWhitespace => prop_get | owner_set; |
49 | 21 private _direct property _current => prop_all; |
22 private _direct property _text => prop_all; | |
23 private _direct property _textHistory => prop_all; | |
24 } | |
25 | |
26 sub Parse { | |
27 my ($this,$in) = @_; | |
28 | |
29 my $parser = new XML::Parser( | |
30 Handlers => { | |
31 Start => sub {shift; goto &OnStart($this,@_)}, | |
32 End => sub {shift; goto &OnEnd($this,@_)}, | |
33 Char => sub {shift; goto &OnChar($this,@_)} | |
34 } | |
35 ); | |
36 | |
37 $parser->parse($in); | |
38 } | |
39 | |
40 sub ParseFile { | |
41 my ($this,$in) = @_; | |
42 | |
43 my $parser = new XML::Parser( | |
44 Handlers => { | |
45 Start => sub {shift; unshift @_, $this; goto &_OnBegin;}, | |
46 End => sub {shift; unshift @_, $this; goto &_OnEnd;}, | |
47 Char => sub {shift; unshift @_, $this; goto &_OnChar;} | |
48 } | |
49 ); | |
50 | |
51 $parser->parsefile($in); | |
52 } | |
53 | |
54 sub _OnBegin { | |
55 my ($this,$element,%attrs) = @_; | |
56 | |
57 push @{$this->{$_textHistory}},$this->{$_text}; | |
58 $this->{$_text} = ""; | |
59 $this->{$_current} = $this->Navigator->NavigateCreate($element,%attrs); | |
60 } | |
61 | |
62 sub _OnEnd { | |
63 my ($this,$element) = @_; | |
384 | 64 $this->{$_current}->nodeValue($this->{$_text}) if length $this->{$_text} and (not $this->{$SkipWhitespace} or $this->{$_text} =~ /\S/); |
49 | 65 $this->{$_text} = pop @{$this->{$_textHistory}}; |
66 $this->{$_current} = $this->Navigator->Back; | |
67 } | |
68 | |
69 sub _OnChar { | |
70 my ($this,$val) = @_; | |
71 $this->{$_text} .= $val; | |
72 } | |
73 | |
104
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
74 sub LoadDocument { |
194 | 75 my ($self,$file,$schema) = @_; |
76 | |
77 my $parser; | |
78 if ($schema) { | |
79 $schema = IMPL::DOM::Schema->LoadSchema($schema) if not ref $schema; | |
80 $parser = $self->new( | |
81 Navigator => IMPL::DOM::Navigator::Builder->new( | |
82 'IMPL::DOM::Document', | |
83 $schema | |
84 ) | |
85 ); | |
86 } else { | |
87 $parser = $self->new( | |
88 Navigator => IMPL::DOM::Navigator::SimpleBuilder->new() | |
89 ); | |
90 } | |
91 | |
92 $parser->ParseFile($file); | |
93 my $doc = $parser->Navigator->Document; | |
368 | 94 my @errors; |
194 | 95 if ($schema) { |
368 | 96 @errors = $parser->Navigator->BuildErrors; |
194 | 97 push @errors, $schema->Validate($doc); |
98 } | |
368 | 99 |
100 if (wantarray) { | |
101 return $doc,\@errors; | |
102 } else { | |
103 die new IMPL::Exception("Loaded document doesn't match the schema", @errors) if @errors; | |
104 return $doc; | |
105 } | |
104
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
106 } |
196bf443b5e1
DOM::Schema RC0 inflators support, validation and some other things,
wizard
parents:
103
diff
changeset
|
107 |
49 | 108 1; |
109 | |
110 __END__ | |
111 | |
112 =pod | |
113 | |
114 =head1 SYNOPSIS | |
115 | |
116 my $reader = new IMPL::DOM::XMLReader(Navigator => $DomBuilder); | |
117 my $obj = $reader->parsefile("data.xml"); | |
118 | |
119 =head1 DESCRIPTION | |
120 | |
180 | 121 Простой класс, использующий навигатор для постороения документа. В зависимости от |
122 используемого навигатора может быть получен различный результат. | |
49 | 123 |
180 | 124 Навигатор должен поодерживать методы C<NavigateCreate> и C<Back> |
49 | 125 |
126 =head1 METHODS | |
127 | |
128 =over | |
129 | |
130 =item C<CTOR(Naviagtor => $builder)> | |
131 | |
180 | 132 Создает новый экземпляр парсера, с указанным навигатором для построения документа |
49 | 133 |
134 =item C<$obj->Parse($in)> | |
135 | |
180 | 136 Строит документ. На вход получает либо xml строку, либо HANDLE. |
49 | 137 |
138 =item C<$obj->ParseFile($fileName)> | |
139 | |
180 | 140 Строит документ из файла с именем C<$fileName>. |
49 | 141 |
142 =back | |
143 | |
144 =cut |