| File | /usr/local/lib/perl5/site_perl/5.10.1/XML/SAX/ParserFactory.pm |
| Statements Executed | 109 |
| Statement Execution Time | 1.45ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 3 | 1 | 1 | 686µs | 36.9ms | XML::SAX::ParserFactory::parser |
| 1 | 1 | 1 | 638µs | 852µs | XML::SAX::ParserFactory::BEGIN@12 |
| 18 | 1 | 2 | 231µs | 231µs | XML::SAX::ParserFactory::CORE:open (opcode) |
| 3 | 1 | 1 | 203µs | 554µs | XML::SAX::ParserFactory::_parser_class |
| 3 | 1 | 1 | 47µs | 675µs | XML::SAX::ParserFactory::new |
| 1 | 1 | 1 | 20µs | 24µs | XML::SAX::ParserFactory::BEGIN@5 |
| 1 | 1 | 1 | 11µs | 42µs | XML::SAX::ParserFactory::BEGIN@10 |
| 1 | 1 | 1 | 10µs | 10µs | XML::SAX::ParserFactory::BEGIN@11 |
| 1 | 1 | 1 | 9µs | 35µs | XML::SAX::ParserFactory::BEGIN@6 |
| 3 | 1 | 2 | 3µs | 3µs | XML::SAX::ParserFactory::CORE:subst (opcode) |
| 0 | 0 | 0 | 0s | 0s | XML::SAX::ParserFactory::require_feature |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | # $Id: ParserFactory.pm,v 1.14 2008-08-04 04:51:29 grant Exp $ | ||||
| 2 | |||||
| 3 | package XML::SAX::ParserFactory; | ||||
| 4 | |||||
| 5 | 3 | 39µs | 2 | 27µs | # spent 24µs (20+4) within XML::SAX::ParserFactory::BEGIN@5 which was called
# once (20µs+4µs) by XML::SAX::BEGIN@18 at line 5 # spent 24µs making 1 call to XML::SAX::ParserFactory::BEGIN@5
# spent 4µs making 1 call to strict::import |
| 6 | 3 | 39µs | 2 | 60µs | # spent 35µs (9+25) within XML::SAX::ParserFactory::BEGIN@6 which was called
# once (9µs+25µs) by XML::SAX::BEGIN@18 at line 6 # spent 35µs making 1 call to XML::SAX::ParserFactory::BEGIN@6
# spent 25µs making 1 call to vars::import |
| 7 | |||||
| 8 | 1 | 800ns | $VERSION = '1.01'; | ||
| 9 | |||||
| 10 | 3 | 30µs | 2 | 73µs | # spent 42µs (11+31) within XML::SAX::ParserFactory::BEGIN@10 which was called
# once (11µs+31µs) by XML::SAX::BEGIN@18 at line 10 # spent 42µs making 1 call to XML::SAX::ParserFactory::BEGIN@10
# spent 31µs making 1 call to Exporter::import |
| 11 | 3 | 31µs | 1 | 10µs | # spent 10µs within XML::SAX::ParserFactory::BEGIN@11 which was called
# once (10µs+0s) by XML::SAX::BEGIN@18 at line 11 # spent 10µs making 1 call to XML::SAX::ParserFactory::BEGIN@11 |
| 12 | 3 | 623µs | 1 | 852µs | # spent 852µs (638+214) within XML::SAX::ParserFactory::BEGIN@12 which was called
# once (638µs+214µs) by XML::SAX::BEGIN@18 at line 12 # spent 852µs making 1 call to XML::SAX::ParserFactory::BEGIN@12 |
| 13 | |||||
| 14 | # spent 675µs (47+628) within XML::SAX::ParserFactory::new which was called 3 times, avg 225µs/call:
# 3 times (47µs+628µs) by XML::SAX::ParserFactory::parser at line 25, avg 225µs/call | ||||
| 15 | 3 | 2µs | my $class = shift; | ||
| 16 | 3 | 3µs | my %params = @_; # TODO : Fix this in spec. | ||
| 17 | 3 | 13µs | my $self = bless \%params, $class; | ||
| 18 | 3 | 15µs | 3 | 628µs | $self->{KnownParsers} = XML::SAX->parsers(); # spent 628µs making 3 calls to XML::SAX::parsers, avg 209µs/call |
| 19 | 3 | 11µs | return $self; | ||
| 20 | } | ||||
| 21 | |||||
| 22 | # spent 36.9ms (686µs+36.2) within XML::SAX::ParserFactory::parser which was called 3 times, avg 12.3ms/call:
# 3 times (686µs+36.2ms) by XML::Simple::build_tree at line 358 of XML/Simple.pm, avg 12.3ms/call | ||||
| 23 | 3 | 3µs | my $self = shift; | ||
| 24 | 3 | 5µs | my @parser_params = @_; | ||
| 25 | 3 | 10µs | 3 | 675µs | if (!ref($self)) { # spent 675µs making 3 calls to XML::SAX::ParserFactory::new, avg 225µs/call |
| 26 | $self = $self->new(); | ||||
| 27 | } | ||||
| 28 | |||||
| 29 | 3 | 11µs | 3 | 554µs | my $parser_class = $self->_parser_class(); # spent 554µs making 3 calls to XML::SAX::ParserFactory::_parser_class, avg 184µs/call |
| 30 | |||||
| 31 | 3 | 2µs | my $version = ''; | ||
| 32 | 3 | 16µs | 3 | 3µs | if ($parser_class =~ s/\s*\(([\d\.]+)\)\s*$//) { # spent 3µs making 3 calls to XML::SAX::ParserFactory::CORE:subst, avg 1µs/call |
| 33 | $version = " $1"; | ||||
| 34 | } | ||||
| 35 | |||||
| 36 | 3 | 30µs | 3 | 8µs | if (!$parser_class->can('new')) { # spent 8µs making 3 calls to UNIVERSAL::can, avg 3µs/call |
| 37 | 1 | 122µs | eval "require $parser_class $version;"; | ||
| 38 | 1 | 500ns | die $@ if $@; | ||
| 39 | } | ||||
| 40 | |||||
| 41 | 3 | 33µs | 3 | 200µs | return $parser_class->new(@parser_params); # spent 200µs making 3 calls to XML::SAX::Base::new, avg 67µs/call |
| 42 | } | ||||
| 43 | |||||
| 44 | sub require_feature { | ||||
| 45 | my $self = shift; | ||||
| 46 | my ($feature) = @_; | ||||
| 47 | $self->{RequiredFeatures}{$feature}++; | ||||
| 48 | return $self; | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | # spent 554µs (203+350) within XML::SAX::ParserFactory::_parser_class which was called 3 times, avg 184µs/call:
# 3 times (203µs+350µs) by XML::SAX::ParserFactory::parser at line 29, avg 184µs/call | ||||
| 52 | 3 | 2µs | my $self = shift; | ||
| 53 | |||||
| 54 | # First try ParserPackage | ||||
| 55 | 3 | 2µs | if ($XML::SAX::ParserPackage) { | ||
| 56 | return $XML::SAX::ParserPackage; | ||||
| 57 | } | ||||
| 58 | |||||
| 59 | # Now check if required/preferred is there | ||||
| 60 | 3 | 2µs | if ($self->{RequiredFeatures}) { | ||
| 61 | my %required = %{$self->{RequiredFeatures}}; | ||||
| 62 | # note - we never go onto the next try (ParserDetails.ini), | ||||
| 63 | # because if we can't provide the requested feature | ||||
| 64 | # we need to throw an exception. | ||||
| 65 | PARSER: | ||||
| 66 | foreach my $parser (reverse @{$self->{KnownParsers}}) { | ||||
| 67 | foreach my $feature (keys %required) { | ||||
| 68 | if (!exists $parser->{Features}{$feature}) { | ||||
| 69 | next PARSER; | ||||
| 70 | } | ||||
| 71 | } | ||||
| 72 | # got here - all features must exist! | ||||
| 73 | return $parser->{Name}; | ||||
| 74 | } | ||||
| 75 | # TODO : should this be NotSupported() ? | ||||
| 76 | throw XML::SAX::Exception ( | ||||
| 77 | Message => "Unable to provide required features", | ||||
| 78 | ); | ||||
| 79 | } | ||||
| 80 | |||||
| 81 | # Next try SAX.ini | ||||
| 82 | 3 | 5µs | for my $dir (@INC) { | ||
| 83 | 18 | 32µs | 18 | 120µs | my $fh = gensym(); # spent 120µs making 18 calls to Symbol::gensym, avg 7µs/call |
| 84 | 18 | 345µs | 18 | 231µs | if (open($fh, "$dir/SAX.ini")) { # spent 231µs making 18 calls to XML::SAX::ParserFactory::CORE:open, avg 13µs/call |
| 85 | my $param_list = XML::SAX->_parse_ini_file($fh); | ||||
| 86 | my $params = $param_list->[0]->{Features}; | ||||
| 87 | if ($params->{ParserPackage}) { | ||||
| 88 | return $params->{ParserPackage}; | ||||
| 89 | } | ||||
| 90 | else { | ||||
| 91 | # we have required features (or nothing?) | ||||
| 92 | PARSER: | ||||
| 93 | foreach my $parser (reverse @{$self->{KnownParsers}}) { | ||||
| 94 | foreach my $feature (keys %$params) { | ||||
| 95 | if (!exists $parser->{Features}{$feature}) { | ||||
| 96 | next PARSER; | ||||
| 97 | } | ||||
| 98 | } | ||||
| 99 | return $parser->{Name}; | ||||
| 100 | } | ||||
| 101 | XML::SAX->do_warn("Unable to provide SAX.ini required features. Using fallback\n"); | ||||
| 102 | } | ||||
| 103 | last; # stop after first INI found | ||||
| 104 | } | ||||
| 105 | } | ||||
| 106 | |||||
| 107 | 3 | 21µs | if (@{$self->{KnownParsers}}) { | ||
| 108 | return $self->{KnownParsers}[-1]{Name}; | ||||
| 109 | } | ||||
| 110 | else { | ||||
| 111 | return "XML::SAX::PurePerl"; # backup plan! | ||||
| 112 | } | ||||
| 113 | } | ||||
| 114 | |||||
| 115 | 1 | 4µs | 1; | ||
| 116 | __END__ | ||||
| 117 | |||||
| 118 | =head1 NAME | ||||
| 119 | |||||
| 120 | XML::SAX::ParserFactory - Obtain a SAX parser | ||||
| 121 | |||||
| 122 | =head1 SYNOPSIS | ||||
| 123 | |||||
| 124 | use XML::SAX::ParserFactory; | ||||
| 125 | use XML::SAX::XYZHandler; | ||||
| 126 | my $handler = XML::SAX::XYZHandler->new(); | ||||
| 127 | my $p = XML::SAX::ParserFactory->parser(Handler => $handler); | ||||
| 128 | $p->parse_uri("foo.xml"); | ||||
| 129 | # or $p->parse_string("<foo/>") or $p->parse_file($fh); | ||||
| 130 | |||||
| 131 | =head1 DESCRIPTION | ||||
| 132 | |||||
| 133 | XML::SAX::ParserFactory is a factory class for providing an application | ||||
| 134 | with a Perl SAX2 XML parser. It is akin to DBI - a front end for other | ||||
| 135 | parser classes. Each new SAX2 parser installed will register itself | ||||
| 136 | with XML::SAX, and then it will become available to all applications | ||||
| 137 | that use XML::SAX::ParserFactory to obtain a SAX parser. | ||||
| 138 | |||||
| 139 | Unlike DBI however, XML/SAX parsers almost all work alike (especially | ||||
| 140 | if they subclass XML::SAX::Base, as they should), so rather than | ||||
| 141 | specifying the parser you want in the call to C<parser()>, XML::SAX | ||||
| 142 | has several ways to automatically choose which parser to use: | ||||
| 143 | |||||
| 144 | =over 4 | ||||
| 145 | |||||
| 146 | =item * $XML::SAX::ParserPackage | ||||
| 147 | |||||
| 148 | If this package variable is set, then this package is C<require()>d | ||||
| 149 | and an instance of this package is returned by calling the C<new()> | ||||
| 150 | class method in that package. If it cannot be loaded or there is | ||||
| 151 | an error, an exception will be thrown. The variable can also contain | ||||
| 152 | a version number: | ||||
| 153 | |||||
| 154 | $XML::SAX::ParserPackage = "XML::SAX::Expat (0.72)"; | ||||
| 155 | |||||
| 156 | And the number will be treated as a minimum version number. | ||||
| 157 | |||||
| 158 | =item * Required features | ||||
| 159 | |||||
| 160 | It is possible to require features from the parsers. For example, you | ||||
| 161 | may wish for a parser that supports validation via a DTD. To do that, | ||||
| 162 | use the following code: | ||||
| 163 | |||||
| 164 | use XML::SAX::ParserFactory; | ||||
| 165 | my $factory = XML::SAX::ParserFactory->new(); | ||||
| 166 | $factory->require_feature('http://xml.org/sax/features/validation'); | ||||
| 167 | my $parser = $factory->parser(...); | ||||
| 168 | |||||
| 169 | Alternatively, specify the required features in the call to the | ||||
| 170 | ParserFactory constructor: | ||||
| 171 | |||||
| 172 | my $factory = XML::SAX::ParserFactory->new( | ||||
| 173 | RequiredFeatures => { | ||||
| 174 | 'http://xml.org/sax/features/validation' => 1, | ||||
| 175 | } | ||||
| 176 | ); | ||||
| 177 | |||||
| 178 | If the features you have asked for are unavailable (for example the | ||||
| 179 | user might not have a validating parser installed), then an | ||||
| 180 | exception will be thrown. | ||||
| 181 | |||||
| 182 | The list of known parsers is searched in reverse order, so it will | ||||
| 183 | always return the last installed parser that supports all of your | ||||
| 184 | requested features (Note: this is subject to change if someone | ||||
| 185 | comes up with a better way of making this work). | ||||
| 186 | |||||
| 187 | =item * SAX.ini | ||||
| 188 | |||||
| 189 | ParserFactory will search @INC for a file called SAX.ini, which | ||||
| 190 | is in a simple format: | ||||
| 191 | |||||
| 192 | # a comment looks like this, | ||||
| 193 | ; or like this, and are stripped anywhere in the file | ||||
| 194 | key = value # SAX.in contains key/value pairs. | ||||
| 195 | |||||
| 196 | All whitespace is non-significant. | ||||
| 197 | |||||
| 198 | This file can contain either a line: | ||||
| 199 | |||||
| 200 | ParserPackage = MyParserModule (1.02) | ||||
| 201 | |||||
| 202 | Where MyParserModule is the module to load and use for the parser, | ||||
| 203 | and the number in brackets is a minimum version to load. | ||||
| 204 | |||||
| 205 | Or you can list required features: | ||||
| 206 | |||||
| 207 | http://xml.org/sax/features/validation = 1 | ||||
| 208 | |||||
| 209 | And each feature with a true value will be required. | ||||
| 210 | |||||
| 211 | =item * Fallback | ||||
| 212 | |||||
| 213 | If none of the above works, the last parser installed on the user's | ||||
| 214 | system will be used. The XML::SAX package ships with a pure perl | ||||
| 215 | XML parser, XML::SAX::PurePerl, so that there will always be a | ||||
| 216 | fallback parser. | ||||
| 217 | |||||
| 218 | =back | ||||
| 219 | |||||
| 220 | =head1 AUTHOR | ||||
| 221 | |||||
| 222 | Matt Sergeant, matt@sergeant.org | ||||
| 223 | |||||
| 224 | =head1 LICENSE | ||||
| 225 | |||||
| 226 | This is free software, you may use it and distribute it under the same | ||||
| 227 | terms as Perl itself. | ||||
| 228 | |||||
| 229 | =cut | ||||
| 230 | |||||
# spent 231µs within XML::SAX::ParserFactory::CORE:open which was called 18 times, avg 13µs/call:
# 18 times (231µs+0s) by XML::SAX::ParserFactory::_parser_class at line 84 of XML/SAX/ParserFactory.pm, avg 13µs/call | |||||
# spent 3µs within XML::SAX::ParserFactory::CORE:subst which was called 3 times, avg 1µs/call:
# 3 times (3µs+0s) by XML::SAX::ParserFactory::parser at line 32 of XML/SAX/ParserFactory.pm, avg 1µs/call |