File Coverage

blib/lib/WebService/Ares/Standard.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package WebService::Ares::Standard;
2              
3             # Pragmas.
4 4     4   114443 use base qw(Exporter);
  4         7  
  4         433  
5 4     4   23 use strict;
  4         9  
  4         121  
6 4     4   21 use warnings;
  4         19  
  4         128  
7              
8             # Modules.
9 4     4   3160 use English;
  4         13755  
  4         26  
10 4     4   4879 use Error::Pure qw(err);
  4         27293  
  4         124  
11 4     4   214 use Readonly;
  4         11  
  4         223  
12 4     4   252043 use XML::Parser;
  0            
  0            
13              
14             # Constants.
15             Readonly::Array our @EXPORT_OK => qw(parse);
16             Readonly::Scalar my $EMPTY_STR => q{};
17              
18             # Version.
19             our $VERSION = 0.01;
20              
21             # Parse XML string.
22             sub parse {
23             my $xml = shift;
24              
25             # XML::Parser object.
26             my $data_hr = {};
27             my $parser = XML::Parser->new(
28             'Handlers' => {
29             'Start' => \&_xml_tag_start,
30             'End' => \&_xml_tag_end,
31             'Char' => \&_xml_char,
32             },
33             'Non-Expat-Options' => {
34             'data' => $data_hr,
35             'stack' => [],
36             },
37             );
38              
39             # Parse.
40             eval {
41             $parser->parse($xml);
42             };
43             if ($EVAL_ERROR) {
44             my $err = $EVAL_ERROR;
45             $err =~ s/^\n+//msg;
46             chomp $err;
47             err 'Cannot parse XML string.',
48             'XML::Parser error', $err;
49             }
50              
51             # Return structure.
52             return $data_hr;
53             }
54              
55             # Parsed data stack check function.
56             sub _check_stack {
57             my ($expat, $tag) = @_;
58             my $stack_ar = $expat->{'Non-Expat-Options'}->{'stack'};
59             foreach my $i (reverse (0 .. $#{$stack_ar})) {
60             if ($stack_ar->[$i]->{'tag'} eq $tag) {
61             return $stack_ar->[$i]->{'attr'};
62             }
63             }
64             return;
65             }
66              
67             # Parsed data stack peek function.
68             sub _peek_stack {
69             my $expat = shift;
70             if (defined $expat->{'Non-Expat-Options'}->{'stack'}->[-1]) {
71             my $tmp_hr = $expat->{'Non-Expat-Options'}->{'stack'}->[-1];
72             return ($tmp_hr->{'tag'}, $tmp_hr->{'attr'});
73             } else {
74             return ($EMPTY_STR, {});
75             }
76             }
77              
78             # Parsed data stack pop function.
79             sub _pop_stack {
80             my $expat = shift;
81             my $tmp_hr = pop @{$expat->{'Non-Expat-Options'}->{'stack'}};
82             return ($tmp_hr->{'tag'}, $tmp_hr->{'attr'});
83             }
84              
85             # Parsed data stack push function.
86             sub _push_stack {
87             my ($expat, $tag, $attr) = @_;
88             my $tmp_hr = {};
89             $tmp_hr->{'tag'} = $tag;
90             $tmp_hr->{'attr'} = $attr;
91             push @{$expat->{'Non-Expat-Options'}->{'stack'}}, $tmp_hr;
92             return;
93             }
94              
95             # Characters handler.
96             sub _xml_char {
97             my ($expat, $text) = @_;
98              
99             # Drop empty strings.
100             if ($text =~ m/^\s*$/sm) {
101             return;
102             }
103              
104             # Get actual tag name.
105             my ($tag_name) = _peek_stack($expat);
106              
107             # Process data.
108             if ($tag_name eq 'are:ICO') {
109             _save($expat, $text, 'ic');
110             } elsif ($tag_name eq 'are:Obchodni_firma') {
111             _save($expat, $text, 'company');
112             } elsif ($tag_name eq 'are:Datum_vzniku') {
113             _save($expat, $text, 'create_date');
114             } elsif ($tag_name eq 'dtt:Nazev_ulice') {
115             _save_address($expat, $text, 'street');
116             } elsif ($tag_name eq 'dtt:PSC') {
117             _save_address($expat, $text, 'psc');
118             } elsif ($tag_name eq 'dtt:Cislo_domovni') {
119             _save_address($expat, $text, 'num');
120             } elsif ($tag_name eq 'dtt:Cislo_orientacni') {
121             _save_address($expat, $text, 'num2');
122             } elsif ($tag_name eq 'dtt:Nazev_obce') {
123             _save_address($expat, $text, 'town');
124             } elsif ($tag_name eq 'dtt:Nazev_casti_obce') {
125             _save_address($expat, $text, 'town_part');
126             } elsif ($tag_name eq 'dtt:Nazev_mestske_casti') {
127             _save_address($expat, $text, 'town_urban');
128             } elsif ($tag_name eq 'dtt:Nazev_okresu') {
129             _save_address($expat, $text, 'district');
130             }
131              
132             return;
133             }
134              
135             # End tags handler.
136             sub _xml_tag_end {
137             my ($expat, $tag_name) = @_;
138             _pop_stack($expat);
139             return;
140             }
141              
142             # Start tags handler.
143             sub _xml_tag_start {
144             my ($expat, $tag_name, @params) = @_;
145             _push_stack($expat, $tag_name, {});
146             return;
147             }
148              
149             # Save common data.
150             sub _save {
151             my ($expat, $text, $key) = @_;
152              
153             # Data.
154             my $data_hr = $expat->{'Non-Expat-Options'}->{'data'};
155              
156             # Save text.
157             $data_hr->{$key} = $text;
158              
159             return;
160             }
161              
162             # Save address data.
163             sub _save_address {
164             my ($expat, $text, $key) = @_;
165              
166             # Data.
167             my $data_hr = $expat->{'Non-Expat-Options'}->{'data'};
168              
169             # Save text.
170             $data_hr->{'address'}->{$key} = $text;
171              
172             return;
173             }
174              
175             1;
176              
177             __END__