home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / perl5 / XML / Parser / PerlSAX.pm
Encoding:
Text File  |  2003-10-21  |  22.7 KB  |  797 lines

  1. #
  2. # Copyright (C) 1999 Ken MacLeod
  3. # XML::Parser::PerlSAX is free software; you can redistribute it and/or
  4. # modify it under the same terms as Perl itself.
  5. #
  6. # $Id: PerlSAX.pm,v 1.7 1999/12/22 21:15:00 kmacleod Exp $
  7. #
  8.  
  9. use strict;
  10.  
  11. package XML::Parser::PerlSAX;
  12.  
  13. use XML::Parser;
  14. use UNIVERSAL;
  15. use vars qw{ $VERSION $name_re };
  16.  
  17. # will be substituted by make-rel script
  18. $VERSION = "0.08";
  19.  
  20. # FIXME I doubt this is a correct Perl RE for productions [4] and
  21. # [5] in the XML 1.0 specification, especially considering Unicode chars
  22. $name_re = '[A-Za-z_:][A-Za-z0-9._:-]*';
  23.  
  24. sub new {
  25.     my $type = shift;
  26.     my $self = (@_ == 1) ? shift : { @_ };
  27.  
  28.     return bless $self, $type;
  29. }
  30.  
  31. sub parse {
  32.     my $self = shift;
  33.  
  34.     die "XML::Parser::PerlSAX: parser instance ($self) already parsing\n"
  35.     if (defined $self->{ParseOptions});
  36.  
  37.     # If there's one arg and it has no ref, it's a string
  38.     my $args;
  39.     if (scalar (@_) == 1 && !ref($_[0])) {
  40.     $args = { Source => { String => shift } };
  41.     } else {
  42.     $args = (scalar (@_) == 1) ? shift : { @_ };
  43.     }
  44.  
  45.     my $parse_options = { %$self, %$args };
  46.     $self->{ParseOptions} = $parse_options;
  47.  
  48.     # ensure that we have at least one source
  49.     if (!defined $parse_options->{Source}
  50.     || !(defined $parse_options->{Source}{String}
  51.          || defined $parse_options->{Source}{ByteStream}
  52.          || defined $parse_options->{Source}{SystemId})) {
  53.     die "XML::Parser::PerlSAX: no source defined for parse\n";
  54.     }
  55.  
  56.     # assign default Handler to any undefined handlers
  57.     if (defined $parse_options->{Handler}) {
  58.     $parse_options->{DocumentHandler} = $parse_options->{Handler}
  59.         if (!defined $parse_options->{DocumentHandler});
  60.     $parse_options->{DTDHandler} = $parse_options->{Handler}
  61.         if (!defined $parse_options->{DTDHandler});
  62.     $parse_options->{EntityResolver} = $parse_options->{Handler}
  63.         if (!defined $parse_options->{EntityResolver});
  64.     }
  65.  
  66.     my @handlers;
  67.     if (defined $parse_options->{DocumentHandler}) {
  68.     # cache DocumentHandler in self for callbacks
  69.     $self->{DocumentHandler} = $parse_options->{DocumentHandler};
  70.  
  71.     my $doc_h = $parse_options->{DocumentHandler};
  72.  
  73.     push (@handlers, Init => sub { $self->_handle_init(@_) } )
  74.         if (UNIVERSAL::can($doc_h, 'start_document'));
  75.     push (@handlers, Final => sub { $self->_handle_final(@_) } )
  76.         if (UNIVERSAL::can($doc_h, 'end_document'));
  77.     push (@handlers, Start => sub { $self->_handle_start(@_) } )
  78.         if (UNIVERSAL::can($doc_h, 'start_element'));
  79.     push (@handlers, End => sub { $self->_handle_end(@_) } )
  80.         if (UNIVERSAL::can($doc_h, 'end_element'));
  81.     push (@handlers, Char => sub { $self->_handle_char(@_) } )
  82.         if (UNIVERSAL::can($doc_h, 'characters'));
  83.     push (@handlers, Proc => sub { $self->_handle_proc(@_) } )
  84.         if (UNIVERSAL::can($doc_h, 'processing_instruction'));
  85.     push (@handlers, Comment => sub { $self->_handle_comment(@_) } )
  86.         if (UNIVERSAL::can($doc_h, 'comment'));
  87.     push (@handlers, CdataStart => sub { $self->_handle_cdatastart(@_) } )
  88.         if (UNIVERSAL::can($doc_h, 'start_cdata'));
  89.     push (@handlers, CdataEnd => sub { $self->_handle_cdataend(@_) } )
  90.         if (UNIVERSAL::can($doc_h, 'end_cdata'));
  91.     if (UNIVERSAL::can($doc_h, 'entity_reference')) {
  92.         push (@handlers, Default => sub { $self->_handle_default(@_) } );
  93.         $self->{UseEntRefs} = 1;
  94.     }
  95.     }
  96.  
  97.     if (defined $parse_options->{DTDHandler}) {
  98.     # cache DTDHandler in self for callbacks
  99.     $self->{DTDHandler} = $parse_options->{DTDHandler};
  100.  
  101.     my $dtd_h = $parse_options->{DTDHandler};
  102.  
  103.     push (@handlers, Notation => sub { $self->_handle_notation(@_) } )
  104.         if (UNIVERSAL::can($dtd_h, 'notation_decl'));
  105.     push (@handlers, Unparsed => sub { $self->_handle_unparsed(@_) } )
  106.         if (UNIVERSAL::can($dtd_h, 'unparsed_entity_decl'));
  107.     push (@handlers, Entity => sub { $self->_handle_entity(@_) } )
  108.         if ($self->{UseEntRefs}
  109.         || UNIVERSAL::can($dtd_h, 'entity_decl'));
  110.     push (@handlers, Element => sub { $self->_handle_element(@_) } )
  111.         if (UNIVERSAL::can($dtd_h, 'element_decl'));
  112.     push (@handlers, Attlist => sub { $self->_handle_attlist(@_) } )
  113.         if (UNIVERSAL::can($dtd_h, 'attlist_decl'));
  114.     push (@handlers, Doctype => sub { $self->_handle_doctype(@_) } )
  115.         if (UNIVERSAL::can($dtd_h, 'doctype_decl'));
  116.     push (@handlers, XMLDecl => sub { $self->_handle_xmldecl(@_) } )
  117.         if (UNIVERSAL::can($dtd_h, 'xml_decl'));
  118.     }
  119.  
  120.     
  121.     if (defined $parse_options->{EntityResolver}) {
  122.     # cache EntityResolver in self for callbacks
  123.     $self->{EntityResolver} = $parse_options->{EntityResolver};
  124.  
  125.     my $er = $parse_options->{EntityResolver};
  126.  
  127.     push (@handlers, ExternEnt => sub { $self->_handle_extern_ent(@_) } )
  128.         if (UNIVERSAL::can($er, 'resolve_entity'));
  129.     }
  130.  
  131.     my @xml_parser_options;
  132.     if ($self->{UseEntRefs}) {
  133.     @xml_parser_options = ( NoExpand => 1,
  134.                 Handlers => { @handlers } );
  135.     } else {
  136.     @xml_parser_options = ( Handlers => { @handlers } );
  137.     }
  138.  
  139.     push (@xml_parser_options,
  140.       ProtocolEncoding => $self->{ParseOptions}{Source}{Encoding})
  141.     if (defined $self->{ParseOptions}{Source}{Encoding});
  142.  
  143.     my $parser = new XML::Parser(@xml_parser_options);
  144.     my $result;
  145.  
  146.     if (defined $self->{ParseOptions}{Source}{ByteStream}) {
  147.     $result = $parser->parse($self->{ParseOptions}{Source}{ByteStream});
  148.     } elsif (defined $self->{ParseOptions}{Source}{String}) {
  149.     $result = $parser->parse($self->{ParseOptions}{Source}{String});
  150.     } elsif (defined $self->{ParseOptions}{Source}{SystemId}) {
  151.     $result = $parser->parsefile($self->{ParseOptions}{Source}{SystemId});
  152.     }
  153.  
  154.     # clean up parser instance
  155.     delete $self->{ParseOptions};
  156.     delete $self->{DocumentHandler};
  157.     delete $self->{DTDHandler};
  158.     delete $self->{EntityResolver};
  159.     delete $self->{Expat};
  160.  
  161.     return $result;
  162. }
  163.  
  164. sub location {
  165.     my $self = shift;
  166.  
  167.     my $expat = $self->{Expat};
  168.  
  169.     my @properties = ( ColumnNumber => $expat->current_column,
  170.                LineNumber => $expat->current_line,
  171.                BytePosition => $expat->current_byte,
  172.                Base => $expat->base );
  173.  
  174.     # FIXME these locations change while parsing external entities
  175.     push (@properties, PublicId => $self->{Source}{PublicId})
  176.     if (defined $self->{Source}{PublicId});
  177.     push (@properties, SystemId => $self->{Source}{SystemId})
  178.     if (defined $self->{Source}{SystemId});
  179.  
  180.     return { @properties };
  181. }
  182.  
  183. ###
  184. ### DocumentHandler methods
  185. ###
  186.  
  187. sub _handle_init {
  188.     my $self = shift;
  189.     my $expat = shift;
  190.  
  191.     $self->{Expat} = $expat;
  192.  
  193.     if ($self->{DocumentHandler}->can('set_document_locator')) {
  194.     $self->{DocumentHandler}->set_document_locator( { Locator => $self } );
  195.     }
  196.     $self->{DocumentHandler}->start_document( { } );
  197. }
  198.  
  199. sub _handle_final {
  200.     my $self = shift;
  201.  
  202.     delete $self->{UseEntRefs};
  203.     delete $self->{EntRefs};
  204.     return $self->{DocumentHandler}->end_document( { } );
  205. }
  206.  
  207. sub _handle_start {
  208.     my $self = shift;
  209.     my $expat = shift;
  210.     my $element = shift;
  211.  
  212.     my @properties;
  213.     if ($self->{ParseOptions}{UseAttributeOrder}) {
  214.     # Capture order and defined() status for attributes
  215.     my $ii;
  216.  
  217.     my $order = [];
  218.     for ($ii = 0; $ii < $#_; $ii += 2) {
  219.         push @$order, $_[$ii];
  220.     }
  221.  
  222.     push @properties, 'AttributeOrder', $order;
  223.  
  224.     # Divide by two because XML::Parser counts both attribute name
  225.     # and value within it's index
  226.     push @properties, 'Defaulted', ($expat->specified_attr() / 2);
  227.     }
  228.  
  229.     $self->{DocumentHandler}->start_element( { Name => $element,
  230.                            Attributes => { @_ },
  231.                            @properties } );
  232. }
  233.  
  234. sub _handle_end {
  235.     my $self = shift;
  236.     my $expat = shift;
  237.     my $element = shift;
  238.  
  239.     $self->{DocumentHandler}->end_element( { Name => $element } );
  240. }
  241.  
  242. sub _handle_char {
  243.     my $self = shift;
  244.     my $expat = shift;
  245.     my $string = shift;
  246.  
  247.     $self->{DocumentHandler}->characters( { Data => $string } );
  248. }
  249.  
  250. sub _handle_proc {
  251.     my $self = shift;
  252.     my $expat = shift;
  253.     my $target = shift;
  254.     my $data = shift;
  255.  
  256.     $self->{DocumentHandler}->processing_instruction( { Target => $target,
  257.                             Data => $data } );
  258. }
  259.  
  260. sub _handle_comment {
  261.     my $self = shift;
  262.     my $expat = shift;
  263.     my $data = shift;
  264.  
  265.     $self->{DocumentHandler}->comment( { Data => $data } );
  266. }
  267.  
  268. sub _handle_cdatastart {
  269.     my $self = shift;
  270.     my $expat = shift;
  271.  
  272.     $self->{DocumentHandler}->start_cdata( { } );
  273. }
  274.  
  275. sub _handle_cdataend {
  276.     my $self = shift;
  277.     my $expat = shift;
  278.  
  279.     $self->{DocumentHandler}->end_cdata( { } );
  280. }
  281.  
  282. # Default receives all characters that aren't handled by some other
  283. # handler, this means a lot of stuff goes through here.  All we're
  284. # looking for are `&NAME;' entity reference sequences
  285. sub _handle_default {
  286.     my $self = shift;
  287.     my $expat = shift;
  288.     my $string = shift;
  289.  
  290.     if ($string =~ /^&($name_re);$/) {
  291.     my $ent_ref = $self->{EntRefs}{$1};
  292.     if (!defined $ent_ref) {
  293.         $ent_ref = { Name => $1 };
  294.     }
  295.     $self->{DocumentHandler}->entity_reference($ent_ref);
  296.     }
  297. }
  298.  
  299. ###
  300. ### DTDHandler methods
  301. ###
  302.  
  303. sub _handle_notation {
  304.     my $self = shift;
  305.     my $expat = shift;
  306.     my $notation = shift;
  307.     my $base = shift;
  308.     my $sysid = shift;
  309.     my $pubid = shift;
  310.     my @properties = (Name => $notation);
  311.  
  312.     push (@properties, Base => $base)
  313.     if (defined $base);
  314.     push (@properties, SystemId => $sysid)
  315.     if (defined $sysid);
  316.     push (@properties, PublicId => $pubid)
  317.     if (defined $pubid);
  318.  
  319.  
  320.     $self->{DTDHandler}->notation_decl( { @properties } );
  321. }
  322.  
  323. sub _handle_unparsed {
  324.     my $self = shift;
  325.     my $expat = shift;
  326.     my $entity = shift;
  327.     my $base = shift;
  328.     my $sysid = shift;
  329.     my $pubid = shift;
  330.     my @properties = (Name => $entity, SystemId => $sysid);
  331.  
  332.     push (@properties, Base => $base)
  333.     if (defined $base);
  334.     push (@properties, PublicId => $pubid)
  335.     if (defined $pubid);
  336.  
  337.     $self->{DTDHandler}->unparsed_entity_decl( { @properties } );
  338. }
  339.  
  340. sub _handle_entity {
  341.     my $self = shift;
  342.     my $expat = shift;
  343.     my $name = shift;
  344.     my $val = shift;
  345.     my $sysid = shift;
  346.     my $pubid = shift;
  347.     my $ndata = shift;
  348.     my @properties = (Name => $name);
  349.  
  350.     push (@properties, Value => $val)
  351.     if (defined $val);
  352.     push (@properties, PublicId => $pubid)
  353.     if (defined $pubid);
  354.     push (@properties, SystemId => $sysid)
  355.     if (defined $sysid);
  356.     push (@properties, Notation => $ndata)
  357.     if (defined $ndata);
  358.  
  359.     my $properties = { @properties };
  360.     if ($self->{UseEntRefs}) {
  361.     $self->{EntRefs}{$name} = $properties;
  362.     }
  363.     if ($self->{DTDHandler}->can('entity_decl')) {
  364.     $self->{DTDHandler}->entity_decl( $properties );
  365.     }
  366. }
  367.  
  368. sub _handle_element {
  369.     my $self = shift;
  370.     my $expat = shift;
  371.     my $name = shift;
  372.     my $model = shift;
  373.  
  374.     $self->{DTDHandler}->element_decl( { Name => $name,
  375.                      Model => $model } );
  376. }
  377.  
  378. sub _handle_attlist {
  379.     my $self = shift;
  380.     my $expat = shift;
  381.     my $elname = shift;
  382.     my $attname = shift;
  383.     my $type = shift;
  384.     my $default = shift;
  385.     my $fixed = shift;
  386.  
  387.     $self->{DTDHandler}->attlist_decl( { ElementName => $elname,
  388.                      AttributeName => $attname,
  389.                      Type => $type,
  390.                      Default => $default,
  391.                      Fixed => $fixed } );
  392. }
  393.  
  394. sub _handle_doctype {
  395.     my $self = shift;
  396.     my $expat = shift;
  397.     my $name = shift;
  398.     my $sysid = shift;
  399.     my $pubid = shift;
  400.     my $internal = shift;
  401.     my @properties = (Name => $name);
  402.  
  403.     push (@properties, SystemId => $sysid)
  404.     if (defined $sysid);
  405.     push (@properties, PublicId => $pubid)
  406.     if (defined $pubid);
  407.     push (@properties, Internal => $internal)
  408.     if (defined $internal);
  409.  
  410.     $self->{DTDHandler}->doctype_decl( { @properties } );
  411. }
  412.  
  413. sub _handle_xmldecl {
  414.     my $self = shift;
  415.     my $expat = shift;
  416.     my $version = shift;
  417.     my $encoding = shift;
  418.     my $standalone = shift;
  419.     my @properties = (Version => $version);
  420.  
  421.     push (@properties, Encoding => $encoding)
  422.     if (defined $encoding);
  423.     push (@properties, Standalone => $standalone)
  424.     if (defined $standalone);
  425.  
  426.     $self->{DTDHandler}->xml_decl( { @properties } );
  427. }
  428.  
  429. ###
  430. ### EntityResolver methods
  431. ###
  432.  
  433. sub _handle_extern_ent {
  434.     my $self = shift;
  435.     my $expat = shift;
  436.     my $base = shift;
  437.     my $sysid = shift;
  438.     my $pubid = shift;
  439.     my @properties = (SystemId => $sysid);
  440.  
  441.     push (@properties, Base => $base)
  442.     if (defined $base);
  443.     push (@properties, PublicId => $pubid)
  444.     if (defined $pubid);
  445.  
  446.     my $result = $self->{EntityResolver}->resolve_entity( { @properties } );
  447.  
  448.     if (UNIVERSAL::isa($result, 'HASH')) {
  449.     if ($result->{ByteStream}) {
  450.         return $result->{ByteStream};
  451.     } elsif ($result->{String}) {
  452.         return $result->{String};
  453.     } elsif ($result->{SystemId}) {
  454.         # FIXME must be able to resolve SystemIds, XML::Parser's
  455.         # default can :-(
  456.         die "PerlSAX: automatic opening of SystemIds from \`resolve_entity' not implemented, contact the author\n";
  457.     } else {
  458.         # FIXME
  459.         die "PerlSAX: invalid source returned from \`resolve_entity'\n";
  460.     }
  461.     }
  462.  
  463.     return undef;
  464. }
  465.  
  466. 1;
  467.  
  468. __END__
  469.  
  470. =head1 NAME
  471.  
  472. XML::Parser::PerlSAX - Perl SAX parser using XML::Parser
  473.  
  474. =head1 SYNOPSIS
  475.  
  476.  use XML::Parser::PerlSAX;
  477.  
  478.  $parser = XML::Parser::PerlSAX->new( [OPTIONS] );
  479.  $result = $parser->parse( [OPTIONS] );
  480.  
  481.  $result = $parser->parse($string);
  482.  
  483. =head1 DESCRIPTION
  484.  
  485. C<XML::Parser::PerlSAX> is a PerlSAX parser using the XML::Parser
  486. module.  This man page summarizes the specific options, handlers, and
  487. properties supported by C<XML::Parser::PerlSAX>; please refer to the
  488. PerlSAX standard in `C<PerlSAX.pod>' for general usage information.
  489.  
  490. =head1 METHODS
  491.  
  492. =over 4
  493.  
  494. =item new
  495.  
  496. Creates a new parser object.  Default options for parsing, described
  497. below, are passed as key-value pairs or as a single hash.  Options may
  498. be changed directly in the parser object unless stated otherwise.
  499. Options passed to `C<parse()>' override the default options in the
  500. parser object for the duration of the parse.
  501.  
  502. =item parse
  503.  
  504. Parses a document.  Options, described below, are passed as key-value
  505. pairs or as a single hash.  Options passed to `C<parse()>' override
  506. default options in the parser object.
  507.  
  508. =item location
  509.  
  510. Returns the location as a hash:
  511.  
  512.   ColumnNumber    The column number of the parse.
  513.   LineNumber      The line number of the parse.
  514.   BytePosition    The current byte position of the parse.
  515.   PublicId        A string containing the public identifier, or undef
  516.                   if none is available.
  517.   SystemId        A string containing the system identifier, or undef
  518.                   if none is available.
  519.   Base            The current value of the base for resolving relative
  520.                   URIs.
  521.  
  522. ALPHA WARNING: The `C<SystemId>' and `C<PublicId>' properties returned
  523. are the system and public identifiers of the document passed to
  524. `C<parse()>', not the identifiers of the currently parsing external
  525. entity.  The column, line, and byte positions I<are> of the current
  526. entity being parsed.
  527.  
  528. =head1 OPTIONS
  529.  
  530. The following options are supported by C<XML::Parser::PerlSAX>:
  531.  
  532.  Handler          default handler to receive events
  533.  DocumentHandler  handler to receive document events
  534.  DTDHandler       handler to receive DTD events
  535.  ErrorHandler     handler to receive error events
  536.  EntityResolver   handler to resolve entities
  537.  Locale           locale to provide localisation for errors
  538.  Source           hash containing the input source for parsing
  539.  UseAttributeOrder set to true to provide AttributeOrder and Defaulted
  540.                    properties in `start_element()'
  541.  
  542. If no handlers are provided then all events will be silently ignored,
  543. except for `C<fatal_error()>' which will cause a `C<die()>' to be
  544. called after calling `C<end_document()>'.
  545.  
  546. If a single string argument is passed to the `C<parse()>' method, it
  547. is treated as if a `C<Source>' option was given with a `C<String>'
  548. parameter.
  549.  
  550. The `C<Source>' hash may contain the following parameters:
  551.  
  552.  ByteStream       The raw byte stream (file handle) containing the
  553.                   document.
  554.  String           A string containing the document.
  555.  SystemId         The system identifier (URI) of the document.
  556.  PublicId         The public identifier.
  557.  Encoding         A string describing the character encoding.
  558.  
  559. If more than one of `C<ByteStream>', `C<String>', or `C<SystemId>',
  560. then preference is given first to `C<ByteStream>', then `C<String>',
  561. then `C<SystemId>'.
  562.  
  563. =head1 HANDLERS
  564.  
  565. The following handlers and properties are supported by
  566. C<XML::Parser::PerlSAX>:
  567.  
  568. =head2 DocumentHandler methods
  569.  
  570. =over 4
  571.  
  572. =item start_document
  573.  
  574. Receive notification of the beginning of a document.
  575.  
  576. No properties defined.
  577.  
  578. =item end_document
  579.  
  580. Receive notification of the end of a document.
  581.  
  582. No properties defined.
  583.  
  584. =item start_element
  585.  
  586. Receive notification of the beginning of an element.
  587.  
  588.  Name             The element type name.
  589.  Attributes       A hash containing the attributes attached to the
  590.                   element, if any.
  591.  
  592. The `C<Attributes>' hash contains only string values.
  593.  
  594. If the `C<UseAttributeOrder>' parser option is true, the following
  595. properties are also passed to `C<start_element>':
  596.  
  597.  AttributeOrder   An array of attribute names in the order they were
  598.                   specified, followed by the defaulted attribute
  599.                   names.
  600.  Defaulted        The index number of the first defaulted attribute in
  601.                   `AttributeOrder.  If this index is equal to the
  602.                   length of `AttributeOrder', there were no defaulted
  603.                   values.
  604.  
  605. Note to C<XML::Parser> users:  `C<Defaulted>' will be half the value of
  606. C<XML::Parser::Expat>'s `C<specified_attr()>' function because only
  607. attribute names are provided, not their values.
  608.  
  609.  
  610. =item end_element
  611.  
  612. Receive notification of the end of an element.
  613.  
  614.  Name             The element type name.
  615.  
  616. =item characters
  617.  
  618. Receive notification of character data.
  619.  
  620.  Data             The characters from the XML document.
  621.  
  622. =item processing_instruction
  623.  
  624. Receive notification of a processing instruction. 
  625.  
  626.  Target           The processing instruction target. 
  627.  Data             The processing instruction data, if any.
  628.  
  629. =item comment
  630.  
  631. Receive notification of a comment.
  632.  
  633.  Data             The comment data, if any.
  634.  
  635. =item start_cdata
  636.  
  637. Receive notification of the start of a CDATA section.
  638.  
  639. No properties defined.
  640.  
  641. =item end_cdata
  642.  
  643. Receive notification of the end of a CDATA section.
  644.  
  645. No properties defined.
  646.  
  647. =item entity_reference
  648.  
  649. Receive notification of an internal entity reference.  If this handler
  650. is defined, internal entities will not be expanded and not passed to
  651. the `C<characters()>' handler.  If this handler is not defined,
  652. internal entities will be expanded if possible and passed to the
  653. `C<characters()>' handler.
  654.  
  655.  Name             The entity reference name
  656.  Value            The entity reference value
  657.  
  658. =back
  659.  
  660. =head2 DTDHandler methods
  661.  
  662. =over 4
  663.  
  664. =item notation_decl
  665.  
  666. Receive notification of a notation declaration event.
  667.  
  668.  Name             The notation name.
  669.  PublicId         The notation's public identifier, if any.
  670.  SystemId         The notation's system identifier, if any.
  671.  Base             The base for resolving a relative URI, if any.
  672.  
  673. =item unparsed_entity_decl
  674.  
  675. Receive notification of an unparsed entity declaration event.
  676.  
  677.  Name             The unparsed entity's name.
  678.  SystemId         The entity's system identifier.
  679.  PublicId         The entity's public identifier, if any.
  680.  Base             The base for resolving a relative URI, if any.
  681.  
  682. =item entity_decl
  683.  
  684. Receive notification of an entity declaration event.
  685.  
  686.  Name             The entity name.
  687.  Value            The entity value, if any.
  688.  PublicId         The notation's public identifier, if any.
  689.  SystemId         The notation's system identifier, if any.
  690.  Notation         The notation declared for this entity, if any.
  691.  
  692. For internal entities, the `C<Value>' parameter will contain the value
  693. and the `C<PublicId>', `C<SystemId>', and `C<Notation>' will be
  694. undefined.  For external entities, the `C<Value>' parameter will be
  695. undefined, the `C<SystemId>' parameter will have the system id, the
  696. `C<PublicId>' parameter will have the public id if it was provided (it
  697. will be undefined otherwise), the `C<Notation>' parameter will contain
  698. the notation name for unparsed entities.  If this is a parameter entity
  699. declaration, then a '%' will be prefixed to the entity name.
  700.  
  701. Note that `C<entity_decl()>' and `C<unparsed_entity_decl()>' overlap.
  702. If both methods are implemented by a handler, then this handler will
  703. not be called for unparsed entities.
  704.  
  705. =item element_decl
  706.  
  707. Receive notification of an element declaration event.
  708.  
  709.  Name             The element type name.
  710.  Model            The content model as a string.
  711.  
  712. =item attlist_decl
  713.  
  714. Receive notification of an attribute list declaration event.
  715.  
  716. This handler is called for each attribute in an ATTLIST declaration
  717. found in the internal subset. So an ATTLIST declaration that has
  718. multiple attributes will generate multiple calls to this handler.
  719.  
  720.  ElementName      The element type name.
  721.  AttributeName    The attribute name.
  722.  Type             The attribute type.
  723.  Fixed            True if this is a fixed attribute.
  724.  
  725. The default for `C<Type>' is the default value, which will either be
  726. "#REQUIRED", "#IMPLIED" or a quoted string (i.e. the returned string
  727. will begin and end with a quote character).
  728.  
  729. =item doctype_decl
  730.  
  731. Receive notification of a DOCTYPE declaration event.
  732.  
  733.  Name             The document type name.
  734.  SystemId         The document's system identifier.
  735.  PublicId         The document's public identifier, if any.
  736.  Internal         The internal subset as a string, if any.
  737.  
  738. Internal will contain all whitespace, comments, processing
  739. instructions, and declarations seen in the internal subset. The
  740. declarations will be there whether or not they have been processed by
  741. another handler (except for unparsed entities processed by the
  742. Unparsed handler).  However, comments and processing instructions will
  743. not appear if they've been processed by their respective handlers.
  744.  
  745. =item xml_decl
  746.  
  747. Receive notification of an XML declaration event.
  748.  
  749.  Version          The version.
  750.  Encoding         The encoding string, if any.
  751.  Standalone       True, false, or undefined if not declared.
  752.  
  753. =back
  754.  
  755. =head2 EntityResolver
  756.  
  757. =over 4
  758.  
  759. =item resolve_entity
  760.  
  761. Allow the handler to resolve external entities.
  762.  
  763.  Name             The notation name.
  764.  SystemId         The notation's system identifier.
  765.  PublicId         The notation's public identifier, if any.
  766.  Base             The base for resolving a relative URI, if any.
  767.  
  768. `C<resolve_entity()>' should return undef to request that the parser
  769. open a regular URI connection to the system identifier or a hash
  770. describing the new input source.  This hash has the same properties as
  771. the `C<Source>' parameter to `C<parse()>':
  772.  
  773.   PublicId    The public identifier of the external entity being
  774.               referenced, or undef if none was supplied. 
  775.   SystemId    The system identifier of the external entity being
  776.               referenced.
  777.   String      String containing XML text
  778.   ByteStream  An open file handle.
  779.   CharacterStream
  780.               An open file handle.
  781.   Encoding    The character encoding, if known.
  782.  
  783. =back
  784.  
  785. =head1 AUTHOR
  786.  
  787. Ken MacLeod, ken@bitsko.slc.ut.us
  788.  
  789. =head1 SEE ALSO
  790.  
  791. perl(1), PerlSAX.pod(3)
  792.  
  793.  Extensible Markup Language (XML) <http://www.w3c.org/XML/>
  794.  SAX 1.0: The Simple API for XML <http://www.megginson.com/SAX/>
  795.  
  796. =cut
  797.