| File: | lib/XML/Parser/Lite/Tree/XPath/Result.pm |
| Coverage: | 96.3% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package XML::Parser::Lite::Tree::XPath::Result; | |||||
| 2 | ||||||
| 3 | 34 34 34 | 120 56 127 | use strict; | |||
| 4 | 34 34 34 | 155 52 334 | use Data::Dumper; | |||
| 5 | ||||||
| 6 | # | |||||
| 7 | # types: | |||||
| 8 | # | |||||
| 9 | # Error - value is error message string | |||||
| 10 | # number - value is numeric scalar | |||||
| 11 | # boolean - value is boolean scalar | |||||
| 12 | # string - value is string scalar | |||||
| 13 | # nodeset - value is arrayref of nodes and/or attributes | |||||
| 14 | # node - value is node | |||||
| 15 | # attribute - value is attribute | |||||
| 16 | # | |||||
| 17 | ||||||
| 18 | sub new { | |||||
| 19 | 1691 | 4031 | my $class = shift; | |||
| 20 | 1691 | 6054 | my $self = bless {}, $class; | |||
| 21 | ||||||
| 22 | 1691 | 5570 | $self->{type} = shift; | |||
| 23 | 1691 | 5155 | $self->{value} = shift; | |||
| 24 | ||||||
| 25 | 1691 | 6686 | return $self; | |||
| 26 | } | |||||
| 27 | ||||||
| 28 | sub is_error { | |||||
| 29 | 3823 | 9234 | my ($self) = @_; | |||
| 30 | 3823 | 20587 | return ($self->{type} eq 'Error') ? 1 : 0; | |||
| 31 | } | |||||
| 32 | ||||||
| 33 | sub normalize { | |||||
| 34 | 288 | 765 | my ($self) = @_; | |||
| 35 | ||||||
| 36 | 288 | 1139 | if ($self->{type} eq 'nodeset'){ | |||
| 37 | ||||||
| 38 | # uniquify and sort | |||||
| 39 | 288 | 637 | my %seen = (); | |||
| 40 | 1703 | 5594 | my @tags = sort { | |||
| 41 | 1107 | 4418 | $a->{order} <=> $b->{order} | |||
| 42 | } grep { | |||||
| 43 | 288 | 1014 | ! $seen{$_->{order}} ++ | |||
| 44 | 288 | 582 | } @{$self->{value}}; | |||
| 45 | ||||||
| 46 | 288 | 2218 | $self->{value} = \@tags; | |||
| 47 | } | |||||
| 48 | } | |||||
| 49 | ||||||
| 50 | sub ret { | |||||
| 51 | 145 | 496 | my ($self, $a, $b) = @_; | |||
| 52 | 145 | 584 | return XML::Parser::Lite::Tree::XPath::Result->new($a, $b); | |||
| 53 | } | |||||
| 54 | ||||||
| 55 | sub get_type { | |||||
| 56 | 179 | 467 | my ($self, $type) = @_; | |||
| 57 | ||||||
| 58 | 179 | 438 | return $self if $self->is_error; | |||
| 59 | ||||||
| 60 | 179 | 707 | return $self->get_number if $type eq 'number'; | |||
| 61 | 46 | 171 | return $self->get_boolean if $type eq 'boolean'; | |||
| 62 | 23 | 70 | return $self->get_string if $type eq 'string'; | |||
| 63 | 22 | 98 | return $self->get_nodeset if $type eq 'nodeset'; | |||
| 64 | 3 | 11 | return $self->get_node if $type eq 'node'; | |||
| 65 | ||||||
| 66 | 2 | 9 | return $self->ret('Error', "Can't get type '$type'"); | |||
| 67 | } | |||||
| 68 | ||||||
| 69 | sub get_boolean { | |||||
| 70 | 36 | 86 | my ($self) = @_; | |||
| 71 | ||||||
| 72 | 36 | 187 | return $self if $self->{type} eq 'boolean'; | |||
| 73 | 12 | 35 | return $self if $self->is_error; | |||
| 74 | ||||||
| 75 | 11 | 42 | if ($self->{type} eq 'number'){ | |||
| 76 | 3 | 14 | return $self->ret('boolean', 0) if $self->{value} eq 'NaN'; | |||
| 77 | 2 | 10 | return $self->ret('boolean', $self->{value} != 0); | |||
| 78 | } | |||||
| 79 | ||||||
| 80 | 8 | 32 | if ($self->{type} eq 'string'){ | |||
| 81 | 2 | 10 | return $self->ret('boolean', length $self->{value} > 0); | |||
| 82 | } | |||||
| 83 | ||||||
| 84 | 6 | 22 | if ($self->{type} eq 'nodeset'){ | |||
| 85 | 4 4 | 9 17 | return $self->ret('boolean', scalar(@{$self->{value}}) > 0); | |||
| 86 | } | |||||
| 87 | ||||||
| 88 | 2 | 8 | if ($self->{type} eq 'node'){ | |||
| 89 | # todo | |||||
| 90 | } | |||||
| 91 | ||||||
| 92 | 2 | 12 | return $self->ret('Error', "can't convert type $self->{type} to boolean"); | |||
| 93 | } | |||||
| 94 | ||||||
| 95 | sub get_string { | |||||
| 96 | 128 | 314 | my ($self) = @_; | |||
| 97 | ||||||
| 98 | 128 | 617 | return $self if $self->{type} eq 'string'; | |||
| 99 | 20 | 54 | return $self if $self->is_error; | |||
| 100 | ||||||
| 101 | ||||||
| 102 | 19 | 73 | if ($self->{type} eq 'nodeset'){ | |||
| 103 | 3 3 | 5 13 | return $self->ret('string', '') unless scalar @{$self->{value}}; | |||
| 104 | ||||||
| 105 | 2 | 9 | my $node = $self->ret('node', $self->{value}->[0]); | |||
| 106 | ||||||
| 107 | 2 | 12 | return $node->get_string; | |||
| 108 | } | |||||
| 109 | ||||||
| 110 | 16 | 59 | if ($self->{type} eq 'node'){ | |||
| 111 | ||||||
| 112 | 7 | 51 | return $self->ret('string', $self->{value}->{value}) if $self->{value}->{type} eq 'attribute'; | |||
| 113 | ||||||
| 114 | 0 | 0 | die "can't convert a node of type $self->{value}->{type} to a string"; | |||
| 115 | } | |||||
| 116 | ||||||
| 117 | 9 | 35 | if ($self->{type} eq 'number'){ | |||
| 118 | 5 | 26 | return $self->ret('string', "$self->{value}"); | |||
| 119 | } | |||||
| 120 | ||||||
| 121 | 4 | 15 | if ($self->{type} eq 'boolean'){ | |||
| 122 | 2 | 11 | return $self->ret('string', $self->{value} ? 'true' : 'false'); | |||
| 123 | } | |||||
| 124 | ||||||
| 125 | 2 | 12 | return $self->ret('Error', "can't convert type $self->{type} to string"); | |||
| 126 | } | |||||
| 127 | ||||||
| 128 | sub get_nodeset { | |||||
| 129 | 166 | 408 | my ($self) = @_; | |||
| 130 | ||||||
| 131 | 166 | 722 | return $self if $self->{type} eq 'nodeset'; | |||
| 132 | 100 | 243 | return $self if $self->is_error; | |||
| 133 | ||||||
| 134 | 99 | 379 | if ($self->{type} eq 'node'){ | |||
| 135 | 94 | 432 | return $self->ret('nodeset', [$self->{value}]); | |||
| 136 | } | |||||
| 137 | ||||||
| 138 | 5 | 24 | return $self->ret('Error', "can't convert type $self->{type} to nodeset"); | |||
| 139 | } | |||||
| 140 | ||||||
| 141 | sub get_node { | |||||
| 142 | 6 | 16 | my ($self) = @_; | |||
| 143 | ||||||
| 144 | 6 | 22 | return $self if $self->{type} eq 'node'; | |||
| 145 | 6 | 15 | return $self if $self->is_error; | |||
| 146 | ||||||
| 147 | 5 | 25 | return $self->ret('Error', "can't convert type $self->{type} to node"); | |||
| 148 | } | |||||
| 149 | ||||||
| 150 | sub get_number { | |||||
| 151 | 167 | 394 | my ($self) = @_; | |||
| 152 | ||||||
| 153 | 167 | 901 | return $self if $self->{type} eq 'number'; | |||
| 154 | 10 | 27 | return $self if $self->is_error; | |||
| 155 | ||||||
| 156 | 9 | 40 | if ($self->{type} eq 'string'){ | |||
| 157 | 5 | 38 | if ($self->{value} =~ m!^[\x20\x09\x0D\x0A]*(-?([0-9]+(\.([0-9]+)?)?)|(\.[0-9]+))[\x20\x09\x0D\x0A]*$!){ | |||
| 158 | ||||||
| 159 | 4 | 13 | return $self->ret('number', $1); | |||
| 160 | }else{ | |||||
| 161 | 1 | 4 | return $self->ret('number', 'NaN'); | |||
| 162 | } | |||||
| 163 | } | |||||
| 164 | ||||||
| 165 | 4 | 15 | if ($self->{type} eq 'boolean'){ | |||
| 166 | 2 | 14 | return $self->ret('number', $self->{value}?1:0); | |||
| 167 | } | |||||
| 168 | ||||||
| 169 | 2 | 12 | return $self->ret('Error', "can't convert type $self->{type} to number"); | |||
| 170 | } | |||||
| 171 | ||||||
| 172 | 1; | |||||