File Coverage

blib/lib/SGML/PYX.pm
Criterion Covered Total %
statement 78 79 98.7
branch 23 24 95.8
condition 6 6 100.0
subroutine 12 12 100.0
pod 2 2 100.0
total 121 123 98.3


line stmt bran cond sub pod time code
1             package SGML::PYX;
2              
3 12     12   406237 use strict;
  12         109  
  12         344  
4 12     12   60 use warnings;
  12         23  
  12         329  
5              
6 12     12   1639 use Class::Utils qw(set_params);
  12         90847  
  12         510  
7 12     12   7791 use Encode qw(encode_utf8);
  12         128520  
  12         805  
8 12     12   88 use Error::Pure qw(err);
  12         34  
  12         448  
9 12     12   6257 use Tag::Reader::Perl;
  12         28832  
  12         446  
10 12     12   5336 use PYX qw(comment end_element char instruction start_element);
  12         98952  
  12         218  
11 12     12   1045 use PYX::Utils qw(decode entity_decode);
  12         23  
  12         18673  
12              
13             our $VERSION = 0.05;
14              
15             # Constructor.
16             sub new {
17 44     44 1 30974 my ($class, @params) = @_;
18              
19             # Create object.
20 44         114 my $self = bless {}, $class;
21              
22             # Output callback.
23             $self->{'output'} = sub {
24 48     48   1221 my (@data) = @_;
25              
26 48         105 print join "\n", map { encode_utf8($_) } @data;
  77         346  
27 48         2413 print "\n";
28              
29 48         262 return;
30 44         275 };
31              
32             # Process params.
33 44         181 set_params($self, @params);
34              
35             # Object.
36 44         431 $self->{'_tag_reader'} = Tag::Reader::Perl->new;
37              
38             # Object.
39 44         1203 return $self;
40             }
41              
42             # Parse file.
43             sub parsefile {
44 43     43 1 37164 my ($self, $sgml_file) = @_;
45              
46             # Set file.
47 43         173 $self->{'_tag_reader'}->set_file($sgml_file);
48              
49             # Process.
50 43         3946 while (my ($data, $tag_type, $line, $column)
51             = $self->{'_tag_reader'}->gettoken) {
52              
53             # Data.
54 45 100       35772 if ($tag_type eq '!data') {
    100          
    100          
    100          
    100          
    100          
    50          
55 3         29 $self->{'output'}->(char(decode(entity_decode($data))));
56              
57             # Comment.
58             } elsif ($tag_type eq '!--') {
59 2         22 $data =~ s/^$//ms;
61 2         14 $self->{'output'}->(comment($data));
62              
63             # End of element.
64             } elsif ($tag_type =~ m/^\//ms) {
65 3         16 my $element = $data;
66 3         30 $element =~ s/^<\///ms;
67 3         16 $element =~ s/>$//ms;
68 3         12 $self->{'output'}->(end_element($element));
69              
70             # Begin of element.
71             } elsif ($tag_type =~ m/^\w+/ms) {
72 29         155 $data =~ s/^
73 29         162 $data =~ s/>$//ms;
74 29         54 my $end = 0;
75 29 100       73 if ($data =~ s/\/$//ms) {
76 5         9 $end = 1;
77             }
78 29         147 (my $element, $data) = ($data =~ m/^([^\s]+)\s*(.*?)$/ms);
79 29         77 my @attrs = $self->_parse_attributes($data);
80 28         84 $self->{'output'}->(start_element($element, @attrs));
81 28 100       177 if ($end) {
82 5         20 $self->{'output'}->(end_element($element));
83             }
84              
85             # Doctype.
86             } elsif ($tag_type eq '!doctype') {
87             # Nop.
88              
89             # CData.
90             } elsif ($tag_type eq '![cdata[') {
91 4         43 $data =~ s/^
92 4         31 $data =~ s/\]\]>$//ms;
93 4         19 $self->{'output'}->(char(decode(entity_decode($data))));
94              
95             # Instruction.
96             } elsif ($tag_type =~ m/^\?/ms) {
97 3         56 $data =~ s/^<\?//ms;
98 3         29 $data =~ s/\s*\?>$//ms;
99 3         20 my ($target, $code) = split m/\s+/ms, $data, 2;
100 3         17 $self->{'output'}->(instruction($target, $code));
101              
102             } else {
103 0         0 err "Unsupported tag type '$tag_type'.";
104             }
105             }
106              
107 42         1768 return;
108             }
109              
110             # Parse attributes.
111             sub _parse_attributes {
112 29     29   58 my ($self, $data) = @_;
113              
114 29         45 my $original_data = $data;
115 29         40 my @attrs;
116 29         57 while ($data) {
117              
118             # or
119 30 100 100     287 if ($data =~ m/^([_\w:][\.\-\w:]*)\s*=\s*"(.*?)"\s*(.*?)$/ms
    100 100        
    100          
120              
121             # or
122             || $data =~ m/^([_\w:][\.\-\w:]*)\s*=\s*'(.*?)'\s*(.*?)$/ms
123              
124             # or .
125             || $data =~ m/^([_\w:][\.\-\w:]*)\s*=\s*([^\s]+)\s*(.*?)$/ms) {
126              
127 22         75 push @attrs, $1, $2;
128 22         55 $data = $3;
129              
130             #
131             } elsif ($data =~ m/^([_\w:][\.\-\w:]*)\s*=\s*$/ms) {
132 3         12 push @attrs, $1, '';
133 3         8 $data = '';
134              
135             #
136             } elsif ($data =~ m/^([_\w:][\.\-\w:]*)\s*(.*?)$/ms) {
137 4         12 push @attrs, $1, $1;
138 4         9 $data = $2;
139             } else {
140 1         5 err 'Problem with attribute parsing.',
141             'data', $original_data;
142             }
143             }
144              
145 28         89 return (@attrs);
146             }
147              
148             1;
149              
150             __END__