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