Mercurial > pub > Impl
comparison lib/IMPL/Serialization/XmlFormatter.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
| author | cin |
|---|---|
| date | Fri, 04 Sep 2015 19:40:23 +0300 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 406:f23fcb19d3c1 | 407:c6e90e02dd17 |
|---|---|
| 1 package IMPL::Serialization::XmlObjectWriter; | |
| 2 use strict; | |
| 3 | |
| 4 use parent qw(IMPL::Object); | |
| 5 use IMPL::Class::Property; | |
| 6 | |
| 7 use IMPL::Serialization; | |
| 8 use XML::Writer; | |
| 9 use IMPL::Exception; | |
| 10 | |
| 11 sub CONTAINER_EMPTY () { 1 } | |
| 12 sub CONTAINER_NORMAL () { 2 } | |
| 13 | |
| 14 BEGIN { | |
| 15 public _direct property Encoding => prop_all; | |
| 16 public _direct property hOutput => prop_all; | |
| 17 public _direct property IdentOutput => prop_all; | |
| 18 | |
| 19 private _direct property CurrentObject => prop_all; | |
| 20 private _direct property ObjectPath => prop_all; | |
| 21 private _direct property XmlWriter => prop_all; | |
| 22 private _direct property IdentLevel => prop_all; | |
| 23 private _direct property IdentNextTag => prop_all; | |
| 24 } | |
| 25 | |
| 26 sub new { | |
| 27 my $class = shift; | |
| 28 my $self = bless {}, ref($class) || $class; | |
| 29 $self->CTOR(@_); | |
| 30 return $self; | |
| 31 } | |
| 32 | |
| 33 sub CTOR { | |
| 34 my $this = shift; | |
| 35 my %args = @_; | |
| 36 $this->{$hOutput} = $args{'hOutput'}; | |
| 37 $this->{$Encoding} = $args{'Encoding'}; | |
| 38 $this->{$CurrentObject} = undef; | |
| 39 $this->{$IdentOutput} = $args{'IdentOutput'}; | |
| 40 $this->{$IdentLevel} = 0; | |
| 41 $this->{$IdentNextTag} = 0; | |
| 42 #$this->{$ObjectPath} = []; | |
| 43 return 1; | |
| 44 } | |
| 45 | |
| 46 sub BeginObject { | |
| 47 my $this = shift; | |
| 48 my %args = @_; | |
| 49 | |
| 50 if (not $this->{$CurrentObject}) { | |
| 51 my $xmlWriter = new XML::Writer(OUTPUT => $this->{$hOutput}, ENCODING => $this->{$Encoding}); | |
| 52 $this->{$XmlWriter} = $xmlWriter; | |
| 53 $xmlWriter->xmlDecl(); | |
| 54 } | |
| 55 | |
| 56 push @{$this->{$ObjectPath}},$this->{$CurrentObject} if $this->{$CurrentObject}; | |
| 57 | |
| 58 my %ObjectProperties = %args; | |
| 59 delete $ObjectProperties{'name'}; | |
| 60 delete $args{'container_type'}; | |
| 61 | |
| 62 $this->{$CurrentObject} = \%ObjectProperties; | |
| 63 | |
| 64 my $tagname; | |
| 65 if (_CheckName($args{'name'})) { | |
| 66 $tagname = $args{'name'}; | |
| 67 } else { | |
| 68 $tagname = 'element'; | |
| 69 $ObjectProperties{'extname'} = $args{'name'}; | |
| 70 } | |
| 71 | |
| 72 if ($args{'refid'}) { | |
| 73 $this->{$XmlWriter}->characters("\n" . (' ' x $$this{$IdentLevel}) ) if $$this{$IdentNextTag}; | |
| 74 $this->{$XmlWriter}->emptyTag($tagname,%ObjectProperties); | |
| 75 $ObjectProperties{'container_type'} = CONTAINER_EMPTY; | |
| 76 } else { | |
| 77 $this->{$XmlWriter}->characters("\n" . (' ' x $$this{$IdentLevel}) ) if $$this{$IdentNextTag}; | |
| 78 $this->{$XmlWriter}->startTag($tagname,%ObjectProperties); | |
| 79 $ObjectProperties{'container_type'} = CONTAINER_NORMAL; | |
| 80 } | |
| 81 | |
| 82 $this->{$IdentLevel} ++; | |
| 83 $this->{$IdentNextTag} = $this->{$IdentOutput}; | |
| 84 | |
| 85 return 1; | |
| 86 } | |
| 87 | |
| 88 sub EndObject { | |
| 89 my $this = shift; | |
| 90 | |
| 91 my $hCurrentObject = $this->{$CurrentObject} or return 0; | |
| 92 | |
| 93 $this->{$IdentLevel} --; | |
| 94 | |
| 95 if ( $hCurrentObject->{'container_type'} != CONTAINER_EMPTY ) { | |
| 96 $this->{$XmlWriter}->characters("\n" . (' ' x $$this{$IdentLevel}) ) if $$this{$IdentNextTag}; | |
| 97 $this->{$XmlWriter}->endTag(); | |
| 98 } | |
| 99 | |
| 100 $this->{$IdentNextTag} = $this->{$IdentOutput}; | |
| 101 | |
| 102 $this->{$CurrentObject} = pop @{$this->{$ObjectPath}} if exists $this->{$ObjectPath}; | |
| 103 $this->{$XmlWriter} = undef if (not $this->{$CurrentObject}); | |
| 104 | |
| 105 return 1; | |
| 106 } | |
| 107 | |
| 108 sub SetData { | |
| 109 my $this = shift; | |
| 110 #my $hCurrentObject = $this->{$CurrentObject} or return 0; | |
| 111 | |
| 112 if ($this->{$CurrentObject}->{'container_type'} == CONTAINER_NORMAL) { | |
| 113 $this->{$XmlWriter}->characters($_[0]) if defined $_[0]; | |
| 114 $this->{$IdentNextTag} = 0; | |
| 115 return 1; | |
| 116 } else { | |
| 117 return 0; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 sub _CheckName { | |
| 122 return 0 if not $_[0]; | |
| 123 return $_[0] =~ /^(_|\w|\d)+$/; | |
| 124 } | |
| 125 | |
| 126 package IMPL::Serialization::XmlObjectReader; | |
| 127 use parent qw(XML::Parser); | |
| 128 | |
| 129 sub new { | |
| 130 my $class = shift; | |
| 131 my %args = @_; | |
| 132 die new Exception("Handler parameter is reqired") if not $args{'Handler'}; | |
| 133 die new Exception("Handler parameter must be a reference") if not ref $args{'Handler'}; | |
| 134 | |
| 135 #my $this = $class->SUPER::new(Style => 'Stream', Pkg => 'Serialization::XmlObjectReader', 'Non-Expat-Options' => {hInput => $args{'hInput'} , Handler => $args{'Handler'}, SkipWhitespace => $args{'SkipWhitespace'} } ); | |
| 136 my $this = $class->SUPER::new(Handlers => { Start => \&StartTag, End => \&EndTag, Char => \&Text} , 'Non-Expat-Options' => {hInput => $args{'hInput'} , Handler => $args{'Handler'}, SkipWhitespace => $args{'SkipWhitespace'} } ); | |
| 137 return $this; | |
| 138 } | |
| 139 | |
| 140 sub Parse { | |
| 141 my $this = shift; | |
| 142 $this->parse($this->{'Non-Expat-Options'}->{'hInput'}); | |
| 143 return 1; | |
| 144 } | |
| 145 | |
| 146 sub StartTag { | |
| 147 my $this = shift; | |
| 148 my $name = shift; | |
| 149 my %Attr = @_; | |
| 150 $name = $Attr{'extname'} if defined $Attr{'extname'}; | |
| 151 $this->{'Non-Expat-Options'}->{'Handler'}->OnObjectBegin($name,\%Attr); | |
| 152 return 1; | |
| 153 } | |
| 154 | |
| 155 sub EndTag { | |
| 156 my ($this,$name) = @_; | |
| 157 $this->{'Non-Expat-Options'}->{'Handler'}->OnObjectEnd($name); | |
| 158 return 1; | |
| 159 } | |
| 160 | |
| 161 sub Text { | |
| 162 my ($this) = shift; | |
| 163 my $text = shift; | |
| 164 return 1 if $this->{'Non-Expat-Options'}->{'SkipWhitespace'} and $text =~ /^\n*\s*\n*$/; | |
| 165 $this->{'Non-Expat-Options'}->{'Handler'}->OnObjectData($text); | |
| 166 return 1; | |
| 167 } | |
| 168 | |
| 169 package IMPL::Serialization::XmlFormatter; | |
| 170 use parent qw(IMPL::Object); | |
| 171 | |
| 172 use IMPL::Class::Property; | |
| 173 | |
| 174 BEGIN { | |
| 175 public _direct property Encoding => prop_all; | |
| 176 public _direct property SkipWhitespace => prop_all; | |
| 177 public _direct property IdentOutput => prop_all; | |
| 178 } | |
| 179 | |
| 180 sub CTOR { | |
| 181 my ($this,%args) = @_; | |
| 182 | |
| 183 $this->Encoding($args{'Encoding'} || 'utf-8'); | |
| 184 $this->SkipWhitespace($args{'SkipWhitespace'}); | |
| 185 $this->IdentOutput($args{'IdentOutput'}); | |
| 186 | |
| 187 return 1; | |
| 188 } | |
| 189 | |
| 190 sub CreateWriter { | |
| 191 my ($this,$hStream) = @_; | |
| 192 return new IMPL::Serialization::XmlObjectWriter(Encoding =>$this->Encoding() , hOutput => $hStream, IdentOutput => $this->IdentOutput()); | |
| 193 } | |
| 194 | |
| 195 sub CreateReader { | |
| 196 my ($this,$hStream,$refHandler) = @_; | |
| 197 return new IMPL::Serialization::XmlObjectReader(hInput => $hStream, Handler => $refHandler, SkipWhitespace => $this->SkipWhitespace()); | |
| 198 } | |
| 199 | |
| 200 1; |
