diff options
author | Norbert Preining <preining@logic.at> | 2010-05-12 16:54:37 +0000 |
---|---|---|
committer | Norbert Preining <preining@logic.at> | 2010-05-12 16:54:37 +0000 |
commit | 661c41a09e39a182865e0b51e34cc995a0dc96e8 (patch) | |
tree | 2f79bb1406e22fdcb2587be8ffda6c0c609d7932 /Master/tlpkg/tlperl/lib/XML | |
parent | b645030efc22e13c2498a1522083634ab91b2de1 (diff) |
move tlperl.straw to tlperl
git-svn-id: svn://tug.org/texlive/trunk@18210 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlperl/lib/XML')
95 files changed, 22992 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML.pm b/Master/tlpkg/tlperl/lib/XML/LibXML.pm new file mode 100755 index 00000000000..37600cdaf93 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML.pm @@ -0,0 +1,2238 @@ +# $Id: LibXML.pm 809 2009-10-04 21:17:41Z pajas $ +# +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML; + +use strict; +use vars qw($VERSION $ABI_VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS + $skipDTD $skipXMLDeclaration $setTagCompression + $MatchCB $ReadCB $OpenCB $CloseCB %PARSER_FLAGS + ); +use Carp; + +use constant XML_XMLNS_NS => 'http://www.w3.org/2000/xmlns/'; +use constant XML_XML_NS => 'http://www.w3.org/XML/1998/namespace'; + +use XML::LibXML::Error; +use XML::LibXML::NodeList; +use XML::LibXML::XPathContext; +use IO::Handle; # for FH reads called as methods + +BEGIN { +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE +$ABI_VERSION = 2; +require Exporter; +require DynaLoader; +@ISA = qw(DynaLoader Exporter); + +use vars qw($__PROXY_NODE_REGISTRY $__threads_shared $__PROXY_NODE_REGISTRY_MUTEX $__loaded); + +sub VERSION { + my $class = shift; + my ($caller) = caller; + my $req_abi = $ABI_VERSION; + if (UNIVERSAL::can($caller,'REQUIRE_XML_LIBXML_ABI_VERSION')) { + $req_abi = $caller->REQUIRE_XML_LIBXML_ABI_VERSION(); + } elsif ($caller eq 'XML::LibXSLT') { + # XML::LibXSLT without REQUIRE_XML_LIBXML_ABI_VERSION is an old and incompatible version + $req_abi = 1; + } + unless ($req_abi == $ABI_VERSION) { + my $ver = @_ ? ' '.$_[0] : ''; + die ("This version of $caller requires XML::LibXML$ver (ABI $req_abi), which is incompatible with currently installed XML::LibXML $VERSION (ABI $ABI_VERSION). Please upgrade $caller, XML::LibXML, or both!"); + } + return $class->UNIVERSAL::VERSION(@_) +} + +#-------------------------------------------------------------------------# +# export information # +#-------------------------------------------------------------------------# +%EXPORT_TAGS = ( + all => [qw( + XML_ELEMENT_NODE + XML_ATTRIBUTE_NODE + XML_TEXT_NODE + XML_CDATA_SECTION_NODE + XML_ENTITY_REF_NODE + XML_ENTITY_NODE + XML_PI_NODE + XML_COMMENT_NODE + XML_DOCUMENT_NODE + XML_DOCUMENT_TYPE_NODE + XML_DOCUMENT_FRAG_NODE + XML_NOTATION_NODE + XML_HTML_DOCUMENT_NODE + XML_DTD_NODE + XML_ELEMENT_DECL + XML_ATTRIBUTE_DECL + XML_ENTITY_DECL + XML_NAMESPACE_DECL + XML_XINCLUDE_END + XML_XINCLUDE_START + encodeToUTF8 + decodeFromUTF8 + XML_XMLNS_NS + XML_XML_NS + )], + libxml => [qw( + XML_ELEMENT_NODE + XML_ATTRIBUTE_NODE + XML_TEXT_NODE + XML_CDATA_SECTION_NODE + XML_ENTITY_REF_NODE + XML_ENTITY_NODE + XML_PI_NODE + XML_COMMENT_NODE + XML_DOCUMENT_NODE + XML_DOCUMENT_TYPE_NODE + XML_DOCUMENT_FRAG_NODE + XML_NOTATION_NODE + XML_HTML_DOCUMENT_NODE + XML_DTD_NODE + XML_ELEMENT_DECL + XML_ATTRIBUTE_DECL + XML_ENTITY_DECL + XML_NAMESPACE_DECL + XML_XINCLUDE_END + XML_XINCLUDE_START + )], + encoding => [qw( + encodeToUTF8 + decodeFromUTF8 + )], + ns => [qw( + XML_XMLNS_NS + XML_XML_NS + )], + ); + +@EXPORT_OK = ( + @{$EXPORT_TAGS{all}}, + ); + +@EXPORT = ( + @{$EXPORT_TAGS{all}}, + ); + +#-------------------------------------------------------------------------# +# initialization of the global variables # +#-------------------------------------------------------------------------# +$skipDTD = 0; +$skipXMLDeclaration = 0; +$setTagCompression = 0; + +$MatchCB = undef; +$ReadCB = undef; +$OpenCB = undef; +$CloseCB = undef; + +# if ($threads::threads) { +# our $__THREADS_TID = 0; +# eval q{ +# use threads::shared; +# our $__PROXY_NODE_REGISTRY_MUTEX :shared = 0; +# }; +# die $@ if $@; +# } +#-------------------------------------------------------------------------# +# bootstrapping # +#-------------------------------------------------------------------------# +bootstrap XML::LibXML $VERSION; +undef &AUTOLOAD; + +*encodeToUTF8 = \&XML::LibXML::Common::encodeToUTF8; +*decodeFromUTF8 = \&XML::LibXML::Common::decodeFromUTF8; + +} # BEGIN + + +#-------------------------------------------------------------------------# +# libxml2 node names (see also XML::LibXML::Common # +#-------------------------------------------------------------------------# +use constant XML_ELEMENT_NODE => 1; +use constant XML_ATTRIBUTE_NODE => 2; +use constant XML_TEXT_NODE => 3; +use constant XML_CDATA_SECTION_NODE => 4; +use constant XML_ENTITY_REF_NODE => 5; +use constant XML_ENTITY_NODE => 6; +use constant XML_PI_NODE => 7; +use constant XML_COMMENT_NODE => 8; +use constant XML_DOCUMENT_NODE => 9; +use constant XML_DOCUMENT_TYPE_NODE => 10; +use constant XML_DOCUMENT_FRAG_NODE => 11; +use constant XML_NOTATION_NODE => 12; +use constant XML_HTML_DOCUMENT_NODE => 13; +use constant XML_DTD_NODE => 14; +use constant XML_ELEMENT_DECL => 15; +use constant XML_ATTRIBUTE_DECL => 16; +use constant XML_ENTITY_DECL => 17; +use constant XML_NAMESPACE_DECL => 18; +use constant XML_XINCLUDE_START => 19; +use constant XML_XINCLUDE_END => 20; + + +sub import { + my $package=shift; + if (grep /^:threads_shared$/, @_) { + require threads; + if (!defined($__threads_shared)) { + if (INIT_THREAD_SUPPORT()) { + eval q{ + use threads::shared; + share($__PROXY_NODE_REGISTRY_MUTEX); + }; + if ($@) { # something went wrong + DISABLE_THREAD_SUPPORT(); # leave the library in a usable state + die $@; # and die + } + $__PROXY_NODE_REGISTRY = XML::LibXML::HashTable->new(); + $__threads_shared=1; + } else { + croak("XML::LibXML or Perl compiled without ithread support!"); + } + } elsif (!$__threads_shared) { + croak("XML::LibXML already loaded without thread support. Too late to enable thread support!"); + } + } elsif (defined $XML::LibXML::__loaded) { + $__threads_shared=0 if not defined $__threads_shared; + } + __PACKAGE__->export_to_level(1,$package,grep !/^:threads(_shared)?$/,@_); +} + +sub threads_shared_enabled { + return $__threads_shared ? 1 : 0; +} + +# if ($threads::threads) { +# our $__PROXY_NODE_REGISTRY = XML::LibXML::HashTable->new(); +# } + +#-------------------------------------------------------------------------# +# test exact version (up to patch-level) # +#-------------------------------------------------------------------------# +{ + my ($runtime_version) = LIBXML_RUNTIME_VERSION() =~ /^(\d+)/; + if ( $runtime_version < LIBXML_VERSION ) { + warn "Warning: XML::LibXML compiled against libxml2 ".LIBXML_VERSION. + ", but runtime libxml2 is older $runtime_version\n"; + } +} + + +#-------------------------------------------------------------------------# +# parser flags # +#-------------------------------------------------------------------------# + +# Copied directly from http://xmlsoft.org/html/libxml-parser.html#xmlParserOption +use constant { + XML_PARSE_RECOVER => 1, # recover on errors + XML_PARSE_NOENT => 2, # substitute entities + XML_PARSE_DTDLOAD => 4, # load the external subset + XML_PARSE_DTDATTR => 8, # default DTD attributes + XML_PARSE_DTDVALID => 16, # validate with the DTD + XML_PARSE_NOERROR => 32, # suppress error reports + XML_PARSE_NOWARNING => 64, # suppress warning reports + XML_PARSE_PEDANTIC => 128, # pedantic error reporting + XML_PARSE_NOBLANKS => 256, # remove blank nodes + XML_PARSE_SAX1 => 512, # use the SAX1 interface internally + XML_PARSE_XINCLUDE => 1024, # Implement XInclude substitition + XML_PARSE_NONET => 2048, # Forbid network access + XML_PARSE_NODICT => 4096, # Do not reuse the context dictionnary + XML_PARSE_NSCLEAN => 8192, # remove redundant namespaces declarations + XML_PARSE_NOCDATA => 16384, # merge CDATA as text nodes + XML_PARSE_NOXINCNODE => 32768, # do not generate XINCLUDE START/END nodes + XML_PARSE_COMPACT => 65536, # compact small text nodes; no modification of the tree allowed afterwards + # (will possibly crash if you try to modify the tree) + XML_PARSE_OLD10 => 131072, # parse using XML-1.0 before update 5 + XML_PARSE_NOBASEFIX => 262144, # do not fixup XINCLUDE xml#base uris + XML_PARSE_HUGE => 524288, # relax any hardcoded limit from the parser + XML_PARSE_OLDSAX => 1048576, # parse using SAX2 interface from before 2.7.0 +}; + +use constant XML_LIBXML_PARSE_DEFAULTS => ( XML_PARSE_NODICT | XML_PARSE_HUGE | XML_PARSE_DTDLOAD | XML_PARSE_NOENT ); + +# this hash is made global so that applications can add names for new +# libxml2 parser flags as temporary workaround + +%PARSER_FLAGS = ( + recover => XML_PARSE_RECOVER, + expand_entities => XML_PARSE_NOENT, + load_ext_dtd => XML_PARSE_DTDLOAD, + complete_attributes => XML_PARSE_DTDATTR, + validation => XML_PARSE_DTDVALID, + suppress_errors => XML_PARSE_NOERROR, + suppress_warnings => XML_PARSE_NOWARNING, + pedantic_parser => XML_PARSE_PEDANTIC, + no_blanks => XML_PARSE_NOBLANKS, + expand_xinclude => XML_PARSE_XINCLUDE, + xinclude => XML_PARSE_XINCLUDE, + no_network => XML_PARSE_NONET, + clean_namespaces => XML_PARSE_NSCLEAN, + no_cdata => XML_PARSE_NOCDATA, + no_xinclude_nodes => XML_PARSE_NOXINCNODE, + old10 => XML_PARSE_OLD10, + no_base_fix => XML_PARSE_NOBASEFIX, + huge => XML_PARSE_HUGE, + oldsax => XML_PARSE_OLDSAX, +); + +my %OUR_FLAGS = ( + recover => 'XML_LIBXML_RECOVER', + line_numbers => 'XML_LIBXML_LINENUMBERS', + URI => 'XML_LIBXML_BASE_URI', + base_uri => 'XML_LIBXML_BASE_URI', + gdome => 'XML_LIBXML_GDOME', + ext_ent_handler => 'ext_ent_handler', +); + +sub _parser_options { + my ($self, $opts) = @_; + + # currently dictionaries break XML::LibXML memory management + + my $flags; + + if (ref($self)) { + $flags = ($self->{XML_LIBXML_PARSER_OPTIONS}||0); + } else { + $flags = XML_LIBXML_PARSE_DEFAULTS; # safety precaution + } + + my ($key, $value); + while (($key,$value) = each %$opts) { + my $f = $PARSER_FLAGS{ $key }; + if (defined $f) { + if ($value) { + $flags |= $f + } else { + $flags &= ~$f; + } + } elsif ($key eq 'set_parser_flags') { # this can be used to pass flags XML::LibXML does not yet know about + $flags |= $value; + } elsif ($key eq 'unset_parser_flags') { + $flags &= ~$value; + } + + } + return $flags; +} + +my %compatibility_flags = ( + XML_LIBXML_VALIDATION => 'validation', + XML_LIBXML_EXPAND_ENTITIES => 'expand_entities', + XML_LIBXML_PEDANTIC => 'pedantic_parser', + XML_LIBXML_NONET => 'no_network', + XML_LIBXML_EXT_DTD => 'load_ext_dtd', + XML_LIBXML_COMPLETE_ATTR => 'complete_attributes', + XML_LIBXML_EXPAND_XINCLUDE => 'expand_xinclude', + XML_LIBXML_NSCLEAN => 'clean_namespaces', + XML_LIBXML_KEEP_BLANKS => 'keep_blanks', + XML_LIBXML_LINENUMBERS => 'line_numbers', +); + +#-------------------------------------------------------------------------# +# parser constructor # +#-------------------------------------------------------------------------# + + +sub new { + my $class = shift; + my $self = bless { + }, $class; + if (@_) { + my %opts = (); + if (ref($_[0]) eq 'HASH') { + %opts = %{$_[0]}; + } else { + # old interface + my %args = @_; + %opts=( + map { + (($compatibility_flags{ $_ }||$_) => $args{ $_ }) + } keys %args + ); + } + # parser flags + $opts{no_blanks} = !$opts{keep_blanks} if exists($opts{keep_blanks}) and !exists($opts{no_blanks}); + + for (keys %OUR_FLAGS) { + $self->{$OUR_FLAGS{$_}} = delete $opts{$_}; + } + $class->load_catalog(delete($opts{catalog})) if $opts{catalog}; + + $self->{XML_LIBXML_PARSER_OPTIONS} = XML::LibXML->_parser_options(\%opts); + + # store remaining unknown options directly in $self + for (keys %opts) { + $self->{$_}=$opts{$_} unless exists $PARSER_FLAGS{$_}; + } + } else { + $self->{XML_LIBXML_PARSER_OPTIONS} = XML_LIBXML_PARSE_DEFAULTS; + } + if ( defined $self->{Handler} ) { + $self->set_handler( $self->{Handler} ); + } + + $self->{_State_} = 0; + return $self; +} + +sub _clone { + my ($self)=@_; + my $new = ref($self)->new({ + recover => $self->{XML_LIBXML_RECOVER}, + line_nubers => $self->{XML_LIBXML_LINENUMBERS}, + base_uri => $self->{XML_LIBXML_BASE_URI}, + gdome => $self->{XML_LIBXML_GDOME}, + set_parser_flags => $self->{XML_LIBXML_PARSER_OPTIONS}, + }); + return $new; +} + +#-------------------------------------------------------------------------# +# Threads support methods # +#-------------------------------------------------------------------------# + +# threads doc says CLONE's API may change in future, which would break +# an XS method prototype +sub CLONE { + if ($XML::LibXML::__threads_shared) { + XML::LibXML::_CLONE( $_[0] ); + } +} + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +sub __proxy_registry { + my ($class)=caller; + die "This version of $class uses API of XML::LibXML 1.66 which is not compatible with XML::LibXML $VERSION. Please upgrade $class!\n"; +} + +#-------------------------------------------------------------------------# +# DOM Level 2 document constructor # +#-------------------------------------------------------------------------# + +sub createDocument { + my $self = shift; + if (!@_ or $_[0] =~ m/^\d\.\d$/) { + # for backward compatibility + return XML::LibXML::Document->new(@_); + } + else { + # DOM API: createDocument(namespaceURI, qualifiedName, doctype?) + my $doc = XML::LibXML::Document-> new; + my $el = $doc->createElementNS(shift, shift); + $doc->setDocumentElement($el); + $doc->setExternalSubset(shift) if @_; + return $doc; + } +} + +#-------------------------------------------------------------------------# +# callback functions # +#-------------------------------------------------------------------------# + +sub input_callbacks { + my $self = shift; + my $icbclass = shift; + + if ( defined $icbclass ) { + $self->{XML_LIBXML_CALLBACK_STACK} = $icbclass; + } + return $self->{XML_LIBXML_CALLBACK_STACK}; +} + +sub match_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXML_MATCH_CB} = shift; + $self->{XML_LIBXML_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXML_MATCH_CB}; + } + else { + $MatchCB = shift if scalar @_; + return $MatchCB; + } +} + +sub read_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXML_READ_CB} = shift; + $self->{XML_LIBXML_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXML_READ_CB}; + } + else { + $ReadCB = shift if scalar @_; + return $ReadCB; + } +} + +sub close_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXML_CLOSE_CB} = shift; + $self->{XML_LIBXML_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXML_CLOSE_CB}; + } + else { + $CloseCB = shift if scalar @_; + return $CloseCB; + } +} + +sub open_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXML_OPEN_CB} = shift; + $self->{XML_LIBXML_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXML_OPEN_CB}; + } + else { + $OpenCB = shift if scalar @_; + return $OpenCB; + } +} + +sub callbacks { + my $self = shift; + if ( ref $self ) { + if (@_) { + my ($match, $open, $read, $close) = @_; + @{$self}{qw(XML_LIBXML_MATCH_CB XML_LIBXML_OPEN_CB XML_LIBXML_READ_CB XML_LIBXML_CLOSE_CB)} = ($match, $open, $read, $close); + $self->{XML_LIBXML_CALLBACK_STACK} = undef; + } + else { + return @{$self}{qw(XML_LIBXML_MATCH_CB XML_LIBXML_OPEN_CB XML_LIBXML_READ_CB XML_LIBXML_CLOSE_CB)}; + } + } + else { + if (@_) { + ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ) = @_; + } + else { + return ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ); + } + } +} + +#-------------------------------------------------------------------------# +# internal member variable manipulation # +#-------------------------------------------------------------------------# +sub __parser_option { + my ($self, $opt) = @_; + if (@_>2) { + if ($_[2]) { + $self->{XML_LIBXML_PARSER_OPTIONS} |= $opt; + return 1; + } else { + $self->{XML_LIBXML_PARSER_OPTIONS} &= ~$opt; + return 0; + } + } else { + return ($self->{XML_LIBXML_PARSER_OPTIONS} & $opt) ? 1 : 0; + } +} + +sub option_exists { + my ($self,$name)=@_; + return ($PARSER_FLAGS{$name} || $OUR_FLAGS{$name}) ? 1 : 0; +} +sub get_option { + my ($self,$name)=@_; + my $flag = $OUR_FLAGS{$name}; + return $self->{$flag} if $flag; + $flag = $PARSER_FLAGS{$name}; + return $self->__parser_option($flag) if $flag; + warn "XML::LibXML::get_option: unknown parser option $name\n"; + return undef; +} +sub set_option { + my ($self,$name,$value)=@_; + my $flag = $OUR_FLAGS{$name}; + return ($self->{$flag}=$value) if $flag; + $flag = $PARSER_FLAGS{$name}; + return $self->__parser_option($flag,$value) if $flag; + warn "XML::LibXML::get_option: unknown parser option $name\n"; + return undef; +} +sub set_options { + my $self=shift; + my $opts; + if (@_==1 and ref($_[0]) eq 'HASH') { + $opts = $_[0]; + } elsif (@_ % 2 == 0) { + $opts={@_}; + } else { + croak("Odd number of elements passed to set_options"); + } + $self->set_option($_=>$opts->{$_}) foreach keys %$opts; + return; +} + +sub validation { + my $self = shift; + return $self->__parser_option(XML_PARSE_DTDVALID,@_); +} + +sub recover { + my $self = shift; + if (scalar @_) { + $self->{XML_LIBXML_RECOVER} = $_[0]; + $self->__parser_option(XML_PARSE_RECOVER,@_); + } + return $self->{XML_LIBXML_RECOVER}; +} + +sub recover_silently { + my $self = shift; + my $arg = shift; + (($arg == 1) ? $self->recover(2) : $self->recover($arg)) if defined($arg); + return (($self->recover()||0) == 2) ? 1 : 0; +} + +sub expand_entities { + my $self = shift; + if (scalar(@_) and $_[0]) { + return $self->__parser_option(XML_PARSE_NOENT | XML_PARSE_DTDLOAD,1); + } + return $self->__parser_option(XML_PARSE_NOENT,@_); +} + +sub keep_blanks { + my $self = shift; + my @args; # we have to negate the argument and return negated value, since + # the actual flag is no_blanks + if (scalar @_) { + @args=($_[0] ? 0 : 1); + } + return $self->__parser_option(XML_PARSE_NOBLANKS,@args) ? 0 : 1; +} + +sub pedantic_parser { + my $self = shift; + return $self->__parser_option(XML_PARSE_PEDANTIC,@_); +} + +sub line_numbers { + my $self = shift; + $self->{XML_LIBXML_LINENUMBERS} = shift if scalar @_; + return $self->{XML_LIBXML_LINENUMBERS}; +} + +sub no_network { + my $self = shift; + return $self->__parser_option(XML_PARSE_NONET,@_); +} + +sub load_ext_dtd { + my $self = shift; + return $self->__parser_option(XML_PARSE_DTDLOAD,@_); +} + +sub complete_attributes { + my $self = shift; + return $self->__parser_option(XML_PARSE_DTDATTR,@_); +} + +sub expand_xinclude { + my $self = shift; + return $self->__parser_option(XML_PARSE_XINCLUDE,@_); +} + +sub base_uri { + my $self = shift; + $self->{XML_LIBXML_BASE_URI} = shift if scalar @_; + return $self->{XML_LIBXML_BASE_URI}; +} + +sub gdome_dom { + my $self = shift; + $self->{XML_LIBXML_GDOME} = shift if scalar @_; + return $self->{XML_LIBXML_GDOME}; +} + +sub clean_namespaces { + my $self = shift; + return $self->__parser_option(XML_PARSE_NSCLEAN,@_); +} + +#-------------------------------------------------------------------------# +# set the optional SAX(2) handler # +#-------------------------------------------------------------------------# +sub set_handler { + my $self = shift; + if ( defined $_[0] ) { + $self->{HANDLER} = $_[0]; + + $self->{SAX_ELSTACK} = []; + $self->{SAX} = {State => 0}; + } + else { + # undef SAX handling + $self->{SAX_ELSTACK} = []; + delete $self->{HANDLER}; + delete $self->{SAX}; + } +} + +#-------------------------------------------------------------------------# +# helper functions # +#-------------------------------------------------------------------------# +sub _auto_expand { + my ( $self, $result, $uri ) = @_; + + $result->setBaseURI( $uri ) if defined $uri; + + if ( $self->expand_xinclude ) { + $self->{_State_} = 1; + eval { $self->processXIncludes($result); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + $self->_cleanup_callbacks(); + $result = undef; + croak $err; + } + } + return $result; +} + +sub _init_callbacks { + my $self = shift; + my $icb = $self->{XML_LIBXML_CALLBACK_STACK}; + unless ( defined $icb ) { + $self->{XML_LIBXML_CALLBACK_STACK} = XML::LibXML::InputCallback->new(); + $icb = $self->{XML_LIBXML_CALLBACK_STACK}; + } + + my $mcb = $self->match_callback(); + my $ocb = $self->open_callback(); + my $rcb = $self->read_callback(); + my $ccb = $self->close_callback(); + + if ( defined $mcb and defined $ocb and defined $rcb and defined $ccb ) { + $icb->register_callbacks( [$mcb, $ocb, $rcb, $ccb] ); + } + $icb->init_callbacks(); +} + +sub _cleanup_callbacks { + my $self = shift; + $self->{XML_LIBXML_CALLBACK_STACK}->cleanup_callbacks(); + my $mcb = $self->match_callback(); + $self->{XML_LIBXML_CALLBACK_STACK}->unregister_callbacks( [$mcb] ); +} + +sub __read { + read($_[0], $_[1], $_[2]); +} + +sub __write { + if ( ref( $_[0] ) ) { + $_[0]->write( $_[1], $_[2] ); + } + else { + $_[0]->write( $_[1] ); + } +} + +sub load_xml { + my ($class_or_self) = shift; + my %args = map { ref($_) eq 'HASH' ? (%$_) : $_ } @_; + my $URI = delete($args{URI}); + $URI = "$URI" if defined $URI; # stringify in case it is an URI object + my $parser; + if (ref($class_or_self)) { + $parser = $class_or_self->_clone(); + $parser->{XML_LIBXML_PARSER_OPTIONS} = $parser->_parser_options(\%args); + } else { + $parser = $class_or_self->new(\%args); + } + my $dom; + if ( defined $args{location} ) { + $dom = $parser->parse_file( "$args{location}" ); + } + elsif ( defined $args{string} ) { + $dom = $parser->parse_string( $args{string}, $URI ); + } + elsif ( defined $args{IO} ) { + $dom = $parser->parse_fh( $args{IO}, $URI ); + } + else { + croak("XML::LibXML->load: specify location, string, or IO"); + } + return $dom; +} + +sub load_html { + my ($class_or_self) = shift; + my %args = map { ref($_) eq 'HASH' ? (%$_) : $_ } @_; + my $URI = delete($args{URI}); + $URI = "$URI" if defined $URI; # stringify in case it is an URI object + my $parser; + if (ref($class_or_self)) { + $parser = $class_or_self->_clone(); + } else { + $parser = $class_or_self->new(); + } + my $dom; + if ( defined $args{location} ) { + $dom = $parser->parse_html_file( "$args{location}", \%args ); + } + elsif ( defined $args{string} ) { + $dom = $parser->parse_html_string( $args{string}, \%args ); + } + elsif ( defined $args{IO} ) { + $dom = $parser->parse_html_fh( $args{IO}, \%args ); + } + else { + croak("XML::LibXML->load: specify location, string, or IO"); + } + return $dom; +} + +#-------------------------------------------------------------------------# +# parsing functions # +#-------------------------------------------------------------------------# +# all parsing functions handle normal as SAX parsing at the same time. +# note that SAX parsing is handled incomplete! use XML::LibXML::SAX for +# complete parsing sequences +#-------------------------------------------------------------------------# +sub parse_string { + my $self = shift; + croak("parse_string is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; + croak("parse already in progress") if $self->{_State_}; + + unless ( defined $_[0] and length $_[0] ) { + croak("Empty String"); + } + + $self->{_State_} = 1; + my $result; + + $self->_init_callbacks(); + + if ( defined $self->{SAX} ) { + my $string = shift; + $self->{SAX_ELSTACK} = []; + eval { $result = $self->_parse_sax_string($string); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + } + else { + eval { $result = $self->_parse_string( @_ ); }; + + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + + $result = $self->_auto_expand( $result, $self->{XML_LIBXML_BASE_URI} ); + } + $self->_cleanup_callbacks(); + + return $result; +} + +sub parse_fh { + my $self = shift; + croak("parse_fh is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; + croak("parse already in progress") if $self->{_State_}; + $self->{_State_} = 1; + my $result; + + $self->_init_callbacks(); + + if ( defined $self->{SAX} ) { + $self->{SAX_ELSTACK} = []; + eval { $self->_parse_sax_fh( @_ ); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + } + else { + eval { $result = $self->_parse_fh( @_ ); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + + $result = $self->_auto_expand( $result, $self->{XML_LIBXML_BASE_URI} ); + } + + $self->_cleanup_callbacks(); + + return $result; +} + +sub parse_file { + my $self = shift; + croak("parse_file is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; + croak("parse already in progress") if $self->{_State_}; + + $self->{_State_} = 1; + my $result; + + $self->_init_callbacks(); + + if ( defined $self->{SAX} ) { + $self->{SAX_ELSTACK} = []; + eval { $self->_parse_sax_file( @_ ); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + } + else { + eval { $result = $self->_parse_file(@_); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + + $result = $self->_auto_expand( $result ); + } + $self->_cleanup_callbacks(); + + return $result; +} + +sub parse_xml_chunk { + my $self = shift; + # max 2 parameter: + # 1: the chunk + # 2: the encoding of the string + croak("parse_xml_chunk is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; + croak("parse already in progress") if $self->{_State_}; my $result; + + unless ( defined $_[0] and length $_[0] ) { + croak("Empty String"); + } + + $self->{_State_} = 1; + + $self->_init_callbacks(); + + if ( defined $self->{SAX} ) { + eval { + $self->_parse_sax_xml_chunk( @_ ); + + # this is required for XML::GenericChunk. + # in normal case is_filter is not defined, an thus the parsing + # will be terminated. in case of a SAX filter the parsing is not + # finished at that state. therefore we must not reset the parsing + unless ( $self->{IS_FILTER} ) { + $result = $self->{HANDLER}->end_document(); + } + }; + } + else { + eval { $result = $self->_parse_xml_chunk( @_ ); }; + } + + $self->_cleanup_callbacks(); + + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + croak $err; + } + + return $result; +} + +sub parse_balanced_chunk { + my $self = shift; + $self->_init_callbacks(); + my $rv; + eval { + $rv = $self->parse_xml_chunk( @_ ); + }; + my $err = $@; + $self->_cleanup_callbacks(); + if ( $err ) { + chomp $err unless ref $err; + croak $err; + } + return $rv +} + +# java style +sub processXIncludes { + my $self = shift; + my $doc = shift; + my $opts = shift; + my $options = $self->_parser_options($opts); + if ( $self->{_State_} != 1 ) { + $self->_init_callbacks(); + } + my $rv; + eval { + $rv = $self->_processXIncludes($doc || " ", $options); + }; + my $err = $@; + if ( $self->{_State_} != 1 ) { + $self->_cleanup_callbacks(); + } + + if ( $err ) { + chomp $err unless ref $err; + croak $err; + } + return $rv; +} + +# perl style +sub process_xincludes { + my $self = shift; + my $doc = shift; + my $opts = shift; + my $options = $self->_parser_options($opts); + + my $rv; + $self->_init_callbacks(); + eval { + $rv = $self->_processXIncludes($doc || " ", $options); + }; + my $err = $@; + $self->_cleanup_callbacks(); + if ( $err ) { + chomp $err unless ref $err; + croak $@; + } + return $rv; +} + +#-------------------------------------------------------------------------# +# HTML parsing functions # +#-------------------------------------------------------------------------# + +sub _html_options { + my ($self,$opts)=@_; + $opts = {} unless ref $opts; + # return (undef,undef) unless ref $opts; + my $flags = 0; + $flags |= 1 if exists $opts->{recover} ? $opts->{recover} : $self->recover; + $flags |= 32 if $opts->{suppress_errors}; + $flags |= 64 if $opts->{suppress_warnings}; + $flags |= 128 if exists $opts->{pedantic_parser} ? $opts->{pedantic_parser} : $self->pedantic_parser; + $flags |= 256 if exists $opts->{no_blanks} ? $opts->{no_blanks} : !$self->keep_blanks; + $flags |= 2048 if exists $opts->{no_network} ? $opts->{no_network} : !$self->no_network; + $flags |= 16384 if $opts->{no_cdata}; + $flags |= 65536 if $opts->{compact}; # compact small text nodes; no modification + # of the tree allowed afterwards + # (WILL possibly CRASH IF YOU try to MODIFY THE TREE) + $flags |= 524288 if $opts->{huge}; # relax any hardcoded limit from the parser + $flags |= 1048576 if $opts->{oldsax}; # parse using SAX2 interface from before 2.7.0 + + return ($opts->{URI},$opts->{encoding},$flags); +} + +sub parse_html_string { + my ($self,$str,$opts) = @_; + croak("parse_html_string is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; + croak("parse already in progress") if $self->{_State_}; + + unless ( defined $str and length $str ) { + croak("Empty String"); + } + $self->{_State_} = 1; + my $result; + + $self->_init_callbacks(); + eval { + $result = $self->_parse_html_string( $str, + $self->_html_options($opts) + ); + }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + + $self->_cleanup_callbacks(); + + return $result; +} + +sub parse_html_file { + my ($self,$file,$opts) = @_; + croak("parse_html_file is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; + croak("parse already in progress") if $self->{_State_}; + $self->{_State_} = 1; + my $result; + + $self->_init_callbacks(); + eval { $result = $self->_parse_html_file($file, + $self->_html_options($opts) + ); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + + $self->_cleanup_callbacks(); + + return $result; +} + +sub parse_html_fh { + my ($self,$fh,$opts) = @_; + croak("parse_html_fh is not a class method! Create a parser object with XML::LibXML->new first!") unless ref $self; + croak("parse already in progress") if $self->{_State_}; + $self->{_State_} = 1; + + my $result; + $self->_init_callbacks(); + eval { $result = $self->_parse_html_fh( $fh, + $self->_html_options($opts) + ); }; + my $err = $@; + $self->{_State_} = 0; + if ($err) { + chomp $err unless ref $err; + $self->_cleanup_callbacks(); + croak $err; + } + $self->_cleanup_callbacks(); + + return $result; +} + +#-------------------------------------------------------------------------# +# push parser interface # +#-------------------------------------------------------------------------# +sub init_push { + my $self = shift; + + if ( defined $self->{CONTEXT} ) { + delete $self->{CONTEXT}; + } + + if ( defined $self->{SAX} ) { + $self->{CONTEXT} = $self->_start_push(1); + } + else { + $self->{CONTEXT} = $self->_start_push(0); + } +} + +sub push { + my $self = shift; + + $self->_init_callbacks(); + + if ( not defined $self->{CONTEXT} ) { + $self->init_push(); + } + + eval { + foreach ( @_ ) { + $self->_push( $self->{CONTEXT}, $_ ); + } + }; + my $err = $@; + $self->_cleanup_callbacks(); + if ( $err ) { + chomp $err unless ref $err; + croak $err; + } +} + +# this function should be promoted! +# the reason is because libxml2 uses xmlParseChunk() for this purpose! +sub parse_chunk { + my $self = shift; + my $chunk = shift; + my $terminate = shift; + + if ( not defined $self->{CONTEXT} ) { + $self->init_push(); + } + + if ( defined $chunk and length $chunk ) { + $self->_push( $self->{CONTEXT}, $chunk ); + } + + if ( $terminate ) { + return $self->finish_push(); + } +} + + +sub finish_push { + my $self = shift; + my $restore = shift || 0; + return undef unless defined $self->{CONTEXT}; + + my $retval; + + if ( defined $self->{SAX} ) { + eval { + $self->_end_sax_push( $self->{CONTEXT} ); + $retval = $self->{HANDLER}->end_document( {} ); + }; + } + else { + eval { $retval = $self->_end_push( $self->{CONTEXT}, $restore ); }; + } + my $err = $@; + delete $self->{CONTEXT}; + if ( $err ) { + chomp $err unless ref $err; + croak( $err ); + } + return $retval; +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Node Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::Node; + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +sub isSupported { + my $self = shift; + my $feature = shift; + return $self->can($feature) ? 1 : 0; +} + +sub getChildNodes { my $self = shift; return $self->childNodes(); } + +sub childNodes { + my $self = shift; + my @children = $self->_childNodes(0); + return wantarray ? @children : XML::LibXML::NodeList->new_from_ref(\@children , 1); +} + +sub nonBlankChildNodes { + my $self = shift; + my @children = $self->_childNodes(1); + return wantarray ? @children : XML::LibXML::NodeList->new_from_ref(\@children , 1); +} + +sub attributes { + my $self = shift; + my @attr = $self->_attributes(); + return wantarray ? @attr : XML::LibXML::NamedNodeMap->new( @attr ); +} + + +sub findnodes { + my ($node, $xpath) = @_; + my @nodes = $node->_findnodes($xpath); + if (wantarray) { + return @nodes; + } + else { + return XML::LibXML::NodeList->new_from_ref(\@nodes, 1); + } +} + +sub exists { + my ($node, $xpath) = @_; + my (undef, $value) = $node->_find($xpath,1); + return $value; +} + +sub findvalue { + my ($node, $xpath) = @_; + my $res; + $res = $node->find($xpath); + return $res->to_literal->value; +} + +sub findbool { + my ($node, $xpath) = @_; + my ($type, @params) = $node->_find($xpath,1); + if ($type) { + return $type->new(@params); + } + return undef; +} + +sub find { + my ($node, $xpath) = @_; + my ($type, @params) = $node->_find($xpath,0); + if ($type) { + return $type->new(@params); + } + return undef; +} + +sub setOwnerDocument { + my ( $self, $doc ) = @_; + $doc->adoptNode( $self ); +} + +sub toStringC14N { + my ($self, $comments, $xpath, $xpc) = @_; + return $self->_toStringC14N( $comments || 0, + (defined $xpath ? $xpath : undef), + 0, + undef, + (defined $xpc ? $xpc : undef) + ); +} +sub toStringEC14N { + my ($self, $comments, $xpath, $xpc, $inc_prefix_list) = @_; + unless (UNIVERSAL::isa($xpc,'XML::LibXML::XPathContext')) { + if ($inc_prefix_list) { + croak("toStringEC14N: 3rd argument is not an XML::LibXML::XPathContext"); + } else { + $inc_prefix_list=$xpc; + $xpc=undef; + } + } + if (defined($inc_prefix_list) and !UNIVERSAL::isa($inc_prefix_list,'ARRAY')) { + croak("toStringEC14N: inclusive_prefix_list must be undefined or ARRAY"); + } + return $self->_toStringC14N( $comments || 0, + (defined $xpath ? $xpath : undef), + 1, + (defined $inc_prefix_list ? $inc_prefix_list : undef), + (defined $xpc ? $xpc : undef) + ); +} + +*serialize_c14n = \&toStringC14N; +*serialize_exc_c14n = \&toStringEC14N; + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Document Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::Document; + +use vars qw(@ISA); +@ISA = ('XML::LibXML::Node'); + +sub actualEncoding { + my $doc = shift; + my $enc = $doc->encoding; + return (defined $enc and length $enc) ? $enc : 'UTF-8'; +} + +sub setDocumentElement { + my $doc = shift; + my $element = shift; + + my $oldelem = $doc->documentElement; + if ( defined $oldelem ) { + $doc->removeChild($oldelem); + } + + $doc->_setDocumentElement($element); +} + +sub toString { + my $self = shift; + my $flag = shift; + + my $retval = ""; + + if ( defined $XML::LibXML::skipXMLDeclaration + and $XML::LibXML::skipXMLDeclaration == 1 ) { + foreach ( $self->childNodes ){ + next if $_->nodeType == XML::LibXML::XML_DTD_NODE() + and $XML::LibXML::skipDTD; + $retval .= $_->toString; + } + } + else { + $flag ||= 0 unless defined $flag; + $retval = $self->_toString($flag); + } + + return $retval; +} + +sub serialize { + my $self = shift; + return $self->toString( @_ ); +} + +#-------------------------------------------------------------------------# +# bad style xinclude processing # +#-------------------------------------------------------------------------# +sub process_xinclude { + my $self = shift; + my $opts = shift; + XML::LibXML->new->processXIncludes( $self, $opts ); +} + +sub insertProcessingInstruction { + my $self = shift; + my $target = shift; + my $data = shift; + + my $pi = $self->createPI( $target, $data ); + my $root = $self->documentElement; + + if ( defined $root ) { + # this is actually not correct, but i guess it's what the user + # intends + $self->insertBefore( $pi, $root ); + } + else { + # if no documentElement was found we just append the PI + $self->appendChild( $pi ); + } +} + +sub insertPI { + my $self = shift; + $self->insertProcessingInstruction( @_ ); +} + +#-------------------------------------------------------------------------# +# DOM L3 Document functions. +# added after robins implicit feature requst +#-------------------------------------------------------------------------# +*getElementsByTagName = \&XML::LibXML::Element::getElementsByTagName; +*getElementsByTagNameNS = \&XML::LibXML::Element::getElementsByTagNameNS; +*getElementsByLocalName = \&XML::LibXML::Element::getElementsByLocalName; + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::DocumentFragment Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::DocumentFragment; + +use vars qw(@ISA); +@ISA = ('XML::LibXML::Node'); + +sub toString { + my $self = shift; + my $retval = ""; + if ( $self->hasChildNodes() ) { + foreach my $n ( $self->childNodes() ) { + $retval .= $n->toString(@_); + } + } + return $retval; +} + +*serialize = \&toString; + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Element Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::Element; + +use vars qw(@ISA); +@ISA = ('XML::LibXML::Node'); +use XML::LibXML qw(:ns :libxml); +use Carp; + +sub setNamespace { + my $self = shift; + my $n = $self->nodeName; + if ( $self->_setNamespace(@_) ){ + if ( scalar @_ < 3 || $_[2] == 1 ){ + $self->setNodeName( $n ); + } + return 1; + } + return 0; +} + +sub getAttribute { + my $self = shift; + my $name = $_[0]; + if ( $name =~ /^xmlns(?::|$)/ ) { + # user wants to get a namespace ... + (my $prefix = $name )=~s/^xmlns:?//; + $self->_getNamespaceDeclURI($prefix); + } + else { + $self->_getAttribute(@_); + } +} + +sub setAttribute { + my ( $self, $name, $value ) = @_; + if ( $name =~ /^xmlns(?::|$)/ ) { + # user wants to set the special attribute for declaring XML namespace ... + + # this is fine but not exactly DOM conformant behavior, btw (according to DOM we should + # probably declare an attribute which looks like XML namespace declaration + # but isn't) + (my $nsprefix = $name )=~s/^xmlns:?//; + my $nn = $self->nodeName; + if ( $nn =~ /^\Q${nsprefix}\E:/ ) { + # the element has the same prefix + $self->setNamespaceDeclURI($nsprefix,$value) || + $self->setNamespace($value,$nsprefix,1); + ## + ## We set the namespace here. + ## This is helpful, as in: + ## + ## | $e = XML::LibXML::Element->new('foo:bar'); + ## | $e->setAttribute('xmlns:foo','http://yoyodine') + ## + } + else { + # just modify the namespace + $self->setNamespaceDeclURI($nsprefix, $value) || + $self->setNamespace($value,$nsprefix,0); + } + } + else { + $self->_setAttribute($name, $value); + } +} + +sub getAttributeNS { + my $self = shift; + my ($nsURI, $name) = @_; + croak("invalid attribute name") if !defined($name) or $name eq q{}; + if ( defined($nsURI) and $nsURI eq XML_XMLNS_NS ) { + $self->_getNamespaceDeclURI($name eq 'xmlns' ? undef : $name); + } + else { + $self->_getAttributeNS(@_); + } +} + +sub setAttributeNS { + my ($self, $nsURI, $qname, $value)=@_; + unless (defined $qname and length $qname) { + croak("bad name"); + } + if (defined($nsURI) and $nsURI eq XML_XMLNS_NS) { + if ($qname !~ /^xmlns(?::|$)/) { + croak("NAMESPACE ERROR: Namespace declartions must have the prefix 'xmlns'"); + } + $self->setAttribute($qname,$value); # see implementation above + return; + } + if ($qname=~/:/ and not (defined($nsURI) and length($nsURI))) { + croak("NAMESPACE ERROR: Attribute without a prefix cannot be in a namespace"); + } + if ($qname=~/^xmlns(?:$|:)/) { + croak("NAMESPACE ERROR: 'xmlns' prefix and qualified-name are reserved for the namespace ".XML_XMLNS_NS); + } + if ($qname=~/^xml:/ and not (defined $nsURI and $nsURI eq XML_XML_NS)) { + croak("NAMESPACE ERROR: 'xml' prefix is reserved for the namespace ".XML_XML_NS); + } + $self->_setAttributeNS( defined $nsURI ? $nsURI : undef, $qname, $value ); +} + +sub getElementsByTagName { + my ( $node , $name ) = @_; + my $xpath = $name eq '*' ? "descendant::*" : "descendant::*[name()='$name']"; + my @nodes = $node->_findnodes($xpath); + return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); +} + +sub getElementsByTagNameNS { + my ( $node, $nsURI, $name ) = @_; + my $xpath; + if ( $name eq '*' ) { + if ( $nsURI eq '*' ) { + $xpath = "descendant::*"; + } else { + $xpath = "descendant::*[namespace-uri()='$nsURI']"; + } + } elsif ( $nsURI eq '*' ) { + $xpath = "descendant::*[local-name()='$name']"; + } else { + $xpath = "descendant::*[local-name()='$name' and namespace-uri()='$nsURI']"; + } + my @nodes = $node->_findnodes($xpath); + return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); +} + +sub getElementsByLocalName { + my ( $node,$name ) = @_; + my $xpath; + if ($name eq '*') { + $xpath = "descendant::*"; + } else { + $xpath = "descendant::*[local-name()='$name']"; + } + my @nodes = $node->_findnodes($xpath); + return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); +} + +sub getChildrenByTagName { + my ( $node, $name ) = @_; + my @nodes; + if ($name eq '*') { + @nodes = grep { $_->nodeType == XML_ELEMENT_NODE() } + $node->childNodes(); + } else { + @nodes = grep { $_->nodeName eq $name } $node->childNodes(); + } + return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); +} + +sub getChildrenByLocalName { + my ( $node, $name ) = @_; + # my @nodes; + # if ($name eq '*') { + # @nodes = grep { $_->nodeType == XML_ELEMENT_NODE() } + # $node->childNodes(); + # } else { + # @nodes = grep { $_->nodeType == XML_ELEMENT_NODE() and + # $_->localName eq $name } $node->childNodes(); + # } + # return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); + my @nodes = $node->_getChildrenByTagNameNS('*',$name); + return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); +} + +sub getChildrenByTagNameNS { + my ( $node, $nsURI, $name ) = @_; + my @nodes = $node->_getChildrenByTagNameNS($nsURI,$name); + return wantarray ? @nodes : XML::LibXML::NodeList->new_from_ref(\@nodes, 1); +} + +sub appendWellBalancedChunk { + my ( $self, $chunk ) = @_; + + my $local_parser = XML::LibXML->new(); + my $frag = $local_parser->parse_xml_chunk( $chunk ); + + $self->appendChild( $frag ); +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Text Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::Text; + +use vars qw(@ISA); +@ISA = ('XML::LibXML::Node'); + +sub attributes { return undef; } + +sub deleteDataString { + my $node = shift; + my $string = shift; + my $all = shift; + my $data = $node->nodeValue(); + $string =~ s/([\\\*\+\^\{\}\&\?\[\]\(\)\$\%\@])/\\$1/g; + if ( $all ) { + $data =~ s/$string//g; + } + else { + $data =~ s/$string//; + } + $node->setData( $data ); +} + +sub replaceDataString { + my ( $node, $left, $right,$all ) = @_; + + #ashure we exchange the strings and not expressions! + $left =~ s/([\\\*\+\^\{\}\&\?\[\]\(\)\$\%\@])/\\$1/g; + my $datastr = $node->nodeValue(); + if ( $all ) { + $datastr =~ s/$left/$right/g; + } + else{ + $datastr =~ s/$left/$right/; + } + $node->setData( $datastr ); +} + +sub replaceDataRegEx { + my ( $node, $leftre, $rightre, $flags ) = @_; + return unless defined $leftre; + $rightre ||= ""; + + my $datastr = $node->nodeValue(); + my $restr = "s/" . $leftre . "/" . $rightre . "/"; + $restr .= $flags if defined $flags; + + eval '$datastr =~ '. $restr; + + $node->setData( $datastr ); +} + +1; + +package XML::LibXML::Comment; + +use vars qw(@ISA); +@ISA = ('XML::LibXML::Text'); + +1; + +package XML::LibXML::CDATASection; + +use vars qw(@ISA); +@ISA = ('XML::LibXML::Text'); + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Attribute Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::Attr; +use vars qw( @ISA ) ; +@ISA = ('XML::LibXML::Node') ; + +sub setNamespace { + my ($self,$href,$prefix) = @_; + my $n = $self->nodeName; + if ( $self->_setNamespace($href,$prefix) ) { + $self->setNodeName($n); + return 1; + } + + return 0; +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Dtd Interface # +#-------------------------------------------------------------------------# +# this is still under construction +# +package XML::LibXML::Dtd; +use vars qw( @ISA ); +@ISA = ('XML::LibXML::Node'); + +# at least DESTROY and CLONE_SKIP must be inherited + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::PI Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::PI; +use vars qw( @ISA ); +@ISA = ('XML::LibXML::Node'); + +sub setData { + my $pi = shift; + + my $string = ""; + if ( scalar @_ == 1 ) { + $string = shift; + } + else { + my %h = @_; + $string = join " ", map {$_.'="'.$h{$_}.'"'} keys %h; + } + + # the spec says any char but "?>" [17] + $pi->_setData( $string ) unless $string =~ /\?>/; +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Namespace Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::Namespace; + +sub CLONE_SKIP { 1 } + +# this is infact not a node! +sub prefix { return "xmlns"; } +sub getPrefix { return "xmlns"; } +sub getNamespaceURI { return "http://www.w3.org/2000/xmlns/" }; + +sub getNamespaces { return (); } + +sub nodeName { + my $self = shift; + my $nsP = $self->localname; + return ( defined($nsP) && length($nsP) ) ? "xmlns:$nsP" : "xmlns"; +} +sub name { goto &nodeName } +sub getName { goto &nodeName } + +sub isEqualNode { + my ( $self, $ref ) = @_; + if ( ref($ref) eq "XML::LibXML::Namespace" ) { + return $self->_isEqual($ref); + } + return 0; +} + +sub isSameNode { + my ( $self, $ref ) = @_; + if ( $$self == $$ref ){ + return 1; + } + return 0; +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::NamedNodeMap Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::NamedNodeMap; + +use XML::LibXML qw(:libxml); + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +sub new { + my $class = shift; + my $self = bless { Nodes => [@_] }, $class; + $self->{NodeMap} = { map { $_->nodeName => $_ } @_ }; + return $self; +} + +sub length { return scalar( @{$_[0]->{Nodes}} ); } +sub nodes { return $_[0]->{Nodes}; } +sub item { $_[0]->{Nodes}->[$_[1]]; } + +sub getNamedItem { + my $self = shift; + my $name = shift; + + return $self->{NodeMap}->{$name}; +} + +sub setNamedItem { + my $self = shift; + my $node = shift; + + my $retval; + if ( defined $node ) { + if ( scalar @{$self->{Nodes}} ) { + my $name = $node->nodeName(); + if ( $node->nodeType() == XML_NAMESPACE_DECL ) { + return; + } + if ( defined $self->{NodeMap}->{$name} ) { + if ( $node->isSameNode( $self->{NodeMap}->{$name} ) ) { + return; + } + $retval = $self->{NodeMap}->{$name}->replaceNode( $node ); + } + else { + $self->{Nodes}->[0]->addSibling($node); + } + + $self->{NodeMap}->{$name} = $node; + push @{$self->{Nodes}}, $node; + } + else { + # not done yet + # can this be properly be done??? + warn "not done yet\n"; + } + } + return $retval; +} + +sub removeNamedItem { + my $self = shift; + my $name = shift; + my $retval; + if ( $name =~ /^xmlns/ ) { + warn "not done yet\n"; + } + elsif ( exists $self->{NodeMap}->{$name} ) { + $retval = $self->{NodeMap}->{$name}; + $retval->unbindNode; + delete $self->{NodeMap}->{$name}; + $self->{Nodes} = [grep {not($retval->isSameNode($_))} @{$self->{Nodes}}]; + } + + return $retval; +} + +sub getNamedItemNS { + my $self = shift; + my $nsURI = shift; + my $name = shift; + return undef; +} + +sub setNamedItemNS { + my $self = shift; + my $nsURI = shift; + my $node = shift; + return undef; +} + +sub removeNamedItemNS { + my $self = shift; + my $nsURI = shift; + my $name = shift; + return undef; +} + +1; + +package XML::LibXML::_SAXParser; + +# this is pseudo class!!! and it will be removed as soon all functions +# moved to XS level + +use XML::SAX::Exception; + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +# these functions will use SAX exceptions as soon i know how things really work +sub warning { + my ( $parser, $message, $line, $col ) = @_; + my $error = XML::SAX::Exception::Parse->new( LineNumber => $line, + ColumnNumber => $col, + Message => $message, ); + $parser->{HANDLER}->warning( $error ); +} + +sub error { + my ( $parser, $message, $line, $col ) = @_; + + my $error = XML::SAX::Exception::Parse->new( LineNumber => $line, + ColumnNumber => $col, + Message => $message, ); + $parser->{HANDLER}->error( $error ); +} + +sub fatal_error { + my ( $parser, $message, $line, $col ) = @_; + my $error = XML::SAX::Exception::Parse->new( LineNumber => $line, + ColumnNumber => $col, + Message => $message, ); + $parser->{HANDLER}->fatal_error( $error ); +} + +1; + +package XML::LibXML::RelaxNG; + +sub CLONE_SKIP { 1 } + +sub new { + my $class = shift; + my %args = @_; + + my $self = undef; + if ( defined $args{location} ) { + $self = $class->parse_location( $args{location} ); + } + elsif ( defined $args{string} ) { + $self = $class->parse_buffer( $args{string} ); + } + elsif ( defined $args{DOM} ) { + $self = $class->parse_document( $args{DOM} ); + } + + return $self; +} + +1; + +package XML::LibXML::Schema; + +sub CLONE_SKIP { 1 } + +sub new { + my $class = shift; + my %args = @_; + + my $self = undef; + if ( defined $args{location} ) { + $self = $class->parse_location( $args{location} ); + } + elsif ( defined $args{string} ) { + $self = $class->parse_buffer( $args{string} ); + } + + return $self; +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::Pattern Interface # +#-------------------------------------------------------------------------# + +package XML::LibXML::Pattern; + +sub CLONE_SKIP { 1 } + +sub new { + my $class = shift; + my ($pattern,$ns_map)=@_; + my $self = undef; + + unless (UNIVERSAL::can($class,'_compilePattern')) { + croak("Cannot create XML::LibXML::Pattern - ". + "your libxml2 is compiled without pattern support!"); + } + + if (ref($ns_map) eq 'HASH') { + # translate prefix=>URL hash to a (URL,prefix) list + $self = $class->_compilePattern($pattern,0,[reverse %$ns_map]); + } else { + $self = $class->_compilePattern($pattern,0); + } + return $self; +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::RegExp Interface # +#-------------------------------------------------------------------------# + +package XML::LibXML::RegExp; + +sub CLONE_SKIP { 1 } + +sub new { + my $class = shift; + my ($regexp)=@_; + unless (UNIVERSAL::can($class,'_compile')) { + croak("Cannot create XML::LibXML::RegExp - ". + "your libxml2 is compiled without regexp support!"); + } + return $class->_compile($regexp); +} + +1; + +#-------------------------------------------------------------------------# +# XML::LibXML::XPathExpression Interface # +#-------------------------------------------------------------------------# + +package XML::LibXML::XPathExpression; + +sub CLONE_SKIP { 1 } + +1; + + +#-------------------------------------------------------------------------# +# XML::LibXML::InputCallback Interface # +#-------------------------------------------------------------------------# +package XML::LibXML::InputCallback; + +use vars qw($_CUR_CB @_GLOBAL_CALLBACKS @_CB_STACK); + +BEGIN { + $_CUR_CB = undef; + @_GLOBAL_CALLBACKS = (); + @_CB_STACK = (); +} + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +#-------------------------------------------------------------------------# +# global callbacks # +#-------------------------------------------------------------------------# +sub _callback_match { + my $uri = shift; + my $retval = 0; + + # loop through the callbacks and and find the first matching + # The callbacks are stored in execution order (reverse stack order) + # any new global callbacks are shifted to the callback stack. + foreach my $cb ( @_GLOBAL_CALLBACKS ) { + + # callbacks have to return 1, 0 or undef, while 0 and undef + # are handled the same way. + # in fact, if callbacks return other values, the global match + # assumes silently that the callback failed. + + $retval = $cb->[0]->($uri); + + if ( defined $retval and $retval == 1 ) { + # make the other callbacks use this callback + $_CUR_CB = $cb; + unshift @_CB_STACK, $cb; + last; + } + } + + return $retval; +} + +sub _callback_open { + my $uri = shift; + my $retval = undef; + + # the open callback has to return a defined value. + # if one works on files this can be a file handle. But + # depending on the needs of the callback it also can be a + # database handle or a integer labeling a certain dataset. + + if ( defined $_CUR_CB ) { + $retval = $_CUR_CB->[1]->( $uri ); + + # reset the callbacks, if one callback cannot open an uri + if ( not defined $retval or $retval == 0 ) { + shift @_CB_STACK; + $_CUR_CB = $_CB_STACK[0]; + } + } + + return $retval; +} + +sub _callback_read { + my $fh = shift; + my $buflen = shift; + + my $retval = undef; + + if ( defined $_CUR_CB ) { + $retval = $_CUR_CB->[2]->( $fh, $buflen ); + } + + return $retval; +} + +sub _callback_close { + my $fh = shift; + my $retval = 0; + + if ( defined $_CUR_CB ) { + $retval = $_CUR_CB->[3]->( $fh ); + shift @_CB_STACK; + $_CUR_CB = $_CB_STACK[0]; + } + + return $retval; +} + +#-------------------------------------------------------------------------# +# member functions and methods # +#-------------------------------------------------------------------------# + +sub new { + my $CLASS = shift; + return bless {'_CALLBACKS' => []}, $CLASS; +} + +# add a callback set to the callback stack +# synopsis: $icb->register_callbacks( [$match_cb, $open_cb, $read_cb, $close_cb] ); +sub register_callbacks { + my $self = shift; + my $cbset = shift; + + # test if callback set is complete + if ( ref $cbset eq "ARRAY" and scalar( @$cbset ) == 4 ) { + unshift @{$self->{_CALLBACKS}}, $cbset; + } +} + +# remove a callback set to the callback stack +# if a callback set is passed, this function will check for the match function +sub unregister_callbacks { + my $self = shift; + my $cbset = shift; + if ( ref $cbset eq "ARRAY" and scalar( @$cbset ) == 4 ) { + $self->{_CALLBACKS} = [grep { $_->[0] != $cbset->[0] } @{$self->{_CALLBACKS}}]; + } + else { + shift @{$self->{_CALLBACKS}}; + } +} + +# make libxml2 use the callbacks +sub init_callbacks { + my $self = shift; + + $_CUR_CB = undef; + @_CB_STACK = (); + + @_GLOBAL_CALLBACKS = @{ $self->{_CALLBACKS} }; + + if ( defined $XML::LibXML::match_cb and + defined $XML::LibXML::open_cb and + defined $XML::LibXML::read_cb and + defined $XML::LibXML::close_cb ) { + push @_GLOBAL_CALLBACKS, [$XML::LibXML::match_cb, + $XML::LibXML::open_cb, + $XML::LibXML::read_cb, + $XML::LibXML::close_cb]; + } + + $self->lib_init_callbacks(); +} + +# reset libxml2's callbacks +sub cleanup_callbacks { + my $self = shift; + + $_CUR_CB = undef; + @_GLOBAL_CALLBACKS = (); + @_CB_STACK = (); + + $self->lib_cleanup_callbacks(); +} + +$XML::LibXML::__loaded=1; + +1; + +__END__ diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML.pod b/Master/tlpkg/tlperl/lib/XML/LibXML.pod new file mode 100755 index 00000000000..73bf58b69f5 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML.pod @@ -0,0 +1,515 @@ +=head1 NAME + +XML::LibXML - Perl Binding for libxml2 + +=head1 SYNOPSIS + + + + use XML::LibXML; + my $dom = XML::LibXML->load_xml(string => <<'EOT'); + <some-xml/> + EOT + + $Version_String = XML::LibXML::LIBXML_DOTTED_VERSION; + $Version_ID = XML::LibXML::LIBXML_VERSION; + $DLL_Version = XML::LibXML::LIBXML_RUNTIME_VERSION; + $libxmlnode = XML::LibXML->import_GDOME( $node, $deep ); + $gdomenode = XML::LibXML->export_GDOME( $node, $deep ); + +=head1 DESCRIPTION + +This module is an interface to libxml2, providing XML and HTML parsers with +DOM, SAX and XMLReader interfaces, a large subset of DOM Layer 3 interface and +a XML::XPath-like interface to XPath API of libxml2. The module is split into +several packages which are not described in this section; unless stated +otherwise, you only need to C<<<<<< use XML::LibXML; >>>>>> in your programs. + +For further information, please check the following documentation: + +=over 4 + +=item L<<<<<< XML::LibXML::Parser >>>>>> + +Parsing XML files with XML::LibXML + + +=item L<<<<<< XML::LibXML::DOM >>>>>> + +XML::LibXML Document Object Model (DOM) Implementation + + +=item L<<<<<< XML::LibXML::SAX >>>>>> + +XML::LibXML direct SAX parser + + +=item L<<<<<< XML::LibXML::Reader >>>>>> + +Reading XML with a pull-parser + + +=item L<<<<<< XML::LibXML::Dtd >>>>>> + +XML::LibXML frontend for DTD validation + + +=item L<<<<<< XML::LibXML::RelaxNG >>>>>> + +XML::LibXML frontend for RelaxNG schema validation + + +=item L<<<<<< XML::LibXML::Schema >>>>>> + +XML::LibXML frontend for W3C Schema schema validation + + +=item L<<<<<< XML::LibXML::XPathContext >>>>>> + +API for evaluating XPath expressions with enhanced support for the evaluation +context + + +=item L<<<<<< XML::LibXML::InputCallback >>>>>> + +Implementing custom URI Resolver and input callbacks + + +=item L<<<<<< XML::LibXML::Common >>>>>> + +Common functions for XML::LibXML related Classes + + + +=back + +The nodes in the Document Object Model (DOM) are represented by the following +classes (most of which "inherit" from L<<<<<< XML::LibXML::Node >>>>>>): + +=over 4 + +=item L<<<<<< XML::LibXML::Document >>>>>> + +XML::LibXML class for DOM document nodes + + +=item L<<<<<< XML::LibXML::Node >>>>>> + +Abstract base class for XML::LibXML DOM nodes + + +=item L<<<<<< XML::LibXML::Element >>>>>> + +XML::LibXML class for DOM element nodes + + +=item L<<<<<< XML::LibXML::Text >>>>>> + +XML::LibXML class for DOM text nodes + + +=item L<<<<<< XML::LibXML::Comment >>>>>> + +XML::LibXML class for comment DOM nodes + + +=item L<<<<<< XML::LibXML::CDATASection >>>>>> + +XML::LibXML class for DOM CDATA sections + + +=item L<<<<<< XML::LibXML::Attr >>>>>> + +XML::LibXML DOM attribute class + + +=item L<<<<<< XML::LibXML::DocumentFragment >>>>>> + +XML::LibXML's DOM L2 Document Fragment implementation + + +=item L<<<<<< XML::LibXML::Namespace >>>>>> + +XML::LibXML DOM namespace nodes + + +=item L<<<<<< XML::LibXML::PI >>>>>> + +XML::LibXML DOM processing instruction nodes + + + +=back + + +=head1 ENCODINGS SUPPORT IN XML::LIBXML + +Recall that since version 5.6.1, Perl distinguishes between character strings +(internally encoded in UTF-8) and so called binary data and, accordingly, +applies either character or byte semantics to them. A scalar representing a +character string is distinguished from a byte string by special flag (UTF8). +Please refer to I<<<<<< perlunicode >>>>>> for details. + +XML::LibXML's API is designed to deal with many encodings of XML documents +completely transparently, so that the application using XML::LibXML can be +completely ignorant about the encoding of the XML documents it works with. On +the other hand, functions like C<<<<<< XML::LibXML::Document->setEncoding >>>>>> give the user control over the document encoding. + +To ensure the aforementioned transparency and uniformity, most functions of +XML::LibXML that work with in-memory trees accept and return data as character +strings (i.e. UTF-8 encoded with the UTF8 flag on) regardless of the original +document encoding; however, the functions related to I/O operations (i.e. +parsing and saving) operate with binary data (in the original document +encoding) obeying the encoding declaration of the XML documents. + +Below we summarize basic rules and principles regarding encoding: + + +=over 4 + +=item 1. + +Do NOT apply any encoding-related PerlIO layers (C<<<<<< :utf8 >>>>>> or C<<<<<< :encoding(...) >>>>>>) to file handles that are an input for the parses or an output for a +serializer of (full) XML documents. This is because the conversion of the data +to/from the internal character representation is provided by libxml2 itself +which must be able to enforce the encoding specified by the C<<<<<< <?xml version="1.0" encoding="..."?> >>>>>> declaration. Here is an example to follow: + + use XML::LibXML; + open my $fh, "file.xml"; + binmode $fh; # drop all PerlIO layers possibly created by a use open pragma + $doc = XML::LibXML->load_xml(IO => $fh); + open my $out, "out.xml"; + binmode $fh; # as above + $doc->toFh($fh); + # or + print $fh $doc->toString(); + + + + + +=item 2. + +All functions working with DOM accept and return character strings (UTF-8 +encoded with UTF8 flag on). E.g. + + my $doc = XML::LibXML:Document->new('1.0',$some_encoding); + my $element = $doc->createElement($name); + $element->appendText($text); + $xml_fragment = $element->toString(); # returns a character string + $xml_document = $doc->toString(); # returns a byte string + +where C<<<<<< $some_encoding >>>>>> is the document encoding that will be used when saving the document, and C<<<<<< $name >>>>>> and C<<<<<< $text >>>>>> contain character strings (UTF-8 encoded with UTF8 flag on). Note that the +method C<<<<<< toString >>>>>> returns XML as a character string if applied to other node than the Document +node and a byte string containing the apropriate + + <?xml version="1.0" encoding="..."?> + +declaration if applied to a L<<<<<< XML::LibXML::Document >>>>>>. + + + +=item 3. + +DOM methods also accept binary strings in the original encoding of the document +to which the node belongs (UTF-8 is assumed if the node is not attached to any +document). Exploiting this feature is NOT RECOMMENDED since it is considered a +bad practice. + + + + my $doc = XML::LibXML:Document->new('1.0','iso-8859-2'); + my $text = $doc->createTextNode($some_latin2_encoded_byte_string); + # WORKS, BUT NOT RECOMMENDED! + + + +=back + +I<<<<<< NOTE: >>>>>> libxml2 support for many encodings is based on the iconv library. The actual +list of supported encodings may vary from platform to platform. To test if your +platform works correctly with your language encoding, build a simple document +in the particular encoding and try to parse it with XML::LibXML to see if the +parser produces any errors. Occasional crashes were reported on rare platforms +that ship with a broken version of iconv. + + +=head1 THREAD SUPPORT + +XML::LibXML since 1.67 partially supports Perl threads in Perl >= 5.8.8. +XML::LibXML can be used with threads in two ways: + +By default, all XML::LibXML classes use CLONE_SKIP class method to prevent Perl +from copying XML::LibXML::* objects when a new thread is spawn. In this mode, +all XML::LibXML::* objects are thread specific. This is the safest way to work +with XML::LibXML in threads. + +Alternatively, one may use + + + + use threads; + use XML::LibXML qw(:threads_shared); + +to indicate, that all XML::LibXML node and parser objects should be shared +between the main thread and any thread spawn from there. For example, in + + + + my $doc = XML::LibXML->load_xml(location => $filename); + my $thr = threads->new(sub{ + # code working with $doc + 1; + }); + $thr->join; + +the variable C<<<<<< $doc >>>>>> refers to the exact same XML::LibXML::Document in the spawned thread as in the +main thread. + +Without using mutex locks, oaralel threads may read the same document (i.e. any +node that belongs to the document), parse files, and modify different +documents. + +However, if there is a chance that some of the threads will attempt to modify a +document ( or even create new nodes based on that document, e.g. with C<<<<<< $doc->createElement >>>>>>) that other threads may be reading at the same time, the user is responsible +for creating a mutex lock and using it in I<<<<<< both >>>>>> in the thread that modifies and the thread that reads: + + + + my $doc = XML::LibXML->load_xml(location => $filename); + my $mutex : shared; + my $thr = threads->new(sub{ + lock $mutex; + my $el = $doc->createElement('foo'); + # ... + 1; + }); + { + lock $mutex; + my $root = $doc->documentElement; + say $root->name; + } + $thr->join; + +Note that libxml2 uses dictionaries to store short strings and these +dicionaries are kept on a document node. Without mutex locks, it could happen +in the previous example that the thread modifies the dictionary while other +threads attempt to read from it, which could easily lead to a crash. + + +=head1 VERSION INFORMATION + +Sometimes it is useful to figure out, for which version XML::LibXML was +compiled for. In most cases this is for debugging or to check if a given +installation meets all functionality for the package. The functions +XML::LibXML::LIBXML_DOTTED_VERSION and XML::LibXML::LIBXML_VERSION provide this +version information. Both functions simply pass through the values of the +similar named macros of libxml2. Similarly, XML::LibXML::LIBXML_RUNTIME_VERSION +returns the version of the (usually dynamically) linked libxml2. + +=over 4 + +=item XML::LibXML::LIBXML_DOTTED_VERSION + + $Version_String = XML::LibXML::LIBXML_DOTTED_VERSION; + +Returns the version string of the libxml2 version XML::LibXML was compiled for. +This will be "2.6.2" for "libxml2 2.6.2". + + +=item XML::LibXML::LIBXML_VERSION + + $Version_ID = XML::LibXML::LIBXML_VERSION; + +Returns the version id of the libxml2 version XML::LibXML was compiled for. +This will be "20602" for "libxml2 2.6.2". Don't mix this version id with +$XML::LibXML::VERSION. The latter contains the version of XML::LibXML itself +while the first contains the version of libxml2 XML::LibXML was compiled for. + + +=item XML::LibXML::LIBXML_RUNTIME_VERSION + + $DLL_Version = XML::LibXML::LIBXML_RUNTIME_VERSION; + +Returns a version string of the libxml2 which is (usually dynamically) linked +by XML::LibXML. This will be "20602" for libxml2 released as "2.6.2" and +something like "20602-CVS2032" for a CVS build of libxml2. + +XML::LibXML issues a warning if the version of libxml2 dynamically linked to it +is less than the version of libxml2 which it was compiled against. + + + +=back + + +=head1 EXPORTS + +By default the module exports all constants and functions listed in the :all +tag, described below. + + +=head1 EXPORT TAGS + +=over 4 + +=item C<<<<<< :all >>>>>> + +Includes the tags C<<<<<< :libxml >>>>>>, C<<<<<< :encoding >>>>>>, and C<<<<<< :ns >>>>>> described below. + + +=item C<<<<<< :libxml >>>>>> + +Exports integer constants for DOM node types. + + + + XML_ELEMENT_NODE => 1 + XML_ATTRIBUTE_NODE => 2 + XML_TEXT_NODE => 3 + XML_CDATA_SECTION_NODE => 4 + XML_ENTITY_REF_NODE => 5 + XML_ENTITY_NODE => 6 + XML_PI_NODE => 7 + XML_COMMENT_NODE => 8 + XML_DOCUMENT_NODE => 9 + XML_DOCUMENT_TYPE_NODE => 10 + XML_DOCUMENT_FRAG_NODE => 11 + XML_NOTATION_NODE => 12 + XML_HTML_DOCUMENT_NODE => 13 + XML_DTD_NODE => 14 + XML_ELEMENT_DECL => 15 + XML_ATTRIBUTE_DECL => 16 + XML_ENTITY_DECL => 17 + XML_NAMESPACE_DECL => 18 + XML_XINCLUDE_START => 19 + XML_XINCLUDE_END => 20 + + +=item C<<<<<< :encoding >>>>>> + +Exports two encoding conversion functions from XML::LibXML::Common. + + + + encodeToUTF8() + decodeFromUTF8() + + +=item C<<<<<< :ns >>>>>> + +Exports two convenience constants: the implicit namespace of the reserved C<<<<<< xml: >>>>>> prefix, and the implicit namespace for the reserved C<<<<<< xmlns: >>>>>> prefix. + + + + XML_XML_NS => 'http://www.w3.org/XML/1998/namespace' + XML_XMLNS_NS => 'http://www.w3.org/2000/xmlns/' + + + +=back + + +=head1 RELATED MODULES + +The modules described in this section are not part of the XML::LibXML package +itself. As they support some additional features, they are mentioned here. + +=over 4 + +=item L<<<<<< XML::LibXSLT >>>>>> + +XSLT 1.0 Processor using libxslt and XML::LibXML + + +=item L<<<<<< XML::LibXML::Iterator >>>>>> + +XML::LibXML Implementation of the DOM Traversal Specification + + +=item L<<<<<< XML::CompactTree::XS >>>>>> + +Uses XML::LibXML::Reader to very efficiently to parse XML document or element +into native Perl data structures, which are less flexible but significantly +faster to process then DOM. + + + +=back + + +=head1 XML::LIBXML AND XML::GDOME + +Note: I<<<<<< THE FUNCTIONS DESCRIBED HERE ARE STILL EXPERIMENTAL >>>>>> + +Although both modules make use of libxml2's XML capabilities, the DOM +implementation of both modules are not compatible. But still it is possible to +exchange nodes from one DOM to the other. The concept of this exchange is +pretty similar to the function cloneNode(): The particular node is copied on +the low-level to the opposite DOM implementation. + +Since the DOM implementations cannot coexist within one document, one is forced +to copy each node that should be used. Because you are always keeping two nodes +this may cause quite an impact on a machines memory usage. + +XML::LibXML provides two functions to export or import GDOME nodes: +import_GDOME() and export_GDOME(). Both function have two parameters: the node +and a flag for recursive import. The flag works as in cloneNode(). + +The two functions allow to export and import XML::GDOME nodes explicitly, +however, XML::LibXML allows also the transparent import of XML::GDOME nodes in +functions such as appendChild(), insertAfter() and so on. While native nodes +are automatically adopted in most functions XML::GDOME nodes are always cloned +in advance. Thus if the original node is modified after the operation, the node +in the XML::LibXML document will not have this information. + +=over 4 + +=item import_GDOME + + $libxmlnode = XML::LibXML->import_GDOME( $node, $deep ); + +This clones an XML::GDOME node to a XML::LibXML node explicitly. + + +=item export_GDOME + + $gdomenode = XML::LibXML->export_GDOME( $node, $deep ); + +Allows to clone an XML::LibXML node into a XML::GDOME node. + + + +=back + + +=head1 CONTACTS + +For bug reports, please use the CPAN request tracker on +http://rt.cpan.org/NoAuth/Bugs.html?Dist=XML-LibXML + +For suggestions etc., and other issues related to XML::LibXML you may use the +perl XML mailing list (C<<<<<< perl-xml@listserv.ActiveState.com >>>>>>), where most XML-related Perl modules are discussed. In case of problems you +should check the archives of that list first. Many problems are already +discussed there. You can find the list's archives and subscription options at L<<<<<< http://aspn.activestate.com/ASPN/Mail/Browse/Threaded/perl-xml >>>>>>. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Attr.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Attr.pod new file mode 100755 index 00000000000..eeb2678ecb6 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Attr.pod @@ -0,0 +1,134 @@ +=head1 NAME + +XML::LibXML::Attr - XML::LibXML Attribute Class + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to Attribute nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + $attr = XML::LibXML::Attr->new($name [,$value]); + $string = $attr->getValue(); + $string = $attr->value; + $attr->setValue( $string ); + $node = $attr->getOwnerElement(); + $attr->setNamespace($nsURI, $prefix); + $bool = $attr->isId; + $string = $attr->serializeContent; + +=head1 DESCRIPTION + +This is the interface to handle Attributes like ordinary nodes. The naming of +the class relies on the W3C DOM documentation. + + +=head1 METHODS + +The class inherits from L<<<<<< XML::LibXML::Node >>>>>>. The documentation for Inherited methods is not listed here. + +Many functions listed here are extensively documented in the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>). Please refer to the specification for extensive documentation. + +=over 4 + +=item new + + $attr = XML::LibXML::Attr->new($name [,$value]); + +Class constructor. If you need to work with ISO encoded strings, you should I<<<<<< always >>>>>> use the C<<<<<< createAttrbute >>>>>> of L<<<<<< XML::LibXML::Document >>>>>>. + + +=item getValue + + $string = $attr->getValue(); + +Returns the value stored for the attribute. If undef is returned, the attribute +has no value, which is different of being C<<<<<< not specified >>>>>>. + + +=item value + + $string = $attr->value; + +Alias for I<<<<<< getValue() >>>>>> + + +=item setValue + + $attr->setValue( $string ); + +This is needed to set a new attribute value. If ISO encoded strings are passed +as parameter, the node has to be bound to a document, otherwise the encoding +might be done incorrectly. + + +=item getOwnerElement + + $node = $attr->getOwnerElement(); + +returns the node the attribute belongs to. If the attribute is not bound to a +node, undef will be returned. Overwriting the underlying implementation, the I<<<<<< parentNode >>>>>> function will return undef, instead of the owner element. + + +=item setNamespace + + $attr->setNamespace($nsURI, $prefix); + +This function tries to bound the attribute to a given namespace. If C<<<<<< $nsURI >>>>>> is undefined or empty, the function discards any previous association of the +attribute with a namespace. If the namespace was not previously declared in the +context of the attribute, this function will fail. In this case you may wish to +call setNamespace() on the ownerElement. If the namespace URI is non-empty and +declared in the context of the attribute, but only with a different (non-empty) +prefix, then the attribute is still bound to the namespace but gets a different +prefix than C<<<<<< $prefix >>>>>>. The function also fails if the prefix is empty but the namespace URI is not +(because unprefixed attributes should by definition belong to no namespace). +This function returns 1 on success, 0 otherwise. + + +=item isId + + $bool = $attr->isId; + +Determine whether an attribute is of type ID. For documents with a DTD, this +information is only available if DTD loading/validation has been requested. For +HTML documents parsed with the HTML parser ID detection is done automatically. +In XML documents, all "xml:id" attributes are considered to be of type ID. + + +=item serializeContent($docencoding) + + $string = $attr->serializeContent; + +This function is not part of DOM API. It returns attribute content in the form +in which it serializes into XML, that is with all meta-characters properly +quoted and with raw entity references (except for entities expanded during +parse time). Setting the optional $docencoding flag to 1 enforces document +encoding for the output string (which is then passed to Perl as a byte string). +Otherwise the string is passed to Perl as (UTF-8 encoded) characters. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Boolean.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/Boolean.pm new file mode 100755 index 00000000000..03db16788e7 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Boolean.pm @@ -0,0 +1,92 @@ +# $Id: Boolean.pm 785 2009-07-16 14:17:46Z pajas $ +# +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::Boolean; +use XML::LibXML::Number; +use XML::LibXML::Literal; +use strict; + +use vars qw ($VERSION); + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use overload + '""' => \&value, + '<=>' => \&cmp; + +sub new { + my $class = shift; + my ($param) = @_; + my $val = $param ? 1 : 0; + bless \$val, $class; +} + +sub True { + my $class = shift; + my $val = 1; + bless \$val, $class; +} + +sub False { + my $class = shift; + my $val = 0; + bless \$val, $class; +} + +sub value { + my $self = shift; + $$self; +} + +sub cmp { + my $self = shift; + my ($other, $swap) = @_; + if ($swap) { + return $other <=> $$self; + } + return $$self <=> $other; +} + +sub to_number { XML::LibXML::Number->new($_[0]->value); } +sub to_boolean { $_[0]; } +sub to_literal { XML::LibXML::Literal->new($_[0]->value ? "true" : "false"); } + +sub string_value { return $_[0]->to_literal->value; } + +1; +__END__ + +=head1 NAME + +XML::LibXML::Boolean - Boolean true/false values + +=head1 DESCRIPTION + +XML::LibXML::Boolean objects implement simple boolean true/false objects. + +=head1 API + +=head2 XML::LibXML::Boolean->True + +Creates a new Boolean object with a true value. + +=head2 XML::LibXML::Boolean->False + +Creates a new Boolean object with a false value. + +=head2 value() + +Returns true or false. + +=head2 to_literal() + +Returns the string "true" or "false". + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/CDATASection.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/CDATASection.pod new file mode 100755 index 00000000000..c1f1b0996c3 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/CDATASection.pod @@ -0,0 +1,58 @@ +=head1 NAME + +XML::LibXML::CDATASection - XML::LibXML Class for CDATA Sections + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to CDATA nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + $node = XML::LibXML::CDATASection( $content ); + +=head1 DESCRIPTION + +This class provides all functions of L<<<<<< XML::LibXML::Text >>>>>>, but for CDATA nodes. + + +=head1 METHODS + +The class inherits from L<<<<<< XML::LibXML::Node >>>>>>. The documentation for Inherited methods is not listed here. + +Many functions listed here are extensively documented in the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>). Please refer to the specification for extensive documentation. + +=over 4 + +=item new + + $node = XML::LibXML::CDATASection( $content ); + +The constructor is the only provided function for this package. It is required, +because I<<<<<< libxml2 >>>>>> treats the different text node types slightly differently. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Comment.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Comment.pod new file mode 100755 index 00000000000..f5e0829af01 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Comment.pod @@ -0,0 +1,59 @@ +=head1 NAME + +XML::LibXML::Comment - XML::LibXML Comment Class + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to Comment nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + $node = XML::LibXML::Comment( $content ); + +=head1 DESCRIPTION + +This class provides all functions of L<<<<<< XML::LibXML::Text >>>>>>, but for comment nodes. This can be done, since only the output of the node +types is different, but not the data structure. :-) + + +=head1 METHODS + +The class inherits from L<<<<<< XML::LibXML::Node >>>>>>. The documentation for Inherited methods is not listed here. + +Many functions listed here are extensively documented in the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>). Please refer to the specification for extensive documentation. + +=over 4 + +=item new + + $node = XML::LibXML::Comment( $content ); + +The constructor is the only provided function for this package. It is required, +because I<<<<<< libxml2 >>>>>> treats text nodes and comment nodes slightly differently. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Common.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/Common.pm new file mode 100755 index 00000000000..2050c8af363 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Common.pm @@ -0,0 +1,203 @@ +#-------------------------------------------------------------------------# +# $Id: Common.pm,v 1.5 2003/02/27 18:32:59 phish108 Exp $ +# +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# +#-------------------------------------------------------------------------# +package XML::LibXML::Common; + + +#-------------------------------------------------------------------------# +# global blur # +#-------------------------------------------------------------------------# +use strict; + +require Exporter; +require DynaLoader; +use vars qw( @ISA $VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS); + +@ISA = qw(Exporter); + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use XML::LibXML qw(:libxml); + +#-------------------------------------------------------------------------# +# export information # +#-------------------------------------------------------------------------# +%EXPORT_TAGS = ( + all => [qw( + ELEMENT_NODE + ATTRIBUTE_NODE + TEXT_NODE + CDATA_SECTION_NODE + ENTITY_REFERENCE_NODE + ENTITY_NODE + PI_NODE + PROCESSING_INSTRUCTION_NODE + COMMENT_NODE + DOCUMENT_NODE + DOCUMENT_TYPE_NODE + DOCUMENT_FRAG_NODE + DOCUMENT_FRAGMENT_NODE + NOTATION_NODE + HTML_DOCUMENT_NODE + DTD_NODE + ELEMENT_DECLARATION + ATTRIBUTE_DECLARATION + ENTITY_DECLARATION + NAMESPACE_DECLARATION + XINCLUDE_END + XINCLUDE_START + encodeToUTF8 + decodeFromUTF8 + )], + w3c => [qw( + ELEMENT_NODE + ATTRIBUTE_NODE + TEXT_NODE + CDATA_SECTION_NODE + ENTITY_REFERENCE_NODE + ENTITY_NODE + PI_NODE + PROCESSING_INSTRUCTION_NODE + COMMENT_NODE + DOCUMENT_NODE + DOCUMENT_TYPE_NODE + DOCUMENT_FRAG_NODE + DOCUMENT_FRAGMENT_NODE + NOTATION_NODE + HTML_DOCUMENT_NODE + DTD_NODE + ELEMENT_DECLARATION + ATTRIBUTE_DECLARATION + ENTITY_DECLARATION + NAMESPACE_DECLARATION + XINCLUDE_END + XINCLUDE_START + )], + libxml => [qw( + XML_ELEMENT_NODE + XML_ATTRIBUTE_NODE + XML_TEXT_NODE + XML_CDATA_SECTION_NODE + XML_ENTITY_REF_NODE + XML_ENTITY_NODE + XML_PI_NODE + XML_COMMENT_NODE + XML_DOCUMENT_NODE + XML_DOCUMENT_TYPE_NODE + XML_DOCUMENT_FRAG_NODE + XML_NOTATION_NODE + XML_HTML_DOCUMENT_NODE + XML_DTD_NODE + XML_ELEMENT_DECL + XML_ATTRIBUTE_DECL + XML_ENTITY_DECL + XML_NAMESPACE_DECL + XML_XINCLUDE_END + XML_XINCLUDE_START + )], + gdome => [qw( + GDOME_ELEMENT_NODE + GDOME_ATTRIBUTE_NODE + GDOME_TEXT_NODE + GDOME_CDATA_SECTION_NODE + GDOME_ENTITY_REF_NODE + GDOME_ENTITY_NODE + GDOME_PI_NODE + GDOME_COMMENT_NODE + GDOME_DOCUMENT_NODE + GDOME_DOCUMENT_TYPE_NODE + GDOME_DOCUMENT_FRAG_NODE + GDOME_NOTATION_NODE + GDOME_HTML_DOCUMENT_NODE + GDOME_DTD_NODE + GDOME_ELEMENT_DECL + GDOME_ATTRIBUTE_DECL + GDOME_ENTITY_DECL + GDOME_NAMESPACE_DECL + GDOME_XINCLUDE_END + GDOME_XINCLUDE_START + )], + encoding => [qw( + encodeToUTF8 + decodeFromUTF8 + )], + ); + +@EXPORT_OK = ( + @{$EXPORT_TAGS{encoding}}, + @{$EXPORT_TAGS{w3c}}, + @{$EXPORT_TAGS{libxml}}, + @{$EXPORT_TAGS{gdome}}, + ); + +@EXPORT = ( + @{$EXPORT_TAGS{encoding}}, + @{$EXPORT_TAGS{w3c}}, + ); + +#-------------------------------------------------------------------------# +# W3 conform node types # +#-------------------------------------------------------------------------# +use constant ELEMENT_NODE => 1; +use constant ATTRIBUTE_NODE => 2; +use constant TEXT_NODE => 3; +use constant CDATA_SECTION_NODE => 4; +use constant ENTITY_REFERENCE_NODE => 5; +use constant ENTITY_NODE => 6; +use constant PROCESSING_INSTRUCTION_NODE => 7; +use constant COMMENT_NODE => 8; +use constant DOCUMENT_NODE => 9; +use constant DOCUMENT_TYPE_NODE => 10; +use constant DOCUMENT_FRAGMENT_NODE => 11; +use constant NOTATION_NODE => 12; +use constant HTML_DOCUMENT_NODE => 13; +use constant DTD_NODE => 14; +use constant ELEMENT_DECLARATION => 15; +use constant ATTRIBUTE_DECLARATION => 16; +use constant ENTITY_DECLARATION => 17; +use constant NAMESPACE_DECLARATION => 18; + +#-------------------------------------------------------------------------# +# some extras for the W3 spec +#-------------------------------------------------------------------------# +use constant PI_NODE => 7; +use constant DOCUMENT_FRAG_NODE => 11; +use constant XINCLUDE_END => 19; +use constant XINCLUDE_START => 20; + +#-------------------------------------------------------------------------# +# libgdome compat names # +#-------------------------------------------------------------------------# +use constant GDOME_ELEMENT_NODE => 1; +use constant GDOME_ATTRIBUTE_NODE => 2; +use constant GDOME_TEXT_NODE => 3; +use constant GDOME_CDATA_SECTION_NODE => 4; +use constant GDOME_ENTITY_REF_NODE => 5; +use constant GDOME_ENTITY_NODE => 6; +use constant GDOME_PI_NODE => 7; +use constant GDOME_COMMENT_NODE => 8; +use constant GDOME_DOCUMENT_NODE => 9; +use constant GDOME_DOCUMENT_TYPE_NODE => 10; +use constant GDOME_DOCUMENT_FRAG_NODE => 11; +use constant GDOME_NOTATION_NODE => 12; +use constant GDOME_HTML_DOCUMENT_NODE => 13; +use constant GDOME_DTD_NODE => 14; +use constant GDOME_ELEMENT_DECL => 15; +use constant GDOME_ATTRIBUTE_DECL => 16; +use constant GDOME_ENTITY_DECL => 17; +use constant GDOME_NAMESPACE_DECL => 18; +use constant GDOME_XINCLUDE_START => 19; +use constant GDOME_XINCLUDE_END => 20; + +1; +#-------------------------------------------------------------------------# +__END__ + diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Common.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Common.pod new file mode 100755 index 00000000000..6097399b7e2 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Common.pod @@ -0,0 +1,129 @@ +=head1 NAME + +XML::LibXML::Common - Constants and Character Encoding Routines + +=head1 SYNOPSIS + + + + use XML::LibXML::Common; + + $encodedstring = encodeToUTF8( $name_of_encoding, $sting_to_encode ); + $decodedstring = decodeFromUTF8($name_of_encoding, $string_to_decode ); + +=head1 DESCRIPTION + +XML::LibXML::Common defines constants for all node types and provides interface +to libxml2 charset conversion functions. + +Since XML::LibXML use their own node type definitions, one may want to use +XML::LibXML::Common in its compatibility mode: + + +=head2 Exporter TAGS + + + + use XML::LibXML::Common qw(:libxml); + +C<<<<<< :libxml >>>>>> tag will use the XML::LibXML Compatibility mode, which defines the old 'XML_' +node-type definitions. + + + + use XML::LibXML::Common qw(:gdome); + +C<<<<<< :gdome >>>>>> tag will use the XML::GDOME Compatibility mode, which defines the old 'GDOME_' +node-type definitions. + + + + use XML::LibXML::Common qw(:w3c); + +This uses the nodetype definition names as specified for DOM. + + + + use XML::LibXML::Common qw(:encoding); + +This tag can be used to export only the charset encoding functions of +XML::LibXML::Common. + + +=head2 Exports + +By default the W3 definitions as defined in the DOM specifications and the +encoding functions are exported by XML::LibXML::Common. + + +=head2 Encoding functions + +To encode or decode a string to or from UTF-8, XML::LibXML::Common exports two +functions, which provide interfact to the encoding support in C<<<<<< libxml2 >>>>>>. Which encodings are supported by these functions depends on how C<<<<<< libxml2 >>>>>> was compiled. UTF-16 is always supported and on most installations, ISO +encodings are supported as well. + +This interface was useful for older versions of Perl. Since Perl >= 5.8 +provides similar funcions via the C<<<<<< Encode >>>>>> module, it is probably a good idea to use those instead. + +=over 4 + +=item encodeToUTF8 + + $encodedstring = encodeToUTF8( $name_of_encoding, $sting_to_encode ); + +The function will convert a byte string from the specified encoding to an UTF-8 +encoded character string. + + +=item decodeToUTF8 + + $decodedstring = decodeFromUTF8($name_of_encoding, $string_to_decode ); + +This function converts an UTF-8 encoded character string to a specified +encoding. Note that the conversion can raise an error if the given string +contains characters that cannot be represented in the target encoding. + + + +=back + +Both these functions report their errors on the standard error. If an error +occours the function will croak(). To catch the error information it is +required to call the encoding function from within an eval block in order to +prevent the entire script from being stopped on encoding error. + + +=head2 A note on history + +Before XML::LibXML 1.70, this class was available as a separate CPAN +distribution, intended to provide functionality shared between XML::LibXML, +XML::GDOME, and possibly other modules. Since there seems to be no progress in +this direction, we decided to merge XML::LibXML::Common 0.13 and XML::LibXML +1.70 to one CPAN distribution. + +The merge also naturally eliminates a practical and urgent problem experienced +by many XML::LibXML users on certain platforms, namely misterious misbehavior +of XML::LibXML occurring if the installed (often pre-packaged) version of +XML::LibXML::Common was compiled against an older version of libxml2 than +XML::LibXML. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/DOM.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/DOM.pod new file mode 100755 index 00000000000..27fd92c6d59 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/DOM.pod @@ -0,0 +1,142 @@ +=head1 NAME + +XML::LibXML::DOM - XML::LibXML DOM Implementation + +=head1 DESCRIPTION + +XML::LibXML provides an light-wight interface to I<<<<<< modify >>>>>> a node of the document tree generated by the XML::LibXML parser. This interface +follows as far as possible the DOM Level 3 specification. Additionally to the +specified functions the XML::LibXML supports some functions that are more handy +to use in the perl environment. + +One also has to remember, that XML::LibXML is an interface to libxml2 nodes +which actually reside on the C-Level of XML::LibXML. This means each node is a +reference to a structure different than a perl hash or array. The only way to +access these structure's values is through the DOM interface provided by +XML::LibXML. This also means, that one I<<<<<< can't >>>>>> simply inherit a XML::LibXML node and add new member variables as they were +hash keys. + +The DOM interface of XML::LibXML does not intend to implement a full DOM +interface as it is done by XML::GDOME and used for full featured application. +Moreover, it offers an simple way to build or modify documents that are created +by XML::LibXML's parser. + +Another target of the XML::LibXML interface is to make the interfaces of +libxml2 available to the perl community. This includes also some workarounds to +some features where libxml2 assumes more control over the C-Level that most +perl users don't have. + +One of the most important parts of the XML::LibXML DOM interface is, that the +interfaces try do follow the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>) rather strictly. This means the interface functions are named as the DOM +specification says and not what widespread Java interfaces claim to be +standard. Although there are several functions that have only a singular +interface that conforms to the DOM spec XML::LibXML provides an additional Java +style alias interface. + +Also there are some function interfaces left over from early stages of +XML::LibXML for compatibility reasons. These interfaces are for compatibility +reasons I<<<<<< only >>>>>>. They might disappear in one of the future versions of XML::LibXML, so a user +is requested to switch over to the official functions. + + +=head2 Encodings and XML::LibXML's DOM implementation + +See the section on Encodings in the I<<<<<< XML::LibXML >>>>>> manual page. + + +=head2 Namespaces and XML::LibXML's DOM implementation + +XML::LibXML's DOM implementation is limited by the DOM implementation of +libxml2 which treats namespaces slightly differently than required by the DOM +Level 2 specification. + +According to the DOM Level 2 specification, namespaces of elements and +attributes should be persistent, and nodes should be permanently bound to +namespace URIs as they get created; it should be possible to manipulate the +special attributes used for declaring XML namespaces just as other attributes +without affecting the namespaces of other nodes. In DOM Level 2, the +application is responsible for creating the special attributes consistently +and/or for correct serialization of the document. + +This is both inconvenient, causes problems in serialization of DOM to XML, and +most importantly, seems almost impossible to implement over libxml2. + +In libxml2, namespace URI and prefix of a node is provided by a pointer to a +namespace declaration (appearing as a special xmlns attribute in the XML +document). If the prefix or namespace URI of the declaration changes, the +prefix and namespace URI of all nodes that point to it changes as well. +Moreover, in contrast to DOM, a node (element or attribute) can only be bound +to a namespace URI if there is some namespace declaration in the document to +point to. + +Therefore current DOM implementation in XML::LibXML tries to treat namespace +declarations in a compromise between reason, common sense, limitations of +libxml2, and the DOM Level 2 specification. + +In XML::LibXML, special attributes declaring XML namespaces are often created +automatically, usually when a namespaced node is attached to a document and no +existing declaration of the namespace and prefix is in the scope to be reused. +In this respect, XML::LibXML DOM implementation differs from the DOM Level 2 +specification according to which special attributes for declaring the +apropriate XML namespaces should not be added when a node with a namespace +prefix and namespace URI is created. + +Namespace declarations are also created when L<<<<<< XML::LibXML::Document >>>>>>'s createElementNS() or createAttributeNS() function are used. If the a +namespace is not declared on the documentElement, the namespace will be locally +declared for the newly created node. In case of Attributes this may look a bit +confusing, since these nodes cannot have namespace declarations itself. In this +case the namespace is internally applied to the attribute and later declared on +the node the attribute is appended to (if required). + +The following example may explain this a bit: + + + + my $doc = XML::LibXML->createDocument; + my $root = $doc->createElementNS( "", "foo" ); + $doc->setDocumentElement( $root ); + + my $attr = $doc->createAttributeNS( "bar", "bar:foo", "test" ); + $root->setAttributeNodeNS( $attr ); + +This piece of code will result in the following document: + + + + <?xml version="1.0"?> + <foo xmlns:bar="bar" bar:foo="test"/> + +The namespace is declared on the document element during the +setAttributeNodeNS() call. + +Namespaces can be also declared explicitly by the use of XML::LibXML:Element's +setNamespace() function. Since 1.61, they can also be manipulated with +functions setNamespaceDeclPrefix() and setNamespaceDeclURI() (not available in +DOM). Changing an URI or prefix of an existing namespace declaration affects +the namespace URI and prefix of all nodes which point to it (that is the nodes +in its scope). + +It is also important to repeat the specification: While working with namespaces +you should use the namespace aware functions instead of the simplified +versions. For example you should I<<<<<< never >>>>>> use setAttribute() but setAttributeNS(). + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Document.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Document.pod new file mode 100755 index 00000000000..a4769d992db --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Document.pod @@ -0,0 +1,696 @@ +=head1 NAME + +XML::LibXML::Document - XML::LibXML DOM Document Class + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to Document nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + $dom = XML::LibXML::Document->new( $version, $encoding ); + $dom = XML::LibXML::Document->createDocument( $version, $encoding ); + $strURI = $doc->URI(); + $doc->setURI($strURI); + $strEncoding = $doc->encoding(); + $strEncoding = $doc->actualEncoding(); + $doc->setEncoding($new_encoding); + $strVersion = $doc->version(); + $doc->standalone + $doc->setStandalone($numvalue); + my $compression = $doc->compression; + $doc->setCompression($ziplevel); + $docstring = $dom->toString($format); + $c14nstr = $doc->toStringC14N($comment_flag, $xpath [, $xpath_context ]); + $ec14nstr = $doc->toStringEC14N($comment_flag, $xpath [, $xpath_context ], $inclusive_prefix_list); + $str = $doc->serialize($format); + $state = $doc->toFile($filename, $format); + $state = $doc->toFH($fh, $format); + $str = $document->toStringHTML(); + $str = $document->serialize_html(); + $bool = $dom->is_valid(); + $dom->validate(); + $root = $dom->documentElement(); + $dom->setDocumentElement( $root ); + $element = $dom->createElement( $nodename ); + $element = $dom->createElementNS( $namespaceURI, $qname ); + $text = $dom->createTextNode( $content_text ); + $comment = $dom->createComment( $comment_text ); + $attrnode = $doc->createAttribute($name [,$value]); + $attrnode = $doc->createAttributeNS( namespaceURI, $name [,$value] ); + $fragment = $doc->createDocumentFragment(); + $cdata = $dom->create( $cdata_content ); + my $pi = $doc->createProcessingInstruction( $target, $data ); + my $entref = $doc->createEntityReference($refname); + $dtd = $document->createInternalSubset( $rootnode, $public, $system); + $dtd = $document->createExternalSubset( $rootnode_name, $publicId, $systemId); + $document->importNode( $node ); + $document->adoptNode( $node ); + my $dtd = $doc->externalSubset; + my $dtd = $doc->internalSubset; + $doc->setExternalSubset($dtd); + $doc->setInternalSubset($dtd); + my $dtd = $doc->removeExternalSubset(); + my $dtd = $doc->removeInternalSubset(); + my @nodelist = $doc->getElementsByTagName($tagname); + my @nodelist = $doc->getElementsByTagNameNS($nsURI,$tagname); + my @nodelist = $doc->getElementsByLocalName($localname); + my $node = $doc->getElementById($id); + $dom->indexElements(); + +=head1 DESCRIPTION + +The Document Class is in most cases the result of a parsing process. But +sometimes it is necessary to create a Document from scratch. The DOM Document +Class provides functions that conform to the DOM Core naming style. + +It inherits all functions from L<<<<<< XML::LibXML::Node >>>>>> as specified in the DOM specification. This enables access to the nodes besides +the root element on document level - a C<<<<<< DTD >>>>>> for example. The support for these nodes is limited at the moment. + +While generally nodes are bound to a document in the DOM concept it is +suggested that one should always create a node not bound to any document. There +is no need of really including the node to the document, but once the node is +bound to a document, it is quite safe that all strings have the correct +encoding. If an unbound text node with an ISO encoded string is created (e.g. +with $CLASS->new()), the C<<<<<< toString >>>>>> function may not return the expected result. + +To prevent such problems, it is recommended to pass all data to XML::LibXML +methods as character strings (i.e. UTF-8 encoded, with the UTF8 flag on). + + +=head1 METHODS + +Many functions listed here are extensively documented in the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>). Please refer to the specification for extensive documentation. + +=over 4 + +=item new + + $dom = XML::LibXML::Document->new( $version, $encoding ); + +alias for createDocument() + + +=item createDocument + + $dom = XML::LibXML::Document->createDocument( $version, $encoding ); + +The constructor for the document class. As Parameter it takes the version +string and (optionally) the encoding string. Simply calling I<<<<<< createDocument >>>>>>() will create the document: + + + + <?xml version="your version" encoding="your encoding"?> + +Both parameter are optional. The default value for I<<<<<< $version >>>>>> is C<<<<<< 1.0 >>>>>>, of course. If the I<<<<<< $encoding >>>>>> parameter is not set, the encoding will be left unset, which means UTF-8 is +implied. + +The call of I<<<<<< createDocument >>>>>>() without any parameter will result the following code: + + + + <?xml version="1.0"?> + +Alternatively one can call this constructor directly from the XML::LibXML class +level, to avoid some typing. This will not have any effect on the class +instance, which is always XML::LibXML::Document. + + + + my $document = XML::LibXML->createDocument( "1.0", "UTF-8" ); + +is therefore a shortcut for + + + + my $document = XML::LibXML::Document->createDocument( "1.0", "UTF-8" ); + + +=item URI + + $strURI = $doc->URI(); + +Returns the URI (or filename) of the original document. For documents obtained +by parsing a string of a FH without using the URI parsing argument of the +corresponding C<<<<<< parse_* >>>>>> function, the result is a generated string unknown-XYZ where XYZ is some +number; for documents created with the constructor C<<<<<< new >>>>>>, the URI is undefined. + +The value can be modified by calling C<<<<<< setURI >>>>>> method on the document node. + + +=item setURI + + $doc->setURI($strURI); + +Sets the URI of the document reported by the method URI (see also the URI +argument to the various C<<<<<< parse_* >>>>>> functions). + + +=item encoding + + $strEncoding = $doc->encoding(); + +returns the encoding string of the document. + + + + my $doc = XML::LibXML->createDocument( "1.0", "ISO-8859-15" ); + print $doc->encoding; # prints ISO-8859-15 + + +=item actualEncoding + + $strEncoding = $doc->actualEncoding(); + +returns the encoding in which the XML will be returned by $doc->toString(). +This is usually the original encoding of the document as declared in the XML +declaration and returned by $doc->encoding. If the original encoding is not +known (e.g. if created in memory or parsed from a XML without a declared +encoding), 'UTF-8' is returned. + + + + my $doc = XML::LibXML->createDocument( "1.0", "ISO-8859-15" ); + print $doc->encoding; # prints ISO-8859-15 + + +=item setEncoding + + $doc->setEncoding($new_encoding); + +This method allows to change the declaration of encoding in the XML declaration +of the document. The value also affects the encoding in which the document is +serialized to XML by $doc->toString(). Use setEncoding() to remove the encoding +declaration. + + +=item version + + $strVersion = $doc->version(); + +returns the version string of the document + +I<<<<<< getVersion() >>>>>> is an alternative form of this function. + + +=item standalone + + $doc->standalone + +This function returns the Numerical value of a documents XML declarations +standalone attribute. It returns I<<<<<< 1 >>>>>> if standalone="yes" was found, I<<<<<< 0 >>>>>> if standalone="no" was found and I<<<<<< -1 >>>>>> if standalone was not specified (default on creation). + + +=item setStandalone + + $doc->setStandalone($numvalue); + +Through this method it is possible to alter the value of a documents standalone +attribute. Set it to I<<<<<< 1 >>>>>> to set standalone="yes", to I<<<<<< 0 >>>>>> to set standalone="no" or set it to I<<<<<< -1 >>>>>> to remove the standalone attribute from the XML declaration. + + +=item compression + + my $compression = $doc->compression; + +libxml2 allows reading of documents directly from gzipped files. In this case +the compression variable is set to the compression level of that file (0-8). If +XML::LibXML parsed a different source or the file wasn't compressed, the +returned value will be I<<<<<< -1 >>>>>>. + + +=item setCompression + + $doc->setCompression($ziplevel); + +If one intends to write the document directly to a file, it is possible to set +the compression level for a given document. This level can be in the range from +0 to 8. If XML::LibXML should not try to compress use I<<<<<< -1 >>>>>> (default). + +Note that this feature will I<<<<<< only >>>>>> work if libxml2 is compiled with zlib support and toFile() is used for output. + + +=item toString + + $docstring = $dom->toString($format); + +I<<<<<< toString >>>>>> is a DOM serializing function, so the DOM Tree is serialized into a XML string, +ready for output. + +IMPORTANT: unlike toString for other nodes, on document nodes this function +returns the XML as a byte string in the original encoding of the document (see +the actualEncoding() method)! This means you can simply do: + + + + open OUT, $file; + print OUT $doc->toString; + +regardless of the actual encoding of the document. See the section on encodings +in L<<<<<< XML::LibXML >>>>>> for more details. + +The optional I<<<<<< $format >>>>>> parameter sets the indenting of the output. This parameter is expected to be an C<<<<<< integer >>>>>> value, that specifies that indentation should be used. The format parameter can +have three different values if it is used: + +If $format is 0, than the document is dumped as it was originally parsed + +If $format is 1, libxml2 will add ignorable white spaces, so the nodes content +is easier to read. Existing text nodes will not be altered + +If $format is 2 (or higher), libxml2 will act as $format == 1 but it add a +leading and a trailing line break to each text node. + +libxml2 uses a hard-coded indentation of 2 space characters per indentation +level. This value can not be altered on run-time. + + +=item toStringC14N + + $c14nstr = $doc->toStringC14N($comment_flag, $xpath [, $xpath_context ]); + +See the documentation in L<<<<<< XML::LibXML::Node >>>>>>. + + +=item toStringEC14N + + $ec14nstr = $doc->toStringEC14N($comment_flag, $xpath [, $xpath_context ], $inclusive_prefix_list); + +See the documentation in L<<<<<< XML::LibXML::Node >>>>>>. + + +=item serialize + + $str = $doc->serialize($format); + +An alias for toString(). This function was name added to be more consistent +with libxml2. + + +=item serialize_c14n + +An alias for toStringC14N(). + + +=item serialize_exc_c14n + +An alias for toStringEC14N(). + + +=item toFile + + $state = $doc->toFile($filename, $format); + +This function is similar to toString(), but it writes the document directly +into a filesystem. This function is very useful, if one needs to store large +documents. + +The format parameter has the same behaviour as in toString(). + + +=item toFH + + $state = $doc->toFH($fh, $format); + +This function is similar to toString(), but it writes the document directly to +a filehandle or a stream. A byte stream in the document encoding is passed to +the file handle. Do NOT apply any C<<<<<< :encoding(...) >>>>>> or C<<<<<< :utf8 >>>>>> PerlIO layer to the filehandle! See the section on encodings in L<<<<<< XML::LibXML >>>>>> for more details. + +The format parameter has the same behaviour as in toString(). + + +=item toStringHTML + + $str = $document->toStringHTML(); + +I<<<<<< toStringHTML >>>>>> serialize the tree to a byte string in the document encoding as HTML. With this +method indenting is automatic and managed by libxml2 internally. + + +=item serialize_html + + $str = $document->serialize_html(); + +An alias for toStringHTML(). + + +=item is_valid + + $bool = $dom->is_valid(); + +Returns either TRUE or FALSE depending on whether the DOM Tree is a valid +Document or not. + +You may also pass in a L<<<<<< XML::LibXML::Dtd >>>>>> object, to validate against an external DTD: + + + + if (!$dom->is_valid($dtd)) { + warn("document is not valid!"); + } + + +=item validate + + $dom->validate(); + +This is an exception throwing equivalent of is_valid. If the document is not +valid it will throw an exception containing the error. This allows you much +better error reporting than simply is_valid or not. + +Again, you may pass in a DTD object + + +=item documentElement + + $root = $dom->documentElement(); + +Returns the root element of the Document. A document can have just one root +element to contain the documents data. + +Optionally one can use I<<<<<< getDocumentElement >>>>>>. + + +=item setDocumentElement + + $dom->setDocumentElement( $root ); + +This function enables you to set the root element for a document. The function +supports the import of a node from a different document tree, but does not +support a document fragment as $root. + + +=item createElement + + $element = $dom->createElement( $nodename ); + +This function creates a new Element Node bound to the DOM with the name C<<<<<< $nodename >>>>>>. + + +=item createElementNS + + $element = $dom->createElementNS( $namespaceURI, $qname ); + +This function creates a new Element Node bound to the DOM with the name C<<<<<< $nodename >>>>>> and placed in the given namespace. + + +=item createTextNode + + $text = $dom->createTextNode( $content_text ); + +As an equivalent of I<<<<<< createElement >>>>>>, but it creates a I<<<<<< Text Node >>>>>> bound to the DOM. + + +=item createComment + + $comment = $dom->createComment( $comment_text ); + +As an equivalent of I<<<<<< createElement >>>>>>, but it creates a I<<<<<< Comment Node >>>>>> bound to the DOM. + + +=item createAttribute + + $attrnode = $doc->createAttribute($name [,$value]); + +Creates a new Attribute node. + + +=item createAttributeNS + + $attrnode = $doc->createAttributeNS( namespaceURI, $name [,$value] ); + +Creates an Attribute bound to a namespace. + + +=item createDocumentFragment + + $fragment = $doc->createDocumentFragment(); + +This function creates a DocumentFragment. + + +=item createCDATASection + + $cdata = $dom->create( $cdata_content ); + +Similar to createTextNode and createComment, this function creates a +CDataSection bound to the current DOM. + + +=item createProcessingInstruction + + my $pi = $doc->createProcessingInstruction( $target, $data ); + +create a processing instruction node. + +Since this method is quite long one may use its short form I<<<<<< createPI() >>>>>>. + + +=item createEntityReference + + my $entref = $doc->createEntityReference($refname); + +If a document has a DTD specified, one can create entity references by using +this function. If one wants to add a entity reference to the document, this +reference has to be created by this function. + +An entity reference is unique to a document and cannot be passed to other +documents as other nodes can be passed. + +I<<<<<< NOTE: >>>>>> A text content containing something that looks like an entity reference, will +not be expanded to a real entity reference unless it is a predefined entity + + + + my $string = "&foo;"; + $some_element->appendText( $string ); + print $some_element->textContent; # prints "&foo;" + + +=item createInternalSubset + + $dtd = $document->createInternalSubset( $rootnode, $public, $system); + +This function creates and adds an internal subset to the given document. +Because the function automatically adds the DTD to the document there is no +need to add the created node explicitly to the document. + + + + my $document = XML::LibXML::Document->new(); + my $dtd = $document->createInternalSubset( "foo", undef, "foo.dtd" ); + +will result in the following XML document: + + + + <?xml version="1.0"?> + <!DOCTYPE foo SYSTEM "foo.dtd"> + +By setting the public parameter it is possible to set PUBLIC DTDs to a given +document. So + + + + my $document = XML::LibXML::Document->new(); + my $dtd = $document->createInternalSubset( "foo", "-//FOO//DTD FOO 0.1//EN", undef ); + +will cause the following declaration to be created on the document: + + + + <?xml version="1.0"?> + <!DOCTYPE foo PUBLIC "-//FOO//DTD FOO 0.1//EN"> + + +=item createExternalSubset + + $dtd = $document->createExternalSubset( $rootnode_name, $publicId, $systemId); + +This function is similar to C<<<<<< createInternalSubset() >>>>>> but this DTD is considered to be external and is therefore not added to the +document itself. Nevertheless it can be used for validation purposes. + + +=item importNode + + $document->importNode( $node ); + +If a node is not part of a document, it can be imported to another document. As +specified in DOM Level 2 Specification the Node will not be altered or removed +from its original document (C<<<<<< $node->cloneNode(1) >>>>>> will get called implicitly). + +I<<<<<< NOTE: >>>>>> Don't try to use importNode() to import sub-trees that contain an entity +reference - even if the entity reference is the root node of the sub-tree. This +will cause serious problems to your program. This is a limitation of libxml2 +and not of XML::LibXML itself. + + +=item adoptNode + + $document->adoptNode( $node ); + +If a node is not part of a document, it can be imported to another document. As +specified in DOM Level 3 Specification the Node will not be altered but it will +removed from its original document. + +After a document adopted a node, the node, its attributes and all its +descendants belong to the new document. Because the node does not belong to the +old document, it will be unlinked from its old location first. + +I<<<<<< NOTE: >>>>>> Don't try to adoptNode() to import sub-trees that contain entity references - +even if the entity reference is the root node of the sub-tree. This will cause +serious problems to your program. This is a limitation of libxml2 and not of +XML::LibXML itself. + + +=item externalSubset + + my $dtd = $doc->externalSubset; + +If a document has an external subset defined it will be returned by this +function. + +I<<<<<< NOTE >>>>>> Dtd nodes are no ordinary nodes in libxml2. The support for these nodes in +XML::LibXML is still limited. In particular one may not want use common node +function on doctype declaration nodes! + + +=item internalSubset + + my $dtd = $doc->internalSubset; + +If a document has an internal subset defined it will be returned by this +function. + +I<<<<<< NOTE >>>>>> Dtd nodes are no ordinary nodes in libxml2. The support for these nodes in +XML::LibXML is still limited. In particular one may not want use common node +function on doctype declaration nodes! + + +=item setExternalSubset + + $doc->setExternalSubset($dtd); + +I<<<<<< EXPERIMENTAL! >>>>>> + +This method sets a DTD node as an external subset of the given document. + + +=item setInternalSubset + + $doc->setInternalSubset($dtd); + +I<<<<<< EXPERIMENTAL! >>>>>> + +This method sets a DTD node as an internal subset of the given document. + + +=item removeExternalSubset + + my $dtd = $doc->removeExternalSubset(); + +I<<<<<< EXPERIMENTAL! >>>>>> + +If a document has an external subset defined it can be removed from the +document by using this function. The removed dtd node will be returned. + + +=item removeInternalSubset + + my $dtd = $doc->removeInternalSubset(); + +I<<<<<< EXPERIMENTAL! >>>>>> + +If a document has an internal subset defined it can be removed from the +document by using this function. The removed dtd node will be returned. + + +=item getElementsByTagName + + my @nodelist = $doc->getElementsByTagName($tagname); + +Implements the DOM Level 2 function + +In SCALAR context this function returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. + + +=item getElementsByTagNameNS + + my @nodelist = $doc->getElementsByTagNameNS($nsURI,$tagname); + +Implements the DOM Level 2 function + +In SCALAR context this function returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. + + +=item getElementsByLocalName + + my @nodelist = $doc->getElementsByLocalName($localname); + +This allows the fetching of all nodes from a given document with the given +Localname. + +In SCALAR context this function returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. + + +=item getElementById + + my $node = $doc->getElementById($id); + +Returns the element that has an ID attribute with the given value. If no such +element exists, this returns undef. + +Note: the ID of an element may change while manipulating the document. For +documents with a DTD, the information about ID attributes is only available if +DTD loading/validation has been requested. For HTML documents parsed with the +HTML parser ID detection is done automatically. In XML documents, all "xml:id" +attributes are considered to be of type ID. You can test ID-ness of an +attribute node with $attr->isId(). + +In versions 1.59 and earlier this method was called getElementsById() (plural) +by mistake. Starting from 1.60 this name is maintained as an alias only for +backward compatibility. + + +=item indexElements + + $dom->indexElements(); + +This function causes libxml2 to stamp all elements in a document with their +document position index which considerably speeds up XPath queries for large +documents. It should only be used with static documents that won't be further +changed by any DOM methods, because once a document is indexed, XPath will +always prefer the index to other methods of determining the document order of +nodes. XPath could therefore return improperly ordered node-lists when applied +on a document that has been changed after being indexed. It is of course +possible to use this method to re-index a modified document before using it +with XPath again. This function is not a part of the DOM specification. + +This function returns number of elements indexed, -1 if error occurred, or -2 +if this feature is not available in the running libxml2. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/DocumentFragment.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/DocumentFragment.pod new file mode 100755 index 00000000000..fb21235c117 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/DocumentFragment.pod @@ -0,0 +1,40 @@ +=head1 NAME + +XML::LibXML::DocumentFragment - XML::LibXML's DOM L2 Document Fragment Implementation + +=head1 SYNOPSIS + + + + use XML::LibXML; + + +=head1 DESCRIPTION + +This class is a helper class as described in the DOM Level 2 Specification. It +is implemented as a node without name. All adding, inserting or replacing +functions are aware of document fragments now. + +As well I<<<<<< all >>>>>> unbound nodes (all nodes that do not belong to any document sub-tree) are +implicit members of document fragments. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Dtd.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Dtd.pod new file mode 100755 index 00000000000..d0b29904c23 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Dtd.pod @@ -0,0 +1,102 @@ +=head1 NAME + +XML::LibXML::Dtd - XML::LibXML DTD Handling + +=head1 SYNOPSIS + + + + use XML::LibXML; + + $dtd = XML::LibXML::Dtd->new($public_id, $system_id); + $dtd = XML::LibXML::Dtd->parse_string($dtd_str); + $publicId = $dtd->getName(); + $publicId = $dtd->publicId(); + $systemId = $dtd->systemId(); + +=head1 DESCRIPTION + +This class holds a DTD. You may parse a DTD from either a string, or from an +external SYSTEM identifier. + +No support is available as yet for parsing from a filehandle. + +XML::LibXML::Dtd is a sub-class of L<<<<<< XML::LibXML::Node >>>>>>, so all the methods available to nodes (particularly toString()) are available +to Dtd objects. + + +=head1 METHODS + +=over 4 + +=item new + + $dtd = XML::LibXML::Dtd->new($public_id, $system_id); + +Parse a DTD from the system identifier, and return a DTD object that you can +pass to $doc->is_valid() or $doc->validate(). + + + + my $dtd = XML::LibXML::Dtd->new( + "SOME // Public / ID / 1.0", + "test.dtd" + ); + my $doc = XML::LibXML->new->parse_file("test.xml"); + $doc->validate($dtd); + + +=item parse_string + + $dtd = XML::LibXML::Dtd->parse_string($dtd_str); + +The same as new() above, except you can parse a DTD from a string. Note that +parsing from string may fail if the DTD contains external parametric-entity +references with relative URLs. + + +=item getName + + $publicId = $dtd->getName(); + +Returns the name of DTD; i.e., the name immediately following the DOCTYPE +keyword. + + +=item publicId + + $publicId = $dtd->publicId(); + +Returns the public identifier of the external subset. + + +=item systemId + + $systemId = $dtd->systemId(); + +Returns the system identifier of the external subset. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Element.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Element.pod new file mode 100755 index 00000000000..b938c25d78c --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Element.pod @@ -0,0 +1,384 @@ +=head1 NAME + +XML::LibXML::Element - XML::LibXML Class for Element Nodes + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to Element nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + $node = XML::LibXML::Element->new( $name ); + $node->setAttribute( $aname, $avalue ); + $node->setAttributeNS( $nsURI, $aname, $avalue ); + $avalue = $node->getAttribute( $aname ); + $avalue = $node->setAttributeNS( $nsURI, $aname ); + $attrnode = $node->getAttributeNode( $aname ); + $attrnode = $node->getAttributeNodeNS( $namespaceURI, $aname ); + $node->removeAttribute( $aname ); + $node->removeAttributeNS( $nsURI, $aname ); + $boolean = $node->hasAttribute( $aname ); + $boolean = $node->hasAttributeNS( $nsURI, $aname ); + @nodes = $node->getChildrenByTagName($tagname); + @nodes = $node->getChildrenByTagNameNS($nsURI,$tagname); + @nodes = $node->getChildrenByLocalName($localname); + @nodes = $node->getElementsByTagName($tagname); + @nodes = $node->getElementsByTagNameNS($nsURI,$localname); + @nodes = $node->getElementsByLocalName($localname); + $node->appendWellBalancedChunk( $chunk ); + $node->appendText( $PCDATA ); + $node->appendTextNode( $PCDATA ); + $node->appendTextChild( $childname , $PCDATA ); + $node->setNamespace( $nsURI , $nsPrefix, $activate ); + $node->setNamespaceDeclURI( $nsPrefix, $newURI ); + $node->setNamespaceDeclPrefix( $oldPrefix, $newPrefix ); + +=head1 METHODS + +The class inherits from L<<<<<< XML::LibXML::Node >>>>>>. The documentation for Inherited methods is not listed here. + +Many functions listed here are extensively documented in the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>). Please refer to the specification for extensive documentation. + +=over 4 + +=item new + + $node = XML::LibXML::Element->new( $name ); + +This function creates a new node unbound to any DOM. + + +=item setAttribute + + $node->setAttribute( $aname, $avalue ); + +This method sets or replaces the node's attribute C<<<<<< $aname >>>>>> to the value C<<<<<< $avalue >>>>>> + + +=item setAttributeNS + + $node->setAttributeNS( $nsURI, $aname, $avalue ); + +Namespace-aware version of C<<<<<< setAttribute >>>>>>, where C<<<<<< $nsURI >>>>>> is a namespace URI, C<<<<<< $aname >>>>>> is a qualified name, and C<<<<<< $avalue >>>>>> is the value. The namespace URI may be null (empty or undefined) in order to +create an attribute which has no namespace. + +The current implementation differs from DOM in the following aspects + +If an attribute with the same local name and namespace URI already exists on +the element, but its prefix differs from the prefix of C<<<<<< $aname >>>>>>, then this function is supposed to change the prefix (regardless of namespace +declarations and possible collisions). However, the current implementation does +rather the opposite. If a prefix is declared for the namespace URI in the scope +of the attribute, then the already declared prefix is used, disregarding the +prefix specified in C<<<<<< $aname >>>>>>. If no prefix is declared for the namespace, the function tries to declare the +prefix specified in C<<<<<< $aname >>>>>> and dies if the prefix is already taken by some other namespace. + +According to DOM Level 2 specification, this method can also be used to create +or modify special attributes used for declaring XML namespaces (which belong to +the namespace "http://www.w3.org/2000/xmlns/" and have prefix or name "xmlns"). +This should work since version 1.61, but again the implementation differs from +DOM specification in the following: if a declaration of the same namespace +prefix already exists on the element, then changing its value via this method +automatically changes the namespace of all elements and attributes in its +scope. This is because in libxml2 the namespace URI of an element is not static +but is computed from a pointer to a namespace declaration attribute. + + +=item getAttribute + + $avalue = $node->getAttribute( $aname ); + +If C<<<<<< $node >>>>>> has an attribute with the name C<<<<<< $aname >>>>>>, the value of this attribute will get returned. + + +=item getAttributeNS + + $avalue = $node->setAttributeNS( $nsURI, $aname ); + +Retrieves an attribute value by local name and namespace URI. + + +=item getAttributeNode + + $attrnode = $node->getAttributeNode( $aname ); + +Retrieve an attribute node by name. If no attribute with a given name exists, C<<<<<< undef >>>>>> is returned. + + +=item getAttributeNodeNS + + $attrnode = $node->getAttributeNodeNS( $namespaceURI, $aname ); + +Retrieves an attribute node by local name and namespace URI. If no attribute +with a given localname and namespace exists, C<<<<<< undef >>>>>> is returned. + + +=item removeAttribute + + $node->removeAttribute( $aname ); + +The method removes the attribute C<<<<<< $aname >>>>>> from the node's attribute list, if the attribute can be found. + + +=item removeAttributeNS + + $node->removeAttributeNS( $nsURI, $aname ); + +Namespace version of C<<<<<< removeAttribute >>>>>> + + +=item hasAttribute + + $boolean = $node->hasAttribute( $aname ); + +This function tests if the named attribute is set for the node. If the +attribute is specified, TRUE (1) will be returned, otherwise the return value +is FALSE (0). + + +=item hasAttributeNS + + $boolean = $node->hasAttributeNS( $nsURI, $aname ); + +namespace version of C<<<<<< hasAttribute >>>>>> + + +=item getChildrenByTagName + + @nodes = $node->getChildrenByTagName($tagname); + +The function gives direct access to all child elements of the current node with +a given tagname, where tagname is a qualified name, that is, in case of +namespace usage it may consist of a prefix and local name. This function makes +things a lot easier if one needs to handle big data sets. A special tagname '*' +can be used to match any name. + +If this function is called in SCALAR context, it returns the number of elements +found. + + +=item getChildrenByTagNameNS + + @nodes = $node->getChildrenByTagNameNS($nsURI,$tagname); + +Namespace version of C<<<<<< getChildrenByTagName >>>>>>. A special nsURI '*' matches any namespace URI, in which case the function +behaves just like C<<<<<< getChildrenByLocalName >>>>>>. + +If this function is called in SCALAR context, it returns the number of elements +found. + + +=item getChildrenByLocalName + + @nodes = $node->getChildrenByLocalName($localname); + +The function gives direct access to all child elements of the current node with +a given local name. It makes things a lot easier if one needs to handle big +data sets. A special C<<<<<< localname >>>>>> '*' can be used to match any local name. + +If this function is called in SCALAR context, it returns the number of elements +found. + + +=item getElementsByTagName + + @nodes = $node->getElementsByTagName($tagname); + +This function is part of the spec. It fetches all descendants of a node with a +given tagname, where C<<<<<< tagname >>>>>> is a qualified name, that is, in case of namespace usage it may consist of a +prefix and local name. A special C<<<<<< tagname >>>>>> '*' can be used to match any tag name. + +In SCALAR context this function returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. + + +=item getElementsByTagNameNS + + @nodes = $node->getElementsByTagNameNS($nsURI,$localname); + +Namespace version of C<<<<<< getElementsByTagName >>>>>> as found in the DOM spec. A special C<<<<<< localname >>>>>> '*' can be used to match any local name and C<<<<<< nsURI >>>>>> '*' can be used to match any namespace URI. + +In SCALAR context this function returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. + + +=item getElementsByLocalName + + @nodes = $node->getElementsByLocalName($localname); + +This function is not found in the DOM specification. It is a mix of +getElementsByTagName and getElementsByTagNameNS. It will fetch all tags +matching the given local-name. This allows one to select tags with the same +local name across namespace borders. + +In SCALAR context this function returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. + + +=item appendWellBalancedChunk + + $node->appendWellBalancedChunk( $chunk ); + +Sometimes it is necessary to append a string coded XML Tree to a node. I<<<<<< appendWellBalancedChunk >>>>>> will do the trick for you. But this is only done if the String is C<<<<<< well-balanced >>>>>>. + +I<<<<<< Note that appendWellBalancedChunk() is only left for compatibility reasons >>>>>>. Implicitly it uses + + + + my $fragment = $parser->parse_xml_chunk( $chunk ); + $node->appendChild( $fragment ); + +This form is more explicit and makes it easier to control the flow of a script. + + +=item appendText + + $node->appendText( $PCDATA ); + +alias for appendTextNode(). + + +=item appendTextNode + + $node->appendTextNode( $PCDATA ); + +This wrapper function lets you add a string directly to an element node. + + +=item appendTextChild + + $node->appendTextChild( $childname , $PCDATA ); + +Somewhat similar with C<<<<<< appendTextNode >>>>>>: It lets you set an Element, that contains only a C<<<<<< text node >>>>>> directly by specifying the name and the text content. + + +=item setNamespace + + $node->setNamespace( $nsURI , $nsPrefix, $activate ); + +setNamespace() allows one to apply a namespace to an element. The function +takes three parameters: 1. the namespace URI, which is required and the two +optional values prefix, which is the namespace prefix, as it should be used in +child elements or attributes as well as the additional activate parameter. If +prefix is not given, undefined or empty, this function tries to create a +declaration of the default namespace. + +The activate parameter is most useful: If this parameter is set to FALSE (0), a +new namespace declaration is simply added to the element while the element's +namespace itself is not altered. Nevertheless, activate is set to TRUE (1) on +default. In this case the namespace is used as the node's effective namespace. +This means the namespace prefix is added to the node name and if there was a +namespace already active for the node, it will be replaced (but its declaration +is not removed from the document). A new namespace declaration is only created +if necessary (that is, if the element is already in the scope of a namespace +declaration associating the prefix with the namespace URI, then this +declaration is reused). + +The following example may clarify this: + + + + my $e1 = $doc->createElement("bar"); + $e1->setNamespace("http://foobar.org", "foo") + +results + + + + <foo:bar xmlns:foo="http://foobar.org"/> + +while + + + + my $e2 = $doc->createElement("bar"); + $e2->setNamespace("http://foobar.org", "foo",0) + +results only + + + + <bar xmlns:foo="http://foobar.org"/> + +By using $activate == 0 it is possible to create multiple namespace +declarations on a single element. + +The function fails if it is required to create a declaration associating the +prefix with the namespace URI but the element already carries a declaration +with the same prefix but different namespace URI. + + +=item setNamespaceDeclURI + + $node->setNamespaceDeclURI( $nsPrefix, $newURI ); + +EXPERIMENTAL IN 1.61 ! + +This function manipulates directly with an existing namespace declaration on an +element. It takes two parameters: the prefix by which it looks up the namespace +declaration and a new namespace URI which replaces its previous value. + +It returns 1 if the namespace declaration was found and changed, 0 otherwise. + +All elements and attributes (even those previously unbound from the document) +for which the namespace declaration determines their namespace belong to the +new namespace after the change. + +If the new URI is undef or empty, the nodes have no namespace and no prefix +after the change. Namespace declarations once nulled in this way do not further +appear in the serialized output (but do remain in the document for internal +integrity of libxml2 data structures). + +This function is NOT part of any DOM API. + + +=item setNamespaceDeclPrefix + + $node->setNamespaceDeclPrefix( $oldPrefix, $newPrefix ); + +EXPERIMENTAL IN 1.61 ! + +This function manipulates directly with an existing namespace declaration on an +element. It takes two parameters: the old prefix by which it looks up the +namespace declaration and a new prefix which is to replace the old one. + +The function dies with an error if the element is in the scope of another +declaration whose prefix equals to the new prefix, or if the change should +result in a declaration with a non-empty prefix but empty namespace URI. +Otherwise, it returns 1 if the namespace declaration was found and changed and +0 if not found. + +All elements and attributes (even those previously unbound from the document) +for which the namespace declaration determines their namespace change their +prefix to the new value. + +If the new prefix is undef or empty, the namespace declaration becomes a +declaration of a default namespace. The corresponding nodes drop their +namespace prefix (but remain in the, now default, namespace). In this case the +function fails, if the containing element is in the scope of another default +namespace declaration. + +This function is NOT part of any DOM API. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/ErrNo.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/ErrNo.pm new file mode 100755 index 00000000000..0e120ab8abe --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/ErrNo.pm @@ -0,0 +1,500 @@ +# $Id: ErrNo.pm,v 1.1.2.1 2004/04/20 20:09:48 pajas Exp $ +# +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::ErrNo; + +use strict; +use vars qw($VERSION); + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use constant ERR_OK => 0; +use constant ERR_INTERNAL_ERROR => 1; +use constant ERR_NO_MEMORY => 2; +use constant ERR_DOCUMENT_START => 3; +use constant ERR_DOCUMENT_EMPTY => 4; +use constant ERR_DOCUMENT_END => 5; +use constant ERR_INVALID_HEX_CHARREF => 6; +use constant ERR_INVALID_DEC_CHARREF => 7; +use constant ERR_INVALID_CHARREF => 8; +use constant ERR_INVALID_CHAR => 9; +use constant ERR_CHARREF_AT_EOF => 10; +use constant ERR_CHARREF_IN_PROLOG => 11; +use constant ERR_CHARREF_IN_EPILOG => 12; +use constant ERR_CHARREF_IN_DTD => 13; +use constant ERR_ENTITYREF_AT_EOF => 14; +use constant ERR_ENTITYREF_IN_PROLOG => 15; +use constant ERR_ENTITYREF_IN_EPILOG => 16; +use constant ERR_ENTITYREF_IN_DTD => 17; +use constant ERR_PEREF_AT_EOF => 18; +use constant ERR_PEREF_IN_PROLOG => 19; +use constant ERR_PEREF_IN_EPILOG => 20; +use constant ERR_PEREF_IN_INT_SUBSET => 21; +use constant ERR_ENTITYREF_NO_NAME => 22; +use constant ERR_ENTITYREF_SEMICOL_MISSING => 23; +use constant ERR_PEREF_NO_NAME => 24; +use constant ERR_PEREF_SEMICOL_MISSING => 25; +use constant ERR_UNDECLARED_ENTITY => 26; +use constant WAR_UNDECLARED_ENTITY => 27; +use constant ERR_UNPARSED_ENTITY => 28; +use constant ERR_ENTITY_IS_EXTERNAL => 29; +use constant ERR_ENTITY_IS_PARAMETER => 30; +use constant ERR_UNKNOWN_ENCODING => 31; +use constant ERR_UNSUPPORTED_ENCODING => 32; +use constant ERR_STRING_NOT_STARTED => 33; +use constant ERR_STRING_NOT_CLOSED => 34; +use constant ERR_NS_DECL_ERROR => 35; +use constant ERR_ENTITY_NOT_STARTED => 36; +use constant ERR_ENTITY_NOT_FINISHED => 37; +use constant ERR_LT_IN_ATTRIBUTE => 38; +use constant ERR_ATTRIBUTE_NOT_STARTED => 39; +use constant ERR_ATTRIBUTE_NOT_FINISHED => 40; +use constant ERR_ATTRIBUTE_WITHOUT_VALUE => 41; +use constant ERR_ATTRIBUTE_REDEFINED => 42; +use constant ERR_LITERAL_NOT_STARTED => 43; +use constant ERR_LITERAL_NOT_FINISHED => 44; +use constant ERR_COMMENT_NOT_FINISHED => 45; +use constant ERR_PI_NOT_STARTED => 46; +use constant ERR_PI_NOT_FINISHED => 47; +use constant ERR_NOTATION_NOT_STARTED => 48; +use constant ERR_NOTATION_NOT_FINISHED => 49; +use constant ERR_ATTLIST_NOT_STARTED => 50; +use constant ERR_ATTLIST_NOT_FINISHED => 51; +use constant ERR_MIXED_NOT_STARTED => 52; +use constant ERR_MIXED_NOT_FINISHED => 53; +use constant ERR_ELEMCONTENT_NOT_STARTED => 54; +use constant ERR_ELEMCONTENT_NOT_FINISHED => 55; +use constant ERR_XMLDECL_NOT_STARTED => 56; +use constant ERR_XMLDECL_NOT_FINISHED => 57; +use constant ERR_CONDSEC_NOT_STARTED => 58; +use constant ERR_CONDSEC_NOT_FINISHED => 59; +use constant ERR_EXT_SUBSET_NOT_FINISHED => 60; +use constant ERR_DOCTYPE_NOT_FINISHED => 61; +use constant ERR_MISPLACED_CDATA_END => 62; +use constant ERR_CDATA_NOT_FINISHED => 63; +use constant ERR_RESERVED_XML_NAME => 64; +use constant ERR_SPACE_REQUIRED => 65; +use constant ERR_SEPARATOR_REQUIRED => 66; +use constant ERR_NMTOKEN_REQUIRED => 67; +use constant ERR_NAME_REQUIRED => 68; +use constant ERR_PCDATA_REQUIRED => 69; +use constant ERR_URI_REQUIRED => 70; +use constant ERR_PUBID_REQUIRED => 71; +use constant ERR_LT_REQUIRED => 72; +use constant ERR_GT_REQUIRED => 73; +use constant ERR_LTSLASH_REQUIRED => 74; +use constant ERR_EQUAL_REQUIRED => 75; +use constant ERR_TAG_NAME_MISMATCH => 76; +use constant ERR_TAG_NOT_FINISHED => 77; +use constant ERR_STANDALONE_VALUE => 78; +use constant ERR_ENCODING_NAME => 79; +use constant ERR_HYPHEN_IN_COMMENT => 80; +use constant ERR_INVALID_ENCODING => 81; +use constant ERR_EXT_ENTITY_STANDALONE => 82; +use constant ERR_CONDSEC_INVALID => 83; +use constant ERR_VALUE_REQUIRED => 84; +use constant ERR_NOT_WELL_BALANCED => 85; +use constant ERR_EXTRA_CONTENT => 86; +use constant ERR_ENTITY_CHAR_ERROR => 87; +use constant ERR_ENTITY_PE_INTERNAL => 88; +use constant ERR_ENTITY_LOOP => 89; +use constant ERR_ENTITY_BOUNDARY => 90; +use constant ERR_INVALID_URI => 91; +use constant ERR_URI_FRAGMENT => 92; +use constant WAR_CATALOG_PI => 93; +use constant ERR_NO_DTD => 94; +use constant ERR_CONDSEC_INVALID_KEYWORD => 95; +use constant ERR_VERSION_MISSING => 96; +use constant WAR_UNKNOWN_VERSION => 97; +use constant WAR_LANG_VALUE => 98; +use constant WAR_NS_URI => 99; +use constant WAR_NS_URI_RELATIVE => 100; +use constant NS_ERR_XML_NAMESPACE => 200; +use constant NS_ERR_UNDEFINED_NAMESPACE => 201; +use constant NS_ERR_QNAME => 202; +use constant NS_ERR_ATTRIBUTE_REDEFINED => 203; +use constant DTD_ATTRIBUTE_DEFAULT => 500; +use constant DTD_ATTRIBUTE_REDEFINED => 501; +use constant DTD_ATTRIBUTE_VALUE => 502; +use constant DTD_CONTENT_ERROR => 503; +use constant DTD_CONTENT_MODEL => 504; +use constant DTD_CONTENT_NOT_DETERMINIST => 505; +use constant DTD_DIFFERENT_PREFIX => 506; +use constant DTD_ELEM_DEFAULT_NAMESPACE => 507; +use constant DTD_ELEM_NAMESPACE => 508; +use constant DTD_ELEM_REDEFINED => 509; +use constant DTD_EMPTY_NOTATION => 510; +use constant DTD_ENTITY_TYPE => 511; +use constant DTD_ID_FIXED => 512; +use constant DTD_ID_REDEFINED => 513; +use constant DTD_ID_SUBSET => 514; +use constant DTD_INVALID_CHILD => 515; +use constant DTD_INVALID_DEFAULT => 516; +use constant DTD_LOAD_ERROR => 517; +use constant DTD_MISSING_ATTRIBUTE => 518; +use constant DTD_MIXED_CORRUPT => 519; +use constant DTD_MULTIPLE_ID => 520; +use constant DTD_NO_DOC => 521; +use constant DTD_NO_DTD => 522; +use constant DTD_NO_ELEM_NAME => 523; +use constant DTD_NO_PREFIX => 524; +use constant DTD_NO_ROOT => 525; +use constant DTD_NOTATION_REDEFINED => 526; +use constant DTD_NOTATION_VALUE => 527; +use constant DTD_NOT_EMPTY => 528; +use constant DTD_NOT_PCDATA => 529; +use constant DTD_NOT_STANDALONE => 530; +use constant DTD_ROOT_NAME => 531; +use constant DTD_STANDALONE_WHITE_SPACE => 532; +use constant DTD_UNKNOWN_ATTRIBUTE => 533; +use constant DTD_UNKNOWN_ELEM => 534; +use constant DTD_UNKNOWN_ENTITY => 535; +use constant DTD_UNKNOWN_ID => 536; +use constant DTD_UNKNOWN_NOTATION => 537; +use constant HTML_STRUCURE_ERROR => 800; +use constant HTML_UNKNOWN_TAG => 801; +use constant RNGP_ANYNAME_ATTR_ANCESTOR => 1000; +use constant RNGP_ATTR_CONFLICT => 1001; +use constant RNGP_ATTRIBUTE_CHILDREN => 1002; +use constant RNGP_ATTRIBUTE_CONTENT => 1003; +use constant RNGP_ATTRIBUTE_EMPTY => 1004; +use constant RNGP_ATTRIBUTE_NOOP => 1005; +use constant RNGP_CHOICE_CONTENT => 1006; +use constant RNGP_CHOICE_EMPTY => 1007; +use constant RNGP_CREATE_FAILURE => 1008; +use constant RNGP_DATA_CONTENT => 1009; +use constant RNGP_DEF_CHOICE_AND_INTERLEAVE => 1010; +use constant RNGP_DEFINE_CREATE_FAILED => 1011; +use constant RNGP_DEFINE_EMPTY => 1012; +use constant RNGP_DEFINE_MISSING => 1013; +use constant RNGP_DEFINE_NAME_MISSING => 1014; +use constant RNGP_ELEM_CONTENT_EMPTY => 1015; +use constant RNGP_ELEM_CONTENT_ERROR => 1016; +use constant RNGP_ELEMENT_EMPTY => 1017; +use constant RNGP_ELEMENT_CONTENT => 1018; +use constant RNGP_ELEMENT_NAME => 1019; +use constant RNGP_ELEMENT_NO_CONTENT => 1020; +use constant RNGP_ELEM_TEXT_CONFLICT => 1021; +use constant RNGP_EMPTY => 1022; +use constant RNGP_EMPTY_CONSTRUCT => 1023; +use constant RNGP_EMPTY_CONTENT => 1024; +use constant RNGP_EMPTY_NOT_EMPTY => 1025; +use constant RNGP_ERROR_TYPE_LIB => 1026; +use constant RNGP_EXCEPT_EMPTY => 1027; +use constant RNGP_EXCEPT_MISSING => 1028; +use constant RNGP_EXCEPT_MULTIPLE => 1029; +use constant RNGP_EXCEPT_NO_CONTENT => 1030; +use constant RNGP_EXTERNALREF_EMTPY => 1031; +use constant RNGP_EXTERNAL_REF_FAILURE => 1032; +use constant RNGP_EXTERNALREF_RECURSE => 1033; +use constant RNGP_FORBIDDEN_ATTRIBUTE => 1034; +use constant RNGP_FOREIGN_ELEMENT => 1035; +use constant RNGP_GRAMMAR_CONTENT => 1036; +use constant RNGP_GRAMMAR_EMPTY => 1037; +use constant RNGP_GRAMMAR_MISSING => 1038; +use constant RNGP_GRAMMAR_NO_START => 1039; +use constant RNGP_GROUP_ATTR_CONFLICT => 1040; +use constant RNGP_HREF_ERROR => 1041; +use constant RNGP_INCLUDE_EMPTY => 1042; +use constant RNGP_INCLUDE_FAILURE => 1043; +use constant RNGP_INCLUDE_RECURSE => 1044; +use constant RNGP_INTERLEAVE_ADD => 1045; +use constant RNGP_INTERLEAVE_CREATE_FAILED => 1046; +use constant RNGP_INTERLEAVE_EMPTY => 1047; +use constant RNGP_INTERLEAVE_NO_CONTENT => 1048; +use constant RNGP_INVALID_DEFINE_NAME => 1049; +use constant RNGP_INVALID_URI => 1050; +use constant RNGP_INVALID_VALUE => 1051; +use constant RNGP_MISSING_HREF => 1052; +use constant RNGP_NAME_MISSING => 1053; +use constant RNGP_NEED_COMBINE => 1054; +use constant RNGP_NOTALLOWED_NOT_EMPTY => 1055; +use constant RNGP_NSNAME_ATTR_ANCESTOR => 1056; +use constant RNGP_NSNAME_NO_NS => 1057; +use constant RNGP_PARAM_FORBIDDEN => 1058; +use constant RNGP_PARAM_NAME_MISSING => 1059; +use constant RNGP_PARENTREF_CREATE_FAILED => 1060; +use constant RNGP_PARENTREF_NAME_INVALID => 1061; +use constant RNGP_PARENTREF_NO_NAME => 1062; +use constant RNGP_PARENTREF_NO_PARENT => 1063; +use constant RNGP_PARENTREF_NOT_EMPTY => 1064; +use constant RNGP_PARSE_ERROR => 1065; +use constant RNGP_PAT_ANYNAME_EXCEPT_ANYNAME => 1066; +use constant RNGP_PAT_ATTR_ATTR => 1067; +use constant RNGP_PAT_ATTR_ELEM => 1068; +use constant RNGP_PAT_DATA_EXCEPT_ATTR => 1069; +use constant RNGP_PAT_DATA_EXCEPT_ELEM => 1070; +use constant RNGP_PAT_DATA_EXCEPT_EMPTY => 1071; +use constant RNGP_PAT_DATA_EXCEPT_GROUP => 1072; +use constant RNGP_PAT_DATA_EXCEPT_INTERLEAVE => 1073; +use constant RNGP_PAT_DATA_EXCEPT_LIST => 1074; +use constant RNGP_PAT_DATA_EXCEPT_ONEMORE => 1075; +use constant RNGP_PAT_DATA_EXCEPT_REF => 1076; +use constant RNGP_PAT_DATA_EXCEPT_TEXT => 1077; +use constant RNGP_PAT_LIST_ATTR => 1078; +use constant RNGP_PAT_LIST_ELEM => 1079; +use constant RNGP_PAT_LIST_INTERLEAVE => 1080; +use constant RNGP_PAT_LIST_LIST => 1081; +use constant RNGP_PAT_LIST_REF => 1082; +use constant RNGP_PAT_LIST_TEXT => 1083; +use constant RNGP_PAT_NSNAME_EXCEPT_ANYNAME => 1084; +use constant RNGP_PAT_NSNAME_EXCEPT_NSNAME => 1085; +use constant RNGP_PAT_ONEMORE_GROUP_ATTR => 1086; +use constant RNGP_PAT_ONEMORE_INTERLEAVE_ATTR => 1087; +use constant RNGP_PAT_START_ATTR => 1088; +use constant RNGP_PAT_START_DATA => 1089; +use constant RNGP_PAT_START_EMPTY => 1090; +use constant RNGP_PAT_START_GROUP => 1091; +use constant RNGP_PAT_START_INTERLEAVE => 1092; +use constant RNGP_PAT_START_LIST => 1093; +use constant RNGP_PAT_START_ONEMORE => 1094; +use constant RNGP_PAT_START_TEXT => 1095; +use constant RNGP_PAT_START_VALUE => 1096; +use constant RNGP_PREFIX_UNDEFINED => 1097; +use constant RNGP_REF_CREATE_FAILED => 1098; +use constant RNGP_REF_CYCLE => 1099; +use constant RNGP_REF_NAME_INVALID => 1100; +use constant RNGP_REF_NO_DEF => 1101; +use constant RNGP_REF_NO_NAME => 1102; +use constant RNGP_REF_NOT_EMPTY => 1103; +use constant RNGP_START_CHOICE_AND_INTERLEAVE => 1104; +use constant RNGP_START_CONTENT => 1105; +use constant RNGP_START_EMPTY => 1106; +use constant RNGP_START_MISSING => 1107; +use constant RNGP_TEXT_EXPECTED => 1108; +use constant RNGP_TEXT_HAS_CHILD => 1109; +use constant RNGP_TYPE_MISSING => 1110; +use constant RNGP_TYPE_NOT_FOUND => 1111; +use constant RNGP_TYPE_VALUE => 1112; +use constant RNGP_UNKNOWN_ATTRIBUTE => 1113; +use constant RNGP_UNKNOWN_COMBINE => 1114; +use constant RNGP_UNKNOWN_CONSTRUCT => 1115; +use constant RNGP_UNKNOWN_TYPE_LIB => 1116; +use constant RNGP_URI_FRAGMENT => 1117; +use constant RNGP_URI_NOT_ABSOLUTE => 1118; +use constant RNGP_VALUE_EMPTY => 1119; +use constant RNGP_VALUE_NO_CONTENT => 1120; +use constant RNGP_XMLNS_NAME => 1121; +use constant RNGP_XML_NS => 1122; +use constant XPATH_EXPRESSION_OK => 1200; +use constant XPATH_NUMBER_ERROR => 1201; +use constant XPATH_UNFINISHED_LITERAL_ERROR => 1202; +use constant XPATH_START_LITERAL_ERROR => 1203; +use constant XPATH_VARIABLE_REF_ERROR => 1204; +use constant XPATH_UNDEF_VARIABLE_ERROR => 1205; +use constant XPATH_INVALID_PREDICATE_ERROR => 1206; +use constant XPATH_EXPR_ERROR => 1207; +use constant XPATH_UNCLOSED_ERROR => 1208; +use constant XPATH_UNKNOWN_FUNC_ERROR => 1209; +use constant XPATH_INVALID_OPERAND => 1210; +use constant XPATH_INVALID_TYPE => 1211; +use constant XPATH_INVALID_ARITY => 1212; +use constant XPATH_INVALID_CTXT_SIZE => 1213; +use constant XPATH_INVALID_CTXT_POSITION => 1214; +use constant XPATH_MEMORY_ERROR => 1215; +use constant XPTR_SYNTAX_ERROR => 1216; +use constant XPTR_RESOURCE_ERROR => 1217; +use constant XPTR_SUB_RESOURCE_ERROR => 1218; +use constant XPATH_UNDEF_PREFIX_ERROR => 1219; +use constant XPATH_ENCODING_ERROR => 1220; +use constant XPATH_INVALID_CHAR_ERROR => 1221; +use constant TREE_INVALID_HEX => 1300; +use constant TREE_INVALID_DEC => 1301; +use constant TREE_UNTERMINATED_ENTITY => 1302; +use constant SAVE_NOT_UTF8 => 1400; +use constant SAVE_CHAR_INVALID => 1401; +use constant SAVE_NO_DOCTYPE => 1402; +use constant SAVE_UNKNOWN_ENCODING => 1403; +use constant REGEXP_COMPILE_ERROR => 1450; +use constant IO_UNKNOWN => 1500; +use constant IO_EACCES => 1501; +use constant IO_EAGAIN => 1502; +use constant IO_EBADF => 1503; +use constant IO_EBADMSG => 1504; +use constant IO_EBUSY => 1505; +use constant IO_ECANCELED => 1506; +use constant IO_ECHILD => 1507; +use constant IO_EDEADLK => 1508; +use constant IO_EDOM => 1509; +use constant IO_EEXIST => 1510; +use constant IO_EFAULT => 1511; +use constant IO_EFBIG => 1512; +use constant IO_EINPROGRESS => 1513; +use constant IO_EINTR => 1514; +use constant IO_EINVAL => 1515; +use constant IO_EIO => 1516; +use constant IO_EISDIR => 1517; +use constant IO_EMFILE => 1518; +use constant IO_EMLINK => 1519; +use constant IO_EMSGSIZE => 1520; +use constant IO_ENAMETOOLONG => 1521; +use constant IO_ENFILE => 1522; +use constant IO_ENODEV => 1523; +use constant IO_ENOENT => 1524; +use constant IO_ENOEXEC => 1525; +use constant IO_ENOLCK => 1526; +use constant IO_ENOMEM => 1527; +use constant IO_ENOSPC => 1528; +use constant IO_ENOSYS => 1529; +use constant IO_ENOTDIR => 1530; +use constant IO_ENOTEMPTY => 1531; +use constant IO_ENOTSUP => 1532; +use constant IO_ENOTTY => 1533; +use constant IO_ENXIO => 1534; +use constant IO_EPERM => 1535; +use constant IO_EPIPE => 1536; +use constant IO_ERANGE => 1537; +use constant IO_EROFS => 1538; +use constant IO_ESPIPE => 1539; +use constant IO_ESRCH => 1540; +use constant IO_ETIMEDOUT => 1541; +use constant IO_EXDEV => 1542; +use constant IO_NETWORK_ATTEMPT => 1543; +use constant IO_ENCODER => 1544; +use constant IO_FLUSH => 1545; +use constant IO_WRITE => 1546; +use constant IO_NO_INPUT => 1547; +use constant IO_BUFFER_FULL => 1548; +use constant IO_LOAD_ERROR => 1549; +use constant IO_ENOTSOCK => 1550; +use constant IO_EISCONN => 1551; +use constant IO_ECONNREFUSED => 1552; +use constant IO_ENETUNREACH => 1553; +use constant IO_EADDRINUSE => 1554; +use constant IO_EALREADY => 1555; +use constant IO_EAFNOSUPPORT => 1556; +use constant XINCLUDE_RECURSION => 1600; +use constant XINCLUDE_PARSE_VALUE => 1601; +use constant XINCLUDE_ENTITY_DEF_MISMATCH => 1602; +use constant XINCLUDE_NO_HREF => 1603; +use constant XINCLUDE_NO_FALLBACK => 1604; +use constant XINCLUDE_HREF_URI => 1605; +use constant XINCLUDE_TEXT_FRAGMENT => 1606; +use constant XINCLUDE_TEXT_DOCUMENT => 1607; +use constant XINCLUDE_INVALID_CHAR => 1608; +use constant XINCLUDE_BUILD_FAILED => 1609; +use constant XINCLUDE_UNKNOWN_ENCODING => 1610; +use constant XINCLUDE_MULTIPLE_ROOT => 1611; +use constant XINCLUDE_XPTR_FAILED => 1612; +use constant XINCLUDE_XPTR_RESULT => 1613; +use constant XINCLUDE_INCLUDE_IN_INCLUDE => 1614; +use constant XINCLUDE_FALLBACKS_IN_INCLUDE => 1615; +use constant XINCLUDE_FALLBACK_NOT_IN_INCLUDE => 1616; +use constant CATALOG_MISSING_ATTR => 1650; +use constant CATALOG_ENTRY_BROKEN => 1651; +use constant CATALOG_PREFER_VALUE => 1652; +use constant CATALOG_NOT_CATALOG => 1653; +use constant CATALOG_RECURSION => 1654; +use constant SCHEMAP_PREFIX_UNDEFINED => 1700; +use constant SCHEMAP_ATTRFORMDEFAULT_VALUE => 1701; +use constant SCHEMAP_ATTRGRP_NONAME_NOREF => 1702; +use constant SCHEMAP_ATTR_NONAME_NOREF => 1703; +use constant SCHEMAP_COMPLEXTYPE_NONAME_NOREF => 1704; +use constant SCHEMAP_ELEMFORMDEFAULT_VALUE => 1705; +use constant SCHEMAP_ELEM_NONAME_NOREF => 1706; +use constant SCHEMAP_EXTENSION_NO_BASE => 1707; +use constant SCHEMAP_FACET_NO_VALUE => 1708; +use constant SCHEMAP_FAILED_BUILD_IMPORT => 1709; +use constant SCHEMAP_GROUP_NONAME_NOREF => 1710; +use constant SCHEMAP_IMPORT_NAMESPACE_NOT_URI => 1711; +use constant SCHEMAP_IMPORT_REDEFINE_NSNAME => 1712; +use constant SCHEMAP_IMPORT_SCHEMA_NOT_URI => 1713; +use constant SCHEMAP_INVALID_BOOLEAN => 1714; +use constant SCHEMAP_INVALID_ENUM => 1715; +use constant SCHEMAP_INVALID_FACET => 1716; +use constant SCHEMAP_INVALID_FACET_VALUE => 1717; +use constant SCHEMAP_INVALID_MAXOCCURS => 1718; +use constant SCHEMAP_INVALID_MINOCCURS => 1719; +use constant SCHEMAP_INVALID_REF_AND_SUBTYPE => 1720; +use constant SCHEMAP_INVALID_WHITE_SPACE => 1721; +use constant SCHEMAP_NOATTR_NOREF => 1722; +use constant SCHEMAP_NOTATION_NO_NAME => 1723; +use constant SCHEMAP_NOTYPE_NOREF => 1724; +use constant SCHEMAP_REF_AND_SUBTYPE => 1725; +use constant SCHEMAP_RESTRICTION_NONAME_NOREF => 1726; +use constant SCHEMAP_SIMPLETYPE_NONAME => 1727; +use constant SCHEMAP_TYPE_AND_SUBTYPE => 1728; +use constant SCHEMAP_UNKNOWN_ALL_CHILD => 1729; +use constant SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD => 1730; +use constant SCHEMAP_UNKNOWN_ATTR_CHILD => 1731; +use constant SCHEMAP_UNKNOWN_ATTRGRP_CHILD => 1732; +use constant SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP => 1733; +use constant SCHEMAP_UNKNOWN_BASE_TYPE => 1734; +use constant SCHEMAP_UNKNOWN_CHOICE_CHILD => 1735; +use constant SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD => 1736; +use constant SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD => 1737; +use constant SCHEMAP_UNKNOWN_ELEM_CHILD => 1738; +use constant SCHEMAP_UNKNOWN_EXTENSION_CHILD => 1739; +use constant SCHEMAP_UNKNOWN_FACET_CHILD => 1740; +use constant SCHEMAP_UNKNOWN_FACET_TYPE => 1741; +use constant SCHEMAP_UNKNOWN_GROUP_CHILD => 1742; +use constant SCHEMAP_UNKNOWN_IMPORT_CHILD => 1743; +use constant SCHEMAP_UNKNOWN_LIST_CHILD => 1744; +use constant SCHEMAP_UNKNOWN_NOTATION_CHILD => 1745; +use constant SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD => 1746; +use constant SCHEMAP_UNKNOWN_REF => 1747; +use constant SCHEMAP_UNKNOWN_RESTRICTION_CHILD => 1748; +use constant SCHEMAP_UNKNOWN_SCHEMAS_CHILD => 1749; +use constant SCHEMAP_UNKNOWN_SEQUENCE_CHILD => 1750; +use constant SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD => 1751; +use constant SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD => 1752; +use constant SCHEMAP_UNKNOWN_TYPE => 1753; +use constant SCHEMAP_UNKNOWN_UNION_CHILD => 1754; +use constant SCHEMAP_ELEM_DEFAULT_FIXED => 1755; +use constant SCHEMAP_REGEXP_INVALID => 1756; +use constant SCHEMAP_FAILED_LOAD => 1756; +use constant SCHEMAP_NOTHING_TO_PARSE => 1757; +use constant SCHEMAP_NOROOT => 1758; +use constant SCHEMAP_REDEFINED_GROUP => 1759; +use constant SCHEMAP_REDEFINED_TYPE => 1760; +use constant SCHEMAP_REDEFINED_ELEMENT => 1761; +use constant SCHEMAP_REDEFINED_ATTRGROUP => 1762; +use constant SCHEMAP_REDEFINED_ATTR => 1763; +use constant SCHEMAP_REDEFINED_NOTATION => 1764; +use constant SCHEMAP_FAILED_PARSE => 1765; +use constant SCHEMAV_NOROOT => 1800; +use constant SCHEMAV_UNDECLAREDELEM => 1801; +use constant SCHEMAV_NOTTOPLEVEL => 1802; +use constant SCHEMAV_MISSING => 1803; +use constant SCHEMAV_WRONGELEM => 1804; +use constant SCHEMAV_NOTYPE => 1805; +use constant SCHEMAV_NOROLLBACK => 1806; +use constant SCHEMAV_ISABSTRACT => 1807; +use constant SCHEMAV_NOTEMPTY => 1808; +use constant SCHEMAV_ELEMCONT => 1809; +use constant SCHEMAV_HAVEDEFAULT => 1810; +use constant SCHEMAV_NOTNILLABLE => 1811; +use constant SCHEMAV_EXTRACONTENT => 1812; +use constant SCHEMAV_INVALIDATTR => 1813; +use constant SCHEMAV_INVALIDELEM => 1814; +use constant SCHEMAV_NOTDETERMINIST => 1815; +use constant SCHEMAV_CONSTRUCT => 1816; +use constant SCHEMAV_INTERNAL => 1817; +use constant SCHEMAV_NOTSIMPLE => 1818; +use constant SCHEMAV_ATTRUNKNOWN => 1819; +use constant SCHEMAV_ATTRINVALID => 1820; +use constant SCHEMAV_VALUE => 1821; +use constant SCHEMAV_FACET => 1822; +use constant XPTR_UNKNOWN_SCHEME => 1900; +use constant XPTR_CHILDSEQ_START => 1901; +use constant XPTR_EVAL_FAILED => 1902; +use constant XPTR_EXTRA_OBJECTS => 1903; +use constant C14N_CREATE_CTXT => 1950; +use constant C14N_REQUIRES_UTF8 => 1951; +use constant C14N_CREATE_STACK => 1952; +use constant C14N_INVALID_NODE => 1953; +use constant FTP_PASV_ANSWER => 2000; +use constant FTP_EPSV_ANSWER => 2001; +use constant FTP_ACCNT => 2002; +use constant HTTP_URL_SYNTAX => 2020; +use constant HTTP_USE_IP => 2021; +use constant HTTP_UNKNOWN_HOST => 2022; + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/ErrNo.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/ErrNo.pod new file mode 100755 index 00000000000..39b5cf432c3 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/ErrNo.pod @@ -0,0 +1,27 @@ +=head1 NAME + +XML::LibXML::ErrNo - Structured Errors +This module is based on xmlerror.h libxml2 C header file. It defines symbolic +constants for all libxml2 error codes. Currently libxml2 uses over 480 +different error codes. See also XML::LibXML::Error. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Error.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/Error.pm new file mode 100755 index 00000000000..b60d6cf2e9e --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Error.pm @@ -0,0 +1,229 @@ +# $Id: Error.pm,v 1.1.2.1 2004/04/20 20:09:48 pajas Exp $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# +package XML::LibXML::Error; + +use strict; +use vars qw($AUTOLOAD @error_domains $VERSION $WARNINGS); +use Carp; +use overload + '""' => \&as_string, + 'eq' => sub { + ("$_[0]" eq "$_[1]") + }, + 'cmp' => sub { + ("$_[0]" cmp "$_[1]") + }, + fallback => 1; + +$WARNINGS = 0; # 0: supress, 1: report via warn, 2: report via die +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use constant XML_ERR_NONE => 0; +use constant XML_ERR_WARNING => 1; # A simple warning +use constant XML_ERR_ERROR => 2; # A recoverable error +use constant XML_ERR_FATAL => 3; # A fatal error + +use constant XML_ERR_FROM_NONE => 0; +use constant XML_ERR_FROM_PARSER => 1; # The XML parser +use constant XML_ERR_FROM_TREE => 2; # The tree module +use constant XML_ERR_FROM_NAMESPACE => 3; # The XML Namespace module +use constant XML_ERR_FROM_DTD => 4; # The XML DTD validation +use constant XML_ERR_FROM_HTML => 5; # The HTML parser +use constant XML_ERR_FROM_MEMORY => 6; # The memory allocator +use constant XML_ERR_FROM_OUTPUT => 7; # The serialization code +use constant XML_ERR_FROM_IO => 8; # The Input/Output stack +use constant XML_ERR_FROM_FTP => 9; # The FTP module +use constant XML_ERR_FROM_HTTP => 10; # The FTP module +use constant XML_ERR_FROM_XINCLUDE => 11; # The XInclude processing +use constant XML_ERR_FROM_XPATH => 12; # The XPath module +use constant XML_ERR_FROM_XPOINTER => 13; # The XPointer module +use constant XML_ERR_FROM_REGEXP => 14; # The regular expressions module +use constant XML_ERR_FROM_DATATYPE => 15; # The W3C XML Schemas Datatype module +use constant XML_ERR_FROM_SCHEMASP => 16; # The W3C XML Schemas parser module +use constant XML_ERR_FROM_SCHEMASV => 17; # The W3C XML Schemas validation module +use constant XML_ERR_FROM_RELAXNGP => 18; # The Relax-NG parser module +use constant XML_ERR_FROM_RELAXNGV => 19; # The Relax-NG validator module +use constant XML_ERR_FROM_CATALOG => 20; # The Catalog module +use constant XML_ERR_FROM_C14N => 21; # The Canonicalization module +use constant XML_ERR_FROM_XSLT => 22; # The XSLT engine from libxslt +use constant XML_ERR_FROM_VALID => 23; # The validaton module + +@error_domains = ("", "parser", "tree", "namespace", "validity", + "HTML parser", "memory", "output", "I/O", "ftp", + "http", "XInclude", "XPath", "xpointer", "regexp", + "Schemas datatype", "Schemas parser", "Schemas validity", + "Relax-NG parser", "Relax-NG validity", + "Catalog", "C14N", "XSLT", "validity"); + +{ + + sub new { + my ($class,$xE) = @_; + my $terr; + if (ref($xE)) { + my ($context,$column) = $xE->context_and_column(); + $terr =bless { + domain => $xE->domain(), + level => $xE->level(), + code => $xE->code(), + message => $xE->message(), + file => $xE->file(), + line => $xE->line(), + str1 => $xE->str1(), + str2 => $xE->str2(), + str3 => $xE->str3(), + num1 => $xE->num1(), + num2 => $xE->num2(), + (defined($context) ? + ( + context => $context, + column => $column, + ) : ()), + }, $class; + } else { + # !!!! problem : got a flat error + # warn("PROBLEM: GOT A FLAT ERROR $xE\n"); + $terr =bless { + domain => 0, + level => 2, + code => -1, + message => $xE, + file => undef, + line => undef, + str1 => undef, + str2 => undef, + str3 => undef, + num1 => undef, + num2 => undef, + }, $class; + } + return $terr; + } + + sub _callback_error { + #print "CALLBACK\n"; + my ($xE,$prev) = @_; + my $terr; + $terr=XML::LibXML::Error->new($xE); + if ($terr->{level} == XML_ERR_WARNING and $WARNINGS!=2) { + warn $terr if $WARNINGS; + return $prev; + } + #unless ( defined $terr->{file} and length $terr->{file} ) { + # this would make it easier to recognize parsed strings + # but it breaks old implementations + # [CG] $terr->{file} = 'string()'; + #} + #warn "Saving the error ",$terr->dump; + $terr->{_prev} = ref($prev) ? $prev : + defined($prev) && length($prev) ? XML::LibXML::Error->new($prev) : undef; + return $terr; + } + sub _instant_error_callback { + my $xE = shift; + my $terr= XML::LibXML::Error->new($xE); + print "Reporting an instanteous error ",$terr->dump; + die $terr; + } + sub _report_warning { + my ($saved_error) = @_; + #print "CALLBACK WARN\n"; + if ( defined $saved_error ) { + #print "reporting a warning ",$saved_error->dump; + warn $saved_error; + } + } + sub _report_error { + my ($saved_error) = @_; + #print "CALLBACK ERROR: $saved_error\n"; + if ( defined $saved_error ) { + die $saved_error; + } + } +} + + +sub AUTOLOAD { + my $self=shift; + return undef unless ref($self); + my $sub = $AUTOLOAD; + $sub =~ s/.*:://; + if ($sub=~/^(?:code|_prev|level|file|line|domain|nodename|message|column|context|str[123]|num[12])$/) { + return $self->{$sub}; + } else { + croak("Unknown error field $sub"); + } +} + +# backward compatibility +sub int1 { $_[0]->num1 } +sub int2 { $_[0]->num2 } + +sub DESTROY {} + +sub domain { + my ($self)=@_; + return undef unless ref($self); + return $error_domains[$self->{domain}]; +} + +sub as_string { + my ($self)=@_; + my $msg = ""; + my $level; + + if (defined($self->{_prev})) { + $msg = $self->{_prev}->as_string; + } + + if ($self->{level} == XML_ERR_NONE) { + $level = ""; + } elsif ($self->{level} == XML_ERR_WARNING) { + $level = "warning"; + } elsif ($self->{level} == XML_ERR_ERROR || + $self->{level} == XML_ERR_FATAL) { + $level = "error"; + } + my $where=""; + if (defined($self->{file})) { + $where="$self->{file}:$self->{line}"; + } elsif (($self->{domain} == XML_ERR_FROM_PARSER) + and + $self->{line}) { + $where="Entity: line $self->{line}"; + } + if ($self->{nodename}) { + $where.=": element ".$self->{nodename}; + } + $msg.=$where.": " if $where ne ""; + $msg.=$error_domains[$self->{domain}]." ".$level." :"; + my $str=$self->{message}||""; + chomp($str); + $msg.=" ".$str."\n"; + if (($self->{domain} == XML_ERR_FROM_XPATH) and + defined($self->{str1})) { + $msg.=$self->{str1}."\n"; + $msg.=(" " x $self->{num1})."^\n"; + } elsif (defined $self->{context}) { + my $context = $self->{context}; + $msg.=$context."\n"; + $context = substr($context,0,$self->{column}); + $context=~s/[^\t]/ /g; + $msg.=$context."^\n"; + } + return $msg; +} + +sub dump { + my ($self)=@_; + use Data::Dumper; + return Data::Dumper->new([$self],['error'])->Dump; +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Error.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Error.pod new file mode 100755 index 00000000000..9583ba5b76f --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Error.pod @@ -0,0 +1,254 @@ +=head1 NAME + +XML::LibXML::Error - Structured Errors + +=head1 SYNOPSIS + + + + eval { ... }; + if (ref($@)) { + # handle a structured error (XML::LibXML::Error object) + } elsif ($@) { + # error, but not an XML::LibXML::Error object + } else { + # no error + } + + $XML::LibXML::Error::WARNINGS=1; + $message = $@->as_string(); + print $@->dump(); + $error_domain = $@->domain(); + $error_code = $@->code(); + $error_message = $@->message(); + $error_level = $@->level(); + $filename = $@->file(); + $line = $@->line(); + $nodename = $@->nodename(); + $error_str1 = $@->str1(); + $error_str2 = $@->str2(); + $error_str3 = $@->str3(); + $error_num1 = $@->num1(); + $error_num2 = $@->num2(); + $string = $@->context(); + $offset = $@->column(); + $previous_error = $@->_prev(); + +=head1 DESCRIPTION + +The XML::LibXML::Error class is a tiny frontend to I<<<<<< libxml2 >>>>>>'s structured error support. If XML::LibXML is compied with structured error +support, all errors reported by libxml2 are transformed to XML::LibXML:Error +objects. These objects automatically serialize to the corresponding error +messages when printed or used in a string operation, but as objects, can also +be used to get a detailed and structured information about the error that +occurred. + +Unlike most other XML::LibXML objects, XML::LibXML::Error doesn't wrap an +underlying I<<<<<< libxml2 >>>>>> structure directly, but rather transforms it to a blessed Perl hash reference +containing the individual fields of the structured error information as hash +key-value pairs. Individual items (fields) of a structured error can either be +obtained directly as $@->{field}, or using autoloaded methods such as as +$@->field() (where field is the field name). XML::LibXML::Error objects have +the following fields: domain, code, level, file, line, nodename, message, str1, +str2, str3, num1, num2, and _prev (some of them may be undefined). + +=over 4 + +=item $XML::LibXML::Error::WARNINGS + + $XML::LibXML::Error::WARNINGS=1; + +Traditionally, XML::LibXML was supressing parser warnings by setting libxml2's +global variable xmlGetWarningsDefaultValue to 0. Since 1.70 we do not change +libxml2's global variables anymore; for backward compatibility, XML::LibXML +suppresses warnings. This variable can be set to 1 to enable reporting of these +warnings via Perl C<<<<<< warn >>>>>> and to 2 to report hem via C<<<<<< die >>>>>>. + + $message = $@->as_string(); + +This functions takes serializes a XML::LibXML::Error object to a string +containing the full error message close to the message produced by I<<<<<< libxml2 >>>>>> default error handlers and tools like xmllint. This method is also used to +overload "" operator on XML::LibXML::Error, so it is automatically called +whenever XML::LibXML::Error object is treated as a string (e.g. in print $@). + + +=item dump + + print $@->dump(); + +This function serializes a XML::LibXML::Error to a string displaying all fields +of the error structure individually on separate lines of the form 'name' => +'value'. + + +=item domain + + $error_domain = $@->domain(); + +Returns string containing information about what part of the library raised the +error. Can be one of: "parser", "tree", "namespace", "validity", "HTML parser", +"memory", "output", "I/O", "ftp", "http", "XInclude", "XPath", "xpointer", +"regexp", "Schemas datatype", "Schemas parser", "Schemas validity", "Relax-NG +parser", "Relax-NG validity", "Catalog", "C14N", "XSLT", "validity". + + +=item code + + $error_code = $@->code(); + +Returns the actual libxml2 error code. The XML::LibXML::ErrNo module defines +constants for individual error codes. Currently libxml2 uses over 480 different +error codes. + + +=item message + + $error_message = $@->message(); + +Returns a human-readable informative error message. + + +=item level + + $error_level = $@->level(); + +Returns an integer value describing how consequent is the error. +XML::LibXML::Error defines the following constants: + + +=over 4 + +=item * + +XML_ERR_NONE = 0 + + + +=item * + +XML_ERR_WARNING = 1 : A simple warning. + + + +=item * + +XML_ERR_ERROR = 2 : A recoverable error. + + + +=item * + +XML_ERR_FATAL = 3 : A fatal error. + + + +=back + + +=item file + + $filename = $@->file(); + +Returns the filename of the file being processed while the error occurred. + + +=item line + + $line = $@->line(); + +The line number, if available. + + +=item nodename + + $nodename = $@->nodename(); + +Name of the node where error occurred, if available. When this field is +non-empty, libxml2 actually returned a physical pointer to the specified node. +Due to memory management issues, it is very difficult to implement a way to +expose the pointer to the Perl level as a XML::LibXML::Node. For this reason, +XML::LibXML::Error currently only exposes the name the node. + + +=item str1 + + $error_str1 = $@->str1(); + +Error specific. Extra string information. + + +=item str2 + + $error_str2 = $@->str2(); + +Error specific. Extra string information. + + +=item str3 + + $error_str3 = $@->str3(); + +Error specific. Extra string information. + + +=item num1 + + $error_num1 = $@->num1(); + +Error specific. Extra numeric information. + + +=item num2 + + $error_num2 = $@->num2(); + +In recent libxml2 versions, this value contains a column number of the error or +0 if N/A. + + +=item context + + $string = $@->context(); + +For parsing errors, this field contains about 80 characters of the XML near the +place where the error occurred. The field C<<<<<< $@->column() >>>>>> contains the corresponding offset. Where N/A, the field is undefined. + + +=item column + + $offset = $@->column(); + +See C<<<<<< $@->column() >>>>>> above. + + +=item _prev + + $previous_error = $@->_prev(); + +This field can possibly hold a reference to another XML::LibXML::Error object +representing an error which occurred just before this error. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/InputCallback.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/InputCallback.pod new file mode 100755 index 00000000000..d3766162629 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/InputCallback.pod @@ -0,0 +1,292 @@ +=head1 NAME + +XML::LibXML::InputCallback - XML::LibXML Class for Input Callbacks + +=head1 SYNOPSIS + + + + use XML::LibXML; + + +=head1 DESCRIPTION + +You may get unexpected results if you are trying to load external documents +during libxml2 parsing if the location of the resource is not a HTTP, FTP or +relative location but a absolute path for example. To get around this +limitation, you may add your own input handler to open, read and close +particular types of locations or URI classes. Using this input callback +handlers, you can handle your own custom URI schemes for example. + +The input callbacks are used whenever LibXML has to get something other than +externally parsed entities from somewhere. They are implemented using a +callback stack on the Perl layer in analogy to libxml2's native callback stack. + +The XML::LibXML::InputCallback class transparently registers the input +callbacks for the libxml2's parser processes. + + +=head2 How does XML::LibXML::InputCallback work? + +The libxml2 library offers a callback implementation as global functions only. +To work-around the troubles resulting in having only global callbacks - for +example, if the same global callback stack is manipulated by different +applications running together in a single Apache Web-server environment -, +XML::LibXML::InputCallback comes with a object-oriented and a function-oriented +part. + +Using the function-oriented part the global callback stack of libxml2 can be +manipulated. Those functions can be used as interface to the callbacks on the +C- and XS Layer. At the object-oriented part, operations for working with the +"pseudo-localized" callback stack are implemented. Currently, you can register +and de-register callbacks on the Perl layer and initialize them on a per parser +basis. + + +=head3 Callback Groups + +The libxml2 input callbacks come in groups. One group contains a URI matcher (I<<<<<< match >>>>>>), a data stream constructor (I<<<<<< open >>>>>>), a data stream reader (I<<<<<< read >>>>>>), and a data stream destructor (I<<<<<< close >>>>>>). The callbacks can be manipulated on a per group basis only. + + +=head3 The Parser Process + +The parser process work on a XML data stream, along which, links to other +resources can be embedded. This can be links to external DTDs or XIncludes for +example. Those resources are identified by URIs. The callback implementation of +libxml2 assumes that one callback group can handle a certain amount of URIs and +a certain URI scheme. Per default, callback handlers for I<<<<<< file://* >>>>>>, I<<<<<< file:://*.gz >>>>>>, I<<<<<< http://* >>>>>> and I<<<<<< ftp://* >>>>>> are registered. + +Callback groups in the callback stack are processed from top to bottom, meaning +that callback groups registered later will be processed before the earlier +registered ones. + +While parsing the data stream, the libxml2 parser checks if a registered +callback group will handle a URI - if they will not, the URI will be +interpreted as I<<<<<< file://URI >>>>>>. To handle a URI, the I<<<<<< match >>>>>> callback will have to return '1'. If that happens, the handling of the URI will +be passed to that callback group. Next, the URI will be passed to the I<<<<<< open >>>>>> callback, which should return a I<<<<<< reference >>>>>> to the data stream if it successfully opened the file, '0' otherwise. If +opening the stream was successful, the I<<<<<< read >>>>>> callback will be called repeatedly until it returns an empty string. After the +read callback, the I<<<<<< close >>>>>> callback will be called to close the stream. + + +=head3 Organisation of callback groups in XML::LibXML::InputCallback + +Callback groups are implemented as a stack (Array), each entry holds a +reference to an array of the callbacks. For the libxml2 library, the +XML::LibXML::InputCallback callback implementation appears as one single +callback group. The Perl implementation however allows to manage different +callback stacks on a per libxml2-parser basis. + + +=head2 Using XML::LibXML::InputCallback + +After object instantiation using the parameter-less constructor, you can +register callback groups. + + + + my $input_callbacks = XML::LibXML::InputCallback->new(); + $input_callbacks->register_callbacks([ $match_cb1, $open_cb1, + $read_cb1, $close_cb1 ] ); + $input_callbacks->register_callbacks([ $match_cb2, $open_cb2, + $read_cb2, $close_cb2 ] ); + $input_callbacks->register_callbacks( [ $match_cb3, $open_cb3, + $read_cb3, $close_cb3 ] ); + + $parser->input_callbacks( $input_callbacks ); + $parser->parse_file( $some_xml_file ); + + +=head2 What about the old callback system prior to XML::LibXML::InputCallback? + +In XML::LibXML versions prior to 1.59 - i.e. without the +XML::LibXML::InputCallback module - you could define your callbacks either +using globally or locally. You still can do that using +XML::LibXML::InputCallback, and in addition to that you can define the +callbacks on a per parser basis! + +If you use the old callback interface through global callbacks, +XML::LibXML::InputCallback will treat them with a lower priority as the ones +registered using the new interface. The global callbacks will not override the +callback groups registered using the new interface. Local callbacks are +attached to a specific parser instance, therefore they are treated with highest +priority. If the I<<<<<< match >>>>>> callback of the callback group registered as local variable is identical to one +of the callback groups registered using the new interface, that callback group +will be replaced. + +Users of the old callback implementation whose I<<<<<< open >>>>>> callback returned a plain string, will have to adapt their code to return a +reference to that string after upgrading to version >= 1.59. The new callback +system can only deal with the I<<<<<< open >>>>>> callback returning a reference! + + +=head1 INTERFACE DESCRIPTION + + +=head2 Global Variables + +=over 4 + +=item $_CUR_CB + +Stores the current callback and can be used as shortcut to access the callback +stack. + + +=item @_GLOBAL_CALLBACKS + +Stores all callback groups for the current parser process. + + +=item @_CB_STACK + +Stores the currently used callback group. Used to prevent parser errors when +dealing with nested XML data. + + + +=back + + +=head2 Global Callbacks + +=over 4 + +=item _callback_match + +Implements the interface for the I<<<<<< match >>>>>> callback at C-level and for the selection of the callback group from the +callbacks defined at the Perl-level. + + +=item _callback_open + +Forwards the I<<<<<< open >>>>>> callback from libxml2 to the corresponding callback function at the Perl-level. + + +=item _callback_read + +Forwards the read request to the corresponding callback function at the +Perl-level and returns the result to libxml2. + + +=item _callback_close + +Forwards the I<<<<<< close >>>>>> callback from libxml2 to the corresponding callback function at the +Perl-level.. + + + +=back + + +=head2 Class methods + +=over 4 + +=item new() + +A simple constructor. + + +=item register_callbacks( [ $match_cb, $open_cb, $read_cb, $close_cb ]) + +The four callbacks I<<<<<< have >>>>>> to be given as array reference in the above order I<<<<<< match >>>>>>, I<<<<<< open >>>>>>, I<<<<<< read >>>>>>, I<<<<<< close >>>>>>! + + +=item unregister_callbacks( [ $match_cb, $open_cb, $read_cb, $close_cb ]) + +With no arguments given, C<<<<<< unregister_callbacks() >>>>>> will delete the last registered callback group from the stack. If four +callbacks are passed as array reference, the callback group to unregister will +be identified by the I<<<<<< match >>>>>> callback and deleted from the callback stack. Note that if several identical I<<<<<< match >>>>>> callbacks are defined in different callback groups, ALL of them will be deleted +from the stack. + + +=item init_callbacks() + +Initializes the callback system before a parsing process. + + +=item cleanup_callbacks() + +Resets global variables and the libxml2 callback stack. + + +=item lib_init_callbacks() + +Used internally for callback registration at C-level. + + +=item lib_cleanup_callbacks() + +Used internally for callback resetting at the C-level. + + + +=back + + + + +=head1 EXAMPLE CALLBACKS + +The following example is a purely fictitious example that uses a +MyScheme::Handler object that responds to methods similar to an IO::Handle. + + + + # Define the four callback functions + sub match_uri { + my $uri = shift; + return $uri =~ /^myscheme:/; # trigger our callback group at a 'myscheme' URIs + } + + sub open_uri { + my $uri = shift; + my $handler = MyScheme::Handler->new($uri); + return $handler; + } + + # The returned $buffer will be parsed by the libxml2 parser + sub read_uri { + my $handler = shift; + my $length = shift; + my $buffer; + read($handler, $buffer, $length); + return $buffer; # $buffer will be an empty string '' if read() is done + } + + # Close the handle associated with the resource. + sub close_uri { + my $handler = shift; + close($handler); + } + + # Register them with a instance of XML::LibXML::InputCallback + my $input_callbacks = XML::LibXML::InputCallback->new(); + $input_callbacks->register_callbacks([ \&match_uri, \&open_uri, + \&read_uri, \&close_uri ] ); + + # Register the callback group at a parser instance + $parser->input_callbacks( $input_callbacks ); + + # $some_xml_file will be parsed using our callbacks + $parser->parse_file( $some_xml_file ); + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Literal.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/Literal.pm new file mode 100755 index 00000000000..d3b34ec2f81 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Literal.pm @@ -0,0 +1,109 @@ +# $Id: Literal.pm 785 2009-07-16 14:17:46Z pajas $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::Literal; +use XML::LibXML::Boolean; +use XML::LibXML::Number; +use strict; + +use vars qw ($VERSION); +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use overload + '""' => \&value, + 'cmp' => \&cmp; + +sub new { + my $class = shift; + my ($string) = @_; + +# $string =~ s/"/"/g; +# $string =~ s/'/'/g; + + bless \$string, $class; +} + +sub as_string { + my $self = shift; + my $string = $$self; + $string =~ s/'/'/g; + return "'$string'"; +} + +sub as_xml { + my $self = shift; + my $string = $$self; + return "<Literal>$string</Literal>\n"; +} + +sub value { + my $self = shift; + $$self; +} + +sub cmp { + my $self = shift; + my ($cmp, $swap) = @_; + if ($swap) { + return $cmp cmp $$self; + } + return $$self cmp $cmp; +} + +sub evaluate { + my $self = shift; + $self; +} + +sub to_boolean { + my $self = shift; + return (length($$self) > 0) ? XML::LibXML::Boolean->True : XML::LibXML::Boolean->False; +} + +sub to_number { return XML::LibXML::Number->new($_[0]->value); } +sub to_literal { return $_[0]; } + +sub string_value { return $_[0]->value; } + +1; +__END__ + +=head1 NAME + +XML::LibXML::Literal - Simple string values. + +=head1 DESCRIPTION + +In XPath terms a Literal is what we know as a string. + +=head1 API + +=head2 new($string) + +Create a new Literal object with the value in $string. Note that " and +' will be converted to " and ' respectively. That is not part of the XPath +specification, but I consider it useful. Note though that you have to go +to extraordinary lengths in an XML template file (be it XSLT or whatever) to +make use of this: + + <xsl:value-of select=""I'm feeling &quot;sad&quot;""/> + +Which produces a Literal of: + + I'm feeling "sad" + +=head2 value() + +Also overloaded as stringification, simply returns the literal string value. + +=head2 cmp($literal) + +Returns the equivalent of perl's cmp operator against the given $literal. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Namespace.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Namespace.pod new file mode 100755 index 00000000000..f8fca958d99 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Namespace.pod @@ -0,0 +1,143 @@ +=head1 NAME + +XML::LibXML::Namespace - XML::LibXML Namespace Implementation + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to Namespace nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + my $ns = XML::LibXML::Namespace->new($nsURI); + print $ns->nodeName(); + print $ns->name(); + $localname = $ns->getLocalName(); + print $ns->getData(); + print $ns->getValue(); + print $ns->value(); + $known_uri = $ns->getNamespaceURI(); + $known_prefix = $ns->getPrefix(); + +=head1 DESCRIPTION + +Namespace nodes are returned by both $element->findnodes('namespace::foo') or +by $node->getNamespaces(). + +The namespace node API is not part of any current DOM API, and so it is quite +minimal. It should be noted that namespace nodes are I<<<<<< not >>>>>> a sub class of L<<<<<< XML::LibXML::Node >>>>>>, however Namespace nodes act a lot like attribute nodes, and similarly named +methods will return what you would expect if you treated the namespace node as +an attribute. Note that in order to fix several inconsistencies between the API +and the documentation, the behavior of some functions have been changed in +1.64. + + +=head1 METHODS + +=over 4 + +=item new + + my $ns = XML::LibXML::Namespace->new($nsURI); + +Creates a new Namespace node. Note that this is not a 'node' as an attribute or +an element node. Therefore you can't do call all L<<<<<< XML::LibXML::Node >>>>>> Functions. All functions available for this node are listed below. + +Optionally you can pass the prefix to the namespace constructor. If this second +parameter is omitted you will create a so called default namespace. Note, the +newly created namespace is not bound to any document or node, therefore you +should not expect it to be available in an existing document. + + +=item declaredURI + +Returns the URI for this namespace. + + +=item declaredPrefix + +Returns the prefix for this namespace. + + +=item nodeName + + print $ns->nodeName(); + +Returns "xmlns:prefix", where prefix is the prefix for this namespace. + + +=item name + + print $ns->name(); + +Alias for nodeName() + + +=item getLocalName + + $localname = $ns->getLocalName(); + +Returns the local name of this node as if it were an attribute, that is, the +prefix associated with the namespace. + + +=item getData + + print $ns->getData(); + +Returns the URI of the namespace, i.e. the value of this node as if it were an +attribute. + + +=item getValue + + print $ns->getValue(); + +Alias for getData() + + +=item value + + print $ns->value(); + +Alias for getData() + + +=item getNamespaceURI + + $known_uri = $ns->getNamespaceURI(); + +Returns the string "http://www.w3.org/2000/xmlns/" + + +=item getPrefix + + $known_prefix = $ns->getPrefix(); + +Returns the string "xmlns" + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Node.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Node.pod new file mode 100755 index 00000000000..5af4f0fe22b --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Node.pod @@ -0,0 +1,752 @@ +=head1 NAME + +XML::LibXML::Node - Abstract Base Class of XML::LibXML Nodes + +=head1 SYNOPSIS + + + + use XML::LibXML; + + $name = $node->nodeName; + $node->setNodeName( $newName ); + $bool = $node->isSameNode( $other_node ); + $bool = $node->isEqual( $other_node ); + $content = $node->nodeValue; + $content = $node->textContent; + $type = $node->nodeType; + $node->unbindNode(); + $childnode = $node->removeChild( $childnode ); + $oldnode = $node->replaceChild( $newNode, $oldNode ); + $node->replaceNode($newNode); + $childnode = $node->appendChild( $childnode ); + $childnode = $node->addChild( $chilnode ); + $node = $parent->addNewChild( $nsURI, $name ); + $node->addSibling($newNode); + $newnode =$node->cloneNode( $deep ); + $parentnode = $node->parentNode; + $nextnode = $node->nextSibling(); + $nextnode = $node->nextNonBlankSibling(); + $prevnode = $node->previousSibling(); + $prevnode = $node->previousNonBlankSibling(); + $boolean = $node->hasChildNodes(); + $childnode = $node->firstChild; + $childnode = $node->lastChild; + $documentnode = $node->ownerDocument; + $node = $node->getOwner; + $node->setOwnerDocument( $doc ); + $node->insertBefore( $newNode, $refNode ); + $node->insertAfter( $newNode, $refNode ); + @nodes = $node->findnodes( $xpath_expression ); + $result = $node->find( $xpath ); + print $node->findvalue( $xpath ); + $bool = $node->exists( $xpath_expression ); + @childnodes = $node->childNodes(); + @childnodes = $node->nonBlankChildNodes(); + $xmlstring = $node->toString($format,$docencoding); + $c14nstring = $node->toStringC14N(); + $c14nstring = $node->toStringC14N($with_comments, $xpath_expression , $xpath_context); + $ec14nstring = $node->toStringEC14N(); + $ec14nstring = $node->toStringEC14N($with_comments, $xpath_expression, $inclusive_prefix_list); + $ec14nstring = $node->toStringEC14N($with_comments, $xpath_expression, $xpath_context, $inclusive_prefix_list); + $str = $doc->serialize($format); + $localname = $node->localname; + $nameprefix = $node->prefix; + $uri = $node->namespaceURI(); + $boolean = $node->hasAttributes(); + @attributelist = $node->attributes(); + $URI = $node->lookupNamespaceURI( $prefix ); + $prefix = $node->lookupNamespacePrefix( $URI ); + $node->normalize; + @nslist = $node->getNamespaces; + $node->removeChildNodes(); + $strURI = $node->baseURI(); + $node->setBaseURI($strURI); + $node->nodePath(); + $lineno = $node->line_number(); + +=head1 DESCRIPTION + +XML::LibXML::Node defines functions that are common to all Node Types. A +LibXML::Node should never be created standalone, but as an instance of a high +level class such as LibXML::Element or LibXML::Text. The class itself should +provide only common functionality. In XML::LibXML each node is part either of a +document or a document-fragment. Because of this there is no node without a +parent. This may causes confusion with "unbound" nodes. + + +=head1 METHODS + +Many functions listed here are extensively documented in the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>). Please refer to the specification for extensive documentation. + +=over 4 + +=item nodeName + + $name = $node->nodeName; + +Returns the node's name. This function is aware of namespaces and returns the +full name of the current node (C<<<<<< prefix:localname >>>>>>). + +Since 1.62 this function also returns the correct DOM names for node types with +constant names, namely: #text, #cdata-section, #comment, #document, +#document-fragment. + + +=item setNodeName + + $node->setNodeName( $newName ); + +In very limited situations, it is useful to change a nodes name. In the DOM +specification this should throw an error. This Function is aware of namespaces. + + +=item isSameNode + + $bool = $node->isSameNode( $other_node ); + +returns TRUE (1) if the given nodes refer to the same node structure, otherwise +FALSE (0) is returned. + + +=item isEqual + + $bool = $node->isEqual( $other_node ); + +deprecated version of isSameNode(). + +I<<<<<< NOTE >>>>>> isEqual will change behaviour to follow the DOM specification + + +=item nodeValue + + $content = $node->nodeValue; + +If the node has any content (such as stored in a C<<<<<< text node >>>>>>) it can get requested through this function. + +I<<<<<< NOTE: >>>>>> Element Nodes have no content per definition. To get the text value of an +Element use textContent() instead! + + +=item textContent + + $content = $node->textContent; + +this function returns the content of all text nodes in the descendants of the +given node as specified in DOM. + + +=item nodeType + + $type = $node->nodeType; + +Return a numeric value representing the node type of this node. The module +XML::LibXML by default exports constants for the node types (see the EXPORT +section in the L<<<<<< XML::LibXML >>>>>> manual page). + + +=item unbindNode + + $node->unbindNode(); + +Unbinds the Node from its siblings and Parent, but not from the Document it +belongs to. If the node is not inserted into the DOM afterwards it will be lost +after the program terminated. From a low level view, the unbound node is +stripped from the context it is and inserted into a (hidden) document-fragment. + + +=item removeChild + + $childnode = $node->removeChild( $childnode ); + +This will unbind the Child Node from its parent C<<<<<< $node >>>>>>. The function returns the unbound node. If C<<<<<< oldNode >>>>>> is not a child of the given Node the function will fail. + + +=item replaceChild + + $oldnode = $node->replaceChild( $newNode, $oldNode ); + +Replaces the C<<<<<< $oldNode >>>>>> with the C<<<<<< $newNode >>>>>>. The C<<<<<< $oldNode >>>>>> will be unbound from the Node. This function differs from the DOM L2 +specification, in the case, if the new node is not part of the document, the +node will be imported first. + + +=item replaceNode + + $node->replaceNode($newNode); + +This function is very similar to replaceChild(), but it replaces the node +itself rather than a childnode. This is useful if a node found by any XPath +function, should be replaced. + + +=item appendChild + + $childnode = $node->appendChild( $childnode ); + +The function will add the C<<<<<< $childnode >>>>>> to the end of C<<<<<< $node >>>>>>'s children. The function should fail, if the new childnode is already a child +of C<<<<<< $node >>>>>>. This function differs from the DOM L2 specification, in the case, if the new +node is not part of the document, the node will be imported first. + + +=item addChild + + $childnode = $node->addChild( $chilnode ); + +As an alternative to appendChild() one can use the addChild() function. This +function is a bit faster, because it avoids all DOM conformity checks. +Therefore this function is quite useful if one builds XML documents in memory +where the order and ownership (C<<<<<< ownerDocument >>>>>>) is assured. + +addChild() uses libxml2's own xmlAddChild() function. Thus it has to be used +with extra care: If a text node is added to a node and the node itself or its +last childnode is as well a text node, the node to add will be merged with the +one already available. The current node will be removed from memory after this +action. Because perl is not aware of this action, the perl instance is still +available. XML::LibXML will catch the loss of a node and refuse to run any +function called on that node. + + + + my $t1 = $doc->createTextNode( "foo" ); + my $t2 = $doc->createTextNode( "bar" ); + $t1->addChild( $t2 ); # is OK + my $val = $t2->nodeValue(); # will fail, script dies + +Also addChild() will not check if the added node belongs to the same document +as the node it will be added to. This could lead to inconsistent documents and +in more worse cases even to memory violations, if one does not keep track of +this issue. + +Although this sounds like a lot of trouble, addChild() is useful if a document +is built from a stream, such as happens sometimes in SAX handlers or filters. + +If you are not sure about the source of your nodes, you better stay with +appendChild(), because this function is more user friendly in the sense of +being more error tolerant. + + +=item addNewChild + + $node = $parent->addNewChild( $nsURI, $name ); + +Similar to C<<<<<< addChild() >>>>>>, this function uses low level libxml2 functionality to provide faster +interface for DOM building. I<<<<<< addNewChild() >>>>>> uses C<<<<<< xmlNewChild() >>>>>> to create a new node on a given parent element. + +addNewChild() has two parameters $nsURI and $name, where $nsURI is an +(optional) namespace URI. $name is the fully qualified element name; +addNewChild() will determine the correct prefix if necessary. + +The function returns the newly created node. + +This function is very useful for DOM building, where a created node can be +directly associated with its parent. I<<<<<< NOTE >>>>>> this function is not part of the DOM specification and its use will limit your +code to XML::LibXML. + + +=item addSibling + + $node->addSibling($newNode); + +addSibling() allows adding an additional node to the end of a nodelist, defined +by the given node. + + +=item cloneNode + + $newnode =$node->cloneNode( $deep ); + +I<<<<<< cloneNode >>>>>> creates a copy of C<<<<<< $node >>>>>>. When $deep is set to 1 (true) the function will copy all childnodes as well. +If $deep is 0 only the current node will be copied. Note that in case of +element, attributes are copied even if $deep is 0. + +Note that the behavior of this function for $deep=0 has changed in 1.62 in +order to be consistent with the DOM spec (in older versions attributes and +namespace information was not copied for elements). + + +=item parentNode + + $parentnode = $node->parentNode; + +Returns simply the Parent Node of the current node. + + +=item nextSibling + + $nextnode = $node->nextSibling(); + +Returns the next sibling if any . + + +=item nextNonBlankSibling + + $nextnode = $node->nextNonBlankSibling(); + +Returns the next non-blank sibling if any (a node is blank if it is a Text or +CDATA node consisting of whitespace only). This method is not defined by DOM. + + +=item previousSibling + + $prevnode = $node->previousSibling(); + +Analogous to I<<<<<< getNextSibling >>>>>> the function returns the previous sibling if any. + + +=item previousNonBlankSibling + + $prevnode = $node->previousNonBlankSibling(); + +Returns the previous non-blank sibling if any (a node is blank if it is a Text +or CDATA node consisting of whitespace only). This method is not defined by +DOM. + + +=item hasChildNodes + + $boolean = $node->hasChildNodes(); + +If the current node has Childnodes this function returns TRUE (1), otherwise it +returns FALSE (0, not undef). + + +=item firstChild + + $childnode = $node->firstChild; + +If a node has childnodes this function will return the first node in the +childlist. + + +=item lastChild + + $childnode = $node->lastChild; + +If the C<<<<<< $node >>>>>> has childnodes this function returns the last child node. + + +=item ownerDocument + + $documentnode = $node->ownerDocument; + +Through this function it is always possible to access the document the current +node is bound to. + + +=item getOwner + + $node = $node->getOwner; + +This function returns the node the current node is associated with. In most +cases this will be a document node or a document fragment node. + + +=item setOwnerDocument + + $node->setOwnerDocument( $doc ); + +This function binds a node to another DOM. This method unbinds the node first, +if it is already bound to another document. + +This function is the opposite calling of L<<<<<< XML::LibXML::Document >>>>>>'s adoptNode() function. Because of this it has the same limitations with +Entity References as adoptNode(). + + +=item insertBefore + + $node->insertBefore( $newNode, $refNode ); + +The method inserts C<<<<<< $newNode >>>>>> before C<<<<<< $refNode >>>>>>. If C<<<<<< $refNode >>>>>> is undefined, the newNode will be set as the new last child of the parent node. +This function differs from the DOM L2 specification, in the case, if the new +node is not part of the document, the node will be imported first, +automatically. + +$refNode has to be passed to the function even if it is undefined: + + + + $node->insertBefore( $newNode, undef ); # the same as $node->appendChild( $newNode ); + $node->insertBefore( $newNode ); # wrong + +Note, that the reference node has to be a direct child of the node the function +is called on. Also, $newChild is not allowed to be an ancestor of the new +parent node. + + +=item insertAfter + + $node->insertAfter( $newNode, $refNode ); + +The method inserts C<<<<<< $newNode >>>>>> after C<<<<<< $refNode >>>>>>. If C<<<<<< $refNode >>>>>> is undefined, the newNode will be set as the new last child of the parent node. + +Note, that $refNode has to be passed explicitly even if it is undef. + + +=item findnodes + + @nodes = $node->findnodes( $xpath_expression ); + +I<<<<<< findnodes >>>>>> evaluates the xpath expression (XPath 1.0) on the current node and returns the +resulting node set as an array. In scalar context returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. + +The xpath expression can be passed either as a string or or as a L<<<<<< XML::LibXML::XPathExpression >>>>>> object. + +I<<<<<< NOTE ON NAMESPACES AND XPATH >>>>>>: + +A common mistake about XPath is to assume that node tests consisting of an +element name with no prefix match elements in the default namespace. This +assumption is wrong - by XPath specification, such node tests can only match +elements that are in no (i.e. null) namespace. + +So, for example, one cannot match the root element of an XHTML document with C<<<<<< $node->find('/html') >>>>>> since C<<<<<< '/html' >>>>>> would only match if the root element C<<<<<< <html> >>>>>> had no namespace, but all XHTML elements belong to the namespace +http://www.w3.org/1999/xhtml. (Note that C<<<<<< xmlns="..." >>>>>> namespace declarations can also be specified in a DTD, which makes the +situation even worse, since the XML document looks as if there was no default +namespace). + +There are several possible ways to deal with namespaces in XPath: + + +=over 4 + +=item * + +The recommended way is to use the L<<<<<< XML::LibXML::XPathContext >>>>>> module to define an explicit context for XPath evaluation, in which a document +independent prefix-to-namespace mapping can be defined. For example: + + + + my $xpc = XML::LibXML::XPathContext->new; + $xpc->registerNs('x', 'http://www.w3.org/1999/xhtml'); + $xpc->find('/x:html',$node); + + + +=item * + +Another possibility is to use prefixes declared in the queried document (if +known). If the document declares a prefix for the namespace in question (and +the context node is in the scope of the declaration), C<<<<<< XML::LibXML >>>>>> allows you to use the prefix in the XPath expression, e.g.: + + + + $node->find('/x:html'); + + + +=back + +See also XML::LibXML::XPathContext->findnodes. + + +=item find + + $result = $node->find( $xpath ); + +I<<<<<< find >>>>>> evaluates the XPath 1.0 expression using the current node as the context of the +expression, and returns the result depending on what type of result the XPath +expression had. For example, the XPath "1 * 3 + 52" results in a L<<<<<< XML::LibXML::Number >>>>>> object being returned. Other expressions might return a L<<<<<< XML::LibXML::Boolean >>>>>> object, or a L<<<<<< XML::LibXML::Literal >>>>>> object (a string). Each of those objects uses Perl's overload feature to "do +the right thing" in different contexts. + +The xpath expression can be passed either as a string or or as a L<<<<<< XML::LibXML::XPathExpression >>>>>> object. + +See also L<<<<<< XML::LibXML::XPathContext >>>>>>->find. + + +=item findvalue + + print $node->findvalue( $xpath ); + +I<<<<<< findvalue >>>>>> is exactly equivalent to: + + + + $node->find( $xpath )->to_literal; + +That is, it returns the literal value of the results. This enables you to +ensure that you get a string back from your search, allowing certain shortcuts. +This could be used as the equivalent of XSLT's <xsl:value-of +select="some_xpath"/>. + +See also L<<<<<< XML::LibXML::XPathContext >>>>>>->findvalue. + +The xpath expression can be passed either as a string or or as a L<<<<<< XML::LibXML::XPathExpression >>>>>> object. + + +=item exists + + $bool = $node->exists( $xpath_expression ); + +This method behaves like I<<<<<< findnodes >>>>>>, except that it only returns a boolean value (1 if the expression matches a +node, 0 otherwise) and may be faster than I<<<<<< findnodes >>>>>>, because the XPath evaluation may stop early on the first match (this is true +for libxml2 >= 2.6.27). + +For XPath expressions that do not return node-set, the method returns true if +the returned value is a non-zero number or a non-empty string. + + +=item childNodes + + @childnodes = $node->childNodes(); + +I<<<<<< childNodes >>>>>> implements a more intuitive interface to the childnodes of the current node. It +enables you to pass all children directly to a C<<<<<< map >>>>>> or C<<<<<< grep >>>>>>. If this function is called in scalar context, a L<<<<<< XML::LibXML::NodeList >>>>>> object will be returned. + + +=item nonBlankChildNodes + + @childnodes = $node->nonBlankChildNodes(); + +This is like I<<<<<< childNodes >>>>>>, but returns only non-blank nodes (where a node is blank if it is a Text or +CDATA node consisting of whitespace only). This method is not defined by DOM. + + +=item toString + + $xmlstring = $node->toString($format,$docencoding); + +This method is similar to the method C<<<<<< toString >>>>>> of a L<<<<<< XML::LibXML::Document >>>>>> but for a single node. It returns a string consisting of XML serialization of +the given node and all its descendants. Unlike C<<<<<< XML::LibXML::Document::toString >>>>>>, in this case the resulting string is by default a character string (UTF-8 +encoded with UTF8 flag on). An optional flag $format controls indentation, as +in C<<<<<< XML::LibXML::Document::toString >>>>>>. If the second optional $docencoding flag is true, the result will be a byte +string in the document encoding (see C<<<<<< XML::LibXML::Document::actualEncoding >>>>>>). + + +=item toStringC14N + + $c14nstring = $node->toStringC14N(); + $c14nstring = $node->toStringC14N($with_comments, $xpath_expression , $xpath_context); + +The function is similar to toString(). Instead of simply serializing the +document tree, it transforms it as it is specified in the XML-C14N +Specification (see L<<<<<< http://www.w3.org/TR/xml-c14n >>>>>>). Such transformation is known as canonization. + +If $with_comments is 0 or not defined, the result-document will not contain any +comments that exist in the original document. To include comments into the +canonized document, $with_comments has to be set to 1. + +The parameter $xpath_expression defines the nodeset of nodes that should be +visible in the resulting document. This can be used to filter out some nodes. +One has to note, that only the nodes that are part of the nodeset, will be +included into the result-document. Their child-nodes will not exist in the +resulting document, unless they are part of the nodeset defined by the xpath +expression. + +If $xpath_expression is omitted or empty, toStringC14N() will include all nodes +in the given sub-tree, using the following XPath expressions: with comments + + (. | .//node() | .//@* | .//namespace::*) + +and without comments + + (. | .//node() | .//@* | .//namespace::*)[not(self::comment())] + + + +An optional parameter $xpath_context can be used to pass an L<<<<<< XML::LibXML::XPathContext >>>>>> object defining the context for evaluation of $xpath_expression. This is useful +for mapping namespace prefixes used in the XPath expression to namespace URIs. +Note, however, that $node will be used as the context node for the evaluation, +not the context node of $xpath_context! + + +=item toStringEC14N + + $ec14nstring = $node->toStringEC14N(); + $ec14nstring = $node->toStringEC14N($with_comments, $xpath_expression, $inclusive_prefix_list); + $ec14nstring = $node->toStringEC14N($with_comments, $xpath_expression, $xpath_context, $inclusive_prefix_list); + +The function is similar to toStringC14N() but follows the XML-EXC-C14N +Specification (see L<<<<<< http://www.w3.org/TR/xml-exc-c14n >>>>>>) for exclusive canonization of XML. + +The arguments $with_comments, $xpath_expression, $xpath_context are as in +toStringC14N(). An ARRAY reference can be passed as the last argument +$inclusive_prefix_list, listing namespace prefixes that are to be handled in +the manner described by the Canonical XML Recommendation (i.e. preserved in the +output even if the namespace is not used). C.f. the spec for details. + + +=item serialize + + $str = $doc->serialize($format); + +An alias for toString(). This function was name added to be more consistent +with libxml2. + + +=item serialize_c14n + +An alias for toStringC14N(). + + +=item serialize_exc_c14n + +An alias for toStringEC14N(). + + +=item localname + + $localname = $node->localname; + +Returns the local name of a tag. This is the part behind the colon. + + +=item prefix + + $nameprefix = $node->prefix; + +Returns the prefix of a tag. This is the part before the colon. + + +=item namespaceURI + + $uri = $node->namespaceURI(); + +returns the URI of the current namespace. + + +=item hasAttributes + + $boolean = $node->hasAttributes(); + +returns 1 (TRUE) if the current node has any attributes set, otherwise 0 +(FALSE) is returned. + + +=item attributes + + @attributelist = $node->attributes(); + +This function returns all attributes and namespace declarations assigned to the +given node. + +Because XML::LibXML does not implement namespace declarations and attributes +the same way, it is required to test what kind of node is handled while +accessing the functions result. + +If this function is called in array context the attribute nodes are returned as +an array. In scalar context the function will return a L<<<<<< XML::LibXML::NamedNodeMap >>>>>> object. + + +=item lookupNamespaceURI + + $URI = $node->lookupNamespaceURI( $prefix ); + +Find a namespace URI by its prefix starting at the current node. + + +=item lookupNamespacePrefix + + $prefix = $node->lookupNamespacePrefix( $URI ); + +Find a namespace prefix by its URI starting at the current node. + +I<<<<<< NOTE >>>>>> Only the namespace URIs are meant to be unique. The prefix is only document +related. Also the document might have more than a single prefix defined for a +namespace. + + +=item normalize + + $node->normalize; + +This function normalizes adjacent text nodes. This function is not as strict as +libxml2's xmlTextMerge() function, since it will not free a node that is still +referenced by the perl layer. + + +=item getNamespaces + + @nslist = $node->getNamespaces; + +If a node has any namespaces defined, this function will return these +namespaces. Note, that this will not return all namespaces that are in scope, +but only the ones declared explicitly for that node. + +Although getNamespaces is available for all nodes, it only makes sense if used +with element nodes. + + +=item removeChildNodes + + $node->removeChildNodes(); + +This function is not specified for any DOM level: It removes all childnodes +from a node in a single step. Other than the libxml2 function itself +(xmlFreeNodeList), this function will not immediately remove the nodes from the +memory. This saves one from getting memory violations, if there are nodes still +referred to from the Perl level. + + +=item baseURI () + + $strURI = $node->baseURI(); + +Searches for the base URL of the node. The method should work on both XML and +HTML documents even if base mechanisms for these are completely different. It +returns the base as defined in RFC 2396 sections "5.1.1. Base URI within +Document Content" and "5.1.2. Base URI from the Encapsulating Entity". However +it does not return the document base (5.1.3), use method C<<<<<< URI >>>>>> of C<<<<<< XML::LibXML::Document >>>>>> for this. + + +=item setBaseURI ($strURI) + + $node->setBaseURI($strURI); + +This method only does something useful for an element node in a XML document. +It sets the xml:base attribute on the node to $strURI, which effectively sets +the base URI of the node to the same value. + +Note: For HTML documents this behaves as if the document was XML which may not +be desired, since it does not effectively set the base URI of the node. See RFC +2396 appendix D for an example of how base URI can be specified in HTML. + + +=item nodePath + + $node->nodePath(); + +This function is not specified for any DOM level: It returns a canonical +structure based XPath for a given node. + + +=item line_number + + $lineno = $node->line_number(); + +This function returns the line number where the tag was found during parsing. +If a node is added to the document the line number is 0. Problems may occur, if +a node from one document is passed to another one. + +IMPORTANT: Due to limitations in the libxml2 library line numbers greater than +65535 will be returned as 65535. Please see L<<<<<< http://bugzilla.gnome.org/show_bug.cgi?id=325533 >>>>>> for more details. + +Note: line_number() is special to XML::LibXML and not part of the DOM +specification. + +If the line_numbers flag of the parser was not activated before parsing, +line_number() will always return 0. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/NodeList.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/NodeList.pm new file mode 100755 index 00000000000..336740803a2 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/NodeList.pm @@ -0,0 +1,198 @@ +# $Id: NodeList.pm 785 2009-07-16 14:17:46Z pajas $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::NodeList; +use strict; +use XML::LibXML::Boolean; +use XML::LibXML::Literal; +use XML::LibXML::Number; + +use vars qw ($VERSION); +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use overload + '""' => \&to_literal, + 'bool' => \&to_boolean, + ; + +sub new { + my $class = shift; + bless [@_], $class; +} + +sub new_from_ref { + my ($class,$array_ref,$reuse) = @_; + return bless $reuse ? $array_ref : [@$array_ref], $class; +} + +sub pop { + my $self = CORE::shift; + CORE::pop @$self; +} + +sub push { + my $self = CORE::shift; + CORE::push @$self, @_; +} + +sub append { + my $self = CORE::shift; + my ($nodelist) = @_; + CORE::push @$self, $nodelist->get_nodelist; +} + +sub shift { + my $self = CORE::shift; + CORE::shift @$self; +} + +sub unshift { + my $self = CORE::shift; + CORE::unshift @$self, @_; +} + +sub prepend { + my $self = CORE::shift; + my ($nodelist) = @_; + CORE::unshift @$self, $nodelist->get_nodelist; +} + +sub size { + my $self = CORE::shift; + scalar @$self; +} + +sub get_node { + # uses array index starting at 1, not 0 + # this is mainly because of XPath. + my $self = CORE::shift; + my ($pos) = @_; + $self->[$pos - 1]; +} + +*item = \&get_node; + +sub get_nodelist { + my $self = CORE::shift; + @$self; +} + +sub to_boolean { + my $self = CORE::shift; + return (@$self > 0) ? XML::LibXML::Boolean->True : XML::LibXML::Boolean->False; +} + +# string-value of a nodelist is the string-value of the first node +sub string_value { + my $self = CORE::shift; + return '' unless @$self; + return $self->[0]->string_value; +} + +sub to_literal { + my $self = CORE::shift; + return XML::LibXML::Literal->new( + join('', grep {defined $_} map { $_->string_value } @$self) + ); +} + +sub to_number { + my $self = CORE::shift; + return XML::LibXML::Number->new( + $self->to_literal + ); +} + +sub iterator { + warn "this function is obsolete!\nIt was disabled in version 1.54\n"; + return undef; +} + +1; +__END__ + +=head1 NAME + +XML::LibXML::NodeList - a list of XML document nodes + +=head1 DESCRIPTION + +An XML::LibXML::NodeList object contains an ordered list of nodes, as +detailed by the W3C DOM documentation of Node Lists. + +=head1 SYNOPSIS + + my $results = $dom->findnodes('//somepath'); + foreach my $context ($results->get_nodelist) { + my $newresults = $context->findnodes('./other/element'); + ... + } + +=head1 API + +=head2 new() + +You will almost never have to create a new NodeSet object, as it is all +done for you by XPath. + +=head2 get_nodelist() + +Returns a list of nodes, the contents of the node list, as a perl list. + +=head2 string_value() + +Returns the string-value of the first node in the list. +See the XPath specification for what "string-value" means. + +=head2 to_literal() + +Returns the concatenation of all the string-values of all +the nodes in the list. + +=head2 get_node($pos) + +Returns the node at $pos. The node position in XPath is based at 1, not 0. + +=head2 size() + +Returns the number of nodes in the NodeSet. + +=head2 pop() + +Equivalent to perl's pop function. + +=head2 push(@nodes) + +Equivalent to perl's push function. + +=head2 append($nodelist) + +Given a nodelist, appends the list of nodes in $nodelist to the end of the +current list. + +=head2 shift() + +Equivalent to perl's shift function. + +=head2 unshift(@nodes) + +Equivalent to perl's unshift function. + +=head2 prepend($nodeset) + +Given a nodelist, prepends the list of nodes in $nodelist to the front of +the current list. + +=head2 iterator() + +Will return a new nodelist iterator for the current nodelist. A +nodelist iterator is usefull if more complex nodelist processing is +needed. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Number.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/Number.pm new file mode 100755 index 00000000000..5538d33e70a --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Number.pm @@ -0,0 +1,97 @@ +# $Id: Number.pm 785 2009-07-16 14:17:46Z pajas $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::Number; +use XML::LibXML::Boolean; +use XML::LibXML::Literal; +use strict; + +use vars qw ($VERSION); +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use overload + '""' => \&value, + '0+' => \&value, + '<=>' => \&cmp; + +sub new { + my $class = shift; + my $number = shift; + if ($number !~ /^\s*(-\s*)?(\d+(\.\d*)?|\.\d+)\s*$/) { + $number = undef; + } + else { + $number =~ s/\s+//g; + } + bless \$number, $class; +} + +sub as_string { + my $self = shift; + defined $$self ? $$self : 'NaN'; +} + +sub as_xml { + my $self = shift; + return "<Number>" . (defined($$self) ? $$self : 'NaN') . "</Number>\n"; +} + +sub value { + my $self = shift; + $$self; +} + +sub cmp { + my $self = shift; + my ($other, $swap) = @_; + if ($swap) { + return $other <=> $$self; + } + return $$self <=> $other; +} + +sub evaluate { + my $self = shift; + $self; +} + +sub to_boolean { + my $self = shift; + return $$self ? XML::LibXML::Boolean->True : XML::LibXML::Boolean->False; +} + +sub to_literal { XML::LibXML::Literal->new($_[0]->as_string); } +sub to_number { $_[0]; } + +sub string_value { return $_[0]->value } + +1; +__END__ + +=head1 NAME + +XML::LibXML::Number - Simple numeric values. + +=head1 DESCRIPTION + +This class holds simple numeric values. It doesn't support -0, +/- Infinity, +or NaN, as the XPath spec says it should, but I'm not hurting anyone I don't think. + +=head1 API + +=head2 new($num) + +Creates a new XML::LibXML::Number object, with the value in $num. Does some +rudimentary numeric checking on $num to ensure it actually is a number. + +=head2 value() + +Also as overloaded stringification. Returns the numeric value held. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/PI.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/PI.pod new file mode 100755 index 00000000000..1c08a8ab3b1 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/PI.pod @@ -0,0 +1,87 @@ +=head1 NAME + +XML::LibXML::PI - XML::LibXML Processing Instructions + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to Processing Instruction nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + $pinode->setData( $data_string ); + $pinode->setData( name=>string_value [...] ); + +=head1 DESCRIPTION + +Processing instructions are implemented with XML::LibXML with read and write +access. The PI data is the PI without the PI target (as specified in XML 1.0 +[17]) as a string. This string can be accessed with getData as implemented in L<<<<<< XML::LibXML::Node >>>>>>. + +The write access is aware about the fact, that many processing instructions +have attribute like data. Therefore setData() provides besides the DOM spec +conform Interface to pass a set of named parameter. So the code segment + + + + my $pi = $dom->createProcessingInstruction("abc"); + $pi->setData(foo=>'bar', foobar=>'foobar'); + $dom->appendChild( $pi ); + +will result the following PI in the DOM: + + + + <?abc foo="bar" foobar="foobar"?> + +Which is how it is specified in the DOM specification. This three step +interface creates temporary a node in perl space. This can be avoided while +using the insertProcessingInstruction() method. Instead of the three calls +described above, the call + + + + $dom->insertProcessingInstruction("abc",'foo="bar" foobar="foobar"'); + +will have the same result as above. + +L<<<<<< XML::LibXML::PI >>>>>>'s implementation of setData() documented below differs a bit from the the +standard version as available in L<<<<<< XML::LibXML::Node >>>>>>: + +=over 4 + +=item setData + + $pinode->setData( $data_string ); + $pinode->setData( name=>string_value [...] ); + +This method allows to change the content data of a PI. Additionally to the +interface specified for DOM Level2, the method provides a named parameter +interface to set the data. This parameter list is converted into a string +before it is appended to the PI. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Parser.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Parser.pod new file mode 100755 index 00000000000..1bf6b48d527 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Parser.pod @@ -0,0 +1,966 @@ +=head1 NAME + +XML::LibXML::Parser - Parsing XML Data with XML::LibXML + +=head1 SYNOPSIS + + + + use XML::LibXML 1.70; + + # Parser constructor + + $parser = XML::LibXML->new(); + $parser = XML::LibXML->new(option=>value, ...); + $parser = XML::LibXML->new({option=>value, ...}); + + # Parsing XML + + $dom = XML::LibXML->load_xml( + location => $file_or_url + # parser options ... + ); + $dom = XML::LibXML->load_xml( + string => $xml_string + # parser options ... + ); + $dom = XML::LibXML->load_xml({ + IO => $perl_file_handle + # parser options ... + ); + $dom = $parser->load_xml(...); + + # Parsing HTML + + $dom = XML::LibXML->load_html(...); + $dom = $parser->load_html(...); + + # Parsing well-balanced XML chunks + + $fragment = $parser->parse_balanced_chunk( $wbxmlstring, $encoding ); + + # Processing XInclude + + $parser->process_xincludes( $doc ); + $parser->processXIncludes( $doc ); + + # Old-style parser interfaces + + $doc = $parser->parse_file( $xmlfilename ); + $doc = $parser->parse_fh( $io_fh ); + $doc = $parser->parse_string( $xmlstring); + $doc = $parser->parse_html_file( $htmlfile, \%opts ); + $doc = $parser->parse_html_fh( $io_fh, \%opts ); + $doc = $parser->parse_html_string( $htmlstring, \%opts ); + + # Push parser + + $parser->parse_chunk($string, $terminate); + $parser->init_push(); + $parser->push(@data); + $doc = $parser->finish_push( $recover ); + + # Set/query parser options + + $parser->option_exists($name); + $parser->get_option($name); + $parser->set_option($name,$value); + $parser->set_options({$name=>$value,...}); + + # XML catalogs + + $parser->load_catalog( $catalog_file ); + +=head1 PARSING + +A XML document is read into a data structure such as a DOM tree by a piece of +software, called a parser. XML::LibXML currently provides four different parser +interfaces: + + +=over 4 + +=item * + +A DOM Pull-Parser + + + +=item * + +A DOM Push-Parser + + + +=item * + +A SAX Parser + + + +=item * + +A DOM based SAX Parser. + + + +=back + + +=head2 Creating a Parser Instance + +XML::LibXML provides an OO interface to the libxml2 parser functions. Thus you +have to create a parser instance before you can parse any XML data. + +=over 4 + +=item new + + + $parser = XML::LibXML->new(); + $parser = XML::LibXML->new(option=>value, ...); + $parser = XML::LibXML->new({option=>value, ...}); + +Create a new XML and HTML parser instance. Each parser instance holds default +values for various parser options. Optionally, one can pass a hash reference or +a list of option => value pairs to set a different default set of options. +Unless specified otherwise, the options C<<<<<< load_ext_dtd >>>>>>, C<<<<<< expand_entities >>>>>>, and C<<<<<< huge >>>>>> are set to 1. See L<<<<<< Parser Options >>>>>> for a list of libxml2 parser's options. + + + +=back + + +=head2 DOM Parser + +One of the common parser interfaces of XML::LibXML is the DOM parser. This +parser reads XML data into a DOM like data structure, so each tag can get +accessed and transformed. + +XML::LibXML's DOM parser is not only capable to parse XML data, but also +(strict) HTML files. There are three ways to parse documents - as a string, as +a Perl filehandle, or as a filename/URL. The return value from each is a L<<<<<< XML::LibXML::Document >>>>>> object, which is a DOM object. + +All of the functions listed below will throw an exception if the document is +invalid. To prevent this causing your program exiting, wrap the call in an +eval{} block + +=over 4 + +=item load_xml + + + $dom = XML::LibXML->load_xml( + location => $file_or_url + # parser options ... + ); + $dom = XML::LibXML->load_xml( + string => $xml_string + # parser options ... + ); + $dom = XML::LibXML->load_xml({ + IO => $perl_file_handle + # parser options ... + ); + $dom = $parser->load_xml(...); + + +This function is available since XML::LibXML 1.70. It provides easy to use +interface to the XML parser that parses given file (or URL), string, or input +stream to a DOM tree. The arguments can be passed in a HASH reference or as +name => value pairs. The function can be called as a class method or an object +method. In both cases it internally creates a new parser instance passing the +specified parser options; if called as an object method, it clones the original +parser (preserving its settings) and additionally applies the specified options +to the new parser. See the constructor C<<<<<< new >>>>>> and L<<<<<< Parser Options >>>>>> for more information. + + +=item load_xml + + + $dom = XML::LibXML->load_html(...); + $dom = $parser->load_html(...); + + +This function is available since XML::LibXML 1.70. It has the same usage as C<<<<<< load_xml >>>>>>, providing interface to the HTML parser. See C<<<<<< load_xml >>>>>> for more information. + + +Parsing HTML may cause problems, especially if the ampersand ('&') is used. +This is a common problem if HTML code is parsed that contains links to +CGI-scripts. Such links cause the parser to throw errors. In such cases libxml2 +still parses the entire document as there was no error, but the error causes +XML::LibXML to stop the parsing process. However, the document is not lost. +Such HTML documents should be parsed using the I<<<<<< recover >>>>>> flag. By default recovering is deactivated. + +The functions described above are implemented to parse well formed documents. +In some cases a program gets well balanced XML instead of well formed documents +(e.g. a XML fragment from a Database). With XML::LibXML it is not required to +wrap such fragments in the code, because XML::LibXML is capable even to parse +well balanced XML fragments. + +=over 4 + +=item parse_balanced_chunk + + $fragment = $parser->parse_balanced_chunk( $wbxmlstring, $encoding ); + +This function parses a well balanced XML string into a L<<<<<< XML::LibXML::DocumentFragment >>>>>>. The first arguments contains the input string, the optional second argument +can be used to specify character encoding of the input (UTF-8 is assumed by +default). + + +=item parse_xml_chunk + +This is the old name of parse_balanced_chunk(). Because it may causes confusion +with the push parser interface, this function should not be used anymore. + + + +=back + +By default XML::LibXML does not process XInclude tags within a XML Document +(see options section below). XML::LibXML allows to post process a document to +expand XInclude tags. + +=over 4 + +=item process_xincludes + + $parser->process_xincludes( $doc ); + +After a document is parsed into a DOM structure, you may want to expand the +documents XInclude tags. This function processes the given document structure +and expands all XInclude tags (or throws an error) by using the flags and +callbacks of the given parser instance. + +Note that the resulting Tree contains some extra nodes (of type +XML_XINCLUDE_START and XML_XINCLUDE_END) after successfully processing the +document. These nodes indicate where data was included into the original tree. +if the document is serialized, these extra nodes will not show up. + +Remember: A Document with processed XIncludes differs from the original +document after serialization, because the original XInclude tags will not get +restored! + +If the parser flag "expand_xincludes" is set to 1, you need not to post process +the parsed document. + + +=item processXIncludes + + $parser->processXIncludes( $doc ); + +This is an alias to process_xincludes, but through a JAVA like function name. + + +=item parse_file + + $doc = $parser->parse_file( $xmlfilename ); + +This function parses an XML document from a file or network; $xmlfilename can +be either a filename or an URL. Note that for parsing files, this function is +the fastest choice, about 6-8 times faster then parse_fh(). + + +=item parse_fh + + $doc = $parser->parse_fh( $io_fh ); + +parse_fh() parses a IOREF or a subclass of IO::Handle. + +Because the data comes from an open handle, libxml2's parser does not know +about the base URI of the document. To set the base URI one should use +parse_fh() as follows: + + + + my $doc = $parser->parse_fh( $io_fh, $baseuri ); + + +=item parse_string + + $doc = $parser->parse_string( $xmlstring); + +This function is similar to parse_fh(), but it parses a XML document that is +available as a single string in memory. Again, you can pass an optional base +URI to the function. + + + + my $doc = $parser->parse_string( $xmlstring, $baseuri ); + + +=item parse_html_file + + $doc = $parser->parse_html_file( $htmlfile, \%opts ); + +Similar to parse_file() but parses HTML (strict) documents; $htmlfile can be +filename or URL. + +An optional second argument can be used to pass some options to the HTML parser +as a HASH reference. See options labeled with HTML in L<<<<<< Parser Options >>>>>>. + + +=item parse_html_fh + + $doc = $parser->parse_html_fh( $io_fh, \%opts ); + +Similar to parse_fh() but parses HTML (strict) streams. + +An optional second argument can be used to pass some options to the HTML parser +as a HASH reference. See options labeled with HTML in L<<<<<< Parser Options >>>>>>. + +Note: encoding option may not work correctly with this function in libxml2 < +2.6.27 if the HTML file declares charset using a META tag. + + +=item parse_html_string + + $doc = $parser->parse_html_string( $htmlstring, \%opts ); + +Similar to parse_string() but parses HTML (strict) strings. + +An optional second argument can be used to pass some options to the HTML parser +as a HASH reference. See options labeled with HTML in L<<<<<< Parser Options >>>>>>. + + + +=back + + +=back + + +=head2 Push Parser + +XML::LibXML provides a push parser interface. Rather than pulling the data from +a given source the push parser waits for the data to be pushed into it. + +This allows one to parse large documents without waiting for the parser to +finish. The interface is especially useful if a program needs to pre-process +the incoming pieces of XML (e.g. to detect document boundaries). + +While XML::LibXML parse_*() functions force the data to be a well-formed XML, +the push parser will take any arbitrary string that contains some XML data. The +only requirement is that all the pushed strings are together a well formed +document. With the push parser interface a program can interrupt the parsing +process as required, where the parse_*() functions give not enough flexibility. + +Different to the pull parser implemented in parse_fh() or parse_file(), the +push parser is not able to find out about the documents end itself. Thus the +calling program needs to indicate explicitly when the parsing is done. + +In XML::LibXML this is done by a single function: + +=over 4 + +=item parse_chunk + + $parser->parse_chunk($string, $terminate); + +parse_chunk() tries to parse a given chunk of data, which isn't necessarily +well balanced data. The function takes two parameters: The chunk of data as a +string and optional a termination flag. If the termination flag is set to a +true value (e.g. 1), the parsing will be stopped and the resulting document +will be returned as the following example describes: + + + + my $parser = XML::LibXML->new; + for my $string ( "<", "foo", ' bar="hello world"', "/>") { + $parser->parse_chunk( $string ); + } + my $doc = $parser->parse_chunk("", 1); # terminate the parsing + + + +=back + +Internally XML::LibXML provides three functions that control the push parser +process: + +=over 4 + +=item init_push + + $parser->init_push(); + +Initializes the push parser. + + +=item push + + $parser->push(@data); + +This function pushes the data stored inside the array to libxml2's parser. Each +entry in @data must be a normal scalar! This method can be called repeatedly. + + +=item finish_push + + $doc = $parser->finish_push( $recover ); + +This function returns the result of the parsing process. If this function is +called without a parameter it will complain about non well-formed documents. If +$restore is 1, the push parser can be used to restore broken or non well formed +(XML) documents as the following example shows: + + + + eval { + $parser->push( "<foo>", "bar" ); + $doc = $parser->finish_push(); # will report broken XML + }; + if ( $@ ) { + # ... + } + +This can be annoying if the closing tag is missed by accident. The following +code will restore the document: + + + + eval { + $parser->push( "<foo>", "bar" ); + $doc = $parser->finish_push(1); # will return the data parsed + # unless an error happened + }; + + print $doc->toString(); # returns "<foo>bar</foo>" + +Of course finish_push() will return nothing if there was no data pushed to the +parser before. + + + +=back + + +=head2 Pull Parser (Reader) + +XML::LibXML also provides a pull-parser interface similar to the XmlReader +interface in .NET. This interface is almost streaming, and is usually faster +and simpler to use than SAX. See L<<<<<< XML::LibXML::Reader >>>>>>. + + +=head2 Direct SAX Parser + +XML::LibXML provides a direct SAX parser in the L<<<<<< XML::LibXML::SAX >>>>>> module. + + +=head2 DOM based SAX Parser + +XML::LibXML also provides a DOM based SAX parser. The SAX parser is defined in +the module XML::LibXML::SAX::Parser. As it is not a stream based parser, it +parses documents into a DOM and traverses the DOM tree instead. + +The API of this parser is exactly the same as any other Perl SAX2 parser. See +XML::SAX::Intro for details. + +Aside from the regular parsing methods, you can access the DOM tree traverser +directly, using the generate() method: + + + + my $doc = build_yourself_a_document(); + my $saxparser = $XML::LibXML::SAX::Parser->new( ... ); + $parser->generate( $doc ); + +This is useful for serializing DOM trees, for example that you might have done +prior processing on, or that you have as a result of XSLT processing. + +I<<<<<< WARNING >>>>>> + +This is NOT a streaming SAX parser. As I said above, this parser reads the +entire document into a DOM and serialises it. Some people couldn't read that in +the paragraph above so I've added this warning. If you want a streaming SAX +parser look at the L<<<<<< XML::LibXML::SAX >>>>>> man page + + +=head1 SERIALIZATION + +XML::LibXML provides some functions to serialize nodes and documents. The +serialization functions are described on the L<<<<<< XML::LibXML::Node >>>>>> manpage or the L<<<<<< XML::LibXML::Document >>>>>> manpage. XML::LibXML checks three global flags that alter the serialization +process: + + +=over 4 + +=item * + +skipXMLDeclaration + + + +=item * + +skipDTD + + + +=item * + +setTagCompression + + + +=back + +of that three functions only setTagCompression is available for all +serialization functions. + +Because XML::LibXML does these flags not itself, one has to define them locally +as the following example shows: + + + + local $XML::LibXML::skipXMLDeclaration = 1; + local $XML::LibXML::skipDTD = 1; + local $XML::LibXML::setTagCompression = 1; + +If skipXMLDeclaration is defined and not '0', the XML declaration is omitted +during serialization. + +If skipDTD is defined and not '0', an existing DTD would not be serialized with +the document. + +If setTagCompression is defined and not '0' empty tags are displayed as open +and closing tags rather than the shortcut. For example the empty tag I<<<<<< foo >>>>>> will be rendered as I<<<<<< <foo></foo> >>>>>> rather than I<<<<<< <foo/> >>>>>>. + + +=head1 PARSER OPTIONS + +Handling of libxml2 parser options has been unified and improved in XML::LibXML +1.70. You can now set default options for a particular parser instance by +passing them to the constructor as C<<<<<< XML::LibXML->new({name=>value, ...}) >>>>>> or C<<<<<< XML::LibXML->new(name=>value,...) >>>>>>. The options can be queried and changed using the following methods (pre-1.70 +interfaces such as C<<<<<< $parser->load_ext_dtd(0) >>>>>> also exist, see below): + +=over 4 + +=item option_exists + + $parser->option_exists($name); + +Returns 1 if the current XML::LibXML version supports the option C<<<<<< $name >>>>>>, otherwise returns 0 (note that this does not necessarily mean that the option +is supported by the underlying libxml2 library). + + +=item get_option + + $parser->get_option($name); + +Returns the current value of the parser option C<<<<<< $name >>>>>>. + + +=item set_option + + $parser->set_option($name,$value); + +Sets option C<<<<<< $name >>>>>> to value C<<<<<< $value >>>>>>. + + +=item set_options + + $parser->set_options({$name=>$value,...}); + +Sets multiple parsing options at once. + + + +=back + +IMPORTANT NOTE: This documentation reflects the parser flags available in +libxml2 2.7.3. Some options have no effect if an older version of libxml2 is +used. + +Each of the flags listed below is labeled labeled + +=over 4 + +=item /parser/ + +if it can be used with a C<<<<<< XML::LibXML >>>>>> parser object (i.e. passed to C<<<<<< XML::LibXML->new >>>>>>, C<<<<<< XML::LibXML->set_option >>>>>>, etc.) + + +=item /html/ + +if it can be used passed to the C<<<<<< parse_html_* >>>>>> methods + + +=item /reader/ + +if it can be used with the C<<<<<< XML::LibXML::Reader >>>>>>. + + + +=back + +Unless specified otherwise, the default for boolean valued options is 0 +(false). + +The available options are: + +=over 4 + +=item URI + +/parser, html, reader/ + +In case of parsing strings or file handles, XML::LibXML doesn't know about the +base uri of the document. To make relative references such as XIncludes work, +one has to set a base URI, that is then used for the parsed document. + + +=item line_numbers + +/parser, html, reader/ + +If this option is activated, libxml2 will store the line number of each element +node in the parsed document. The line number can be obtained using the C<<<<<< line_number() >>>>>> method of the C<<<<<< XML::LibXML::Node >>>>>> class (for non-element nodes this may report the line number of the containing +element). The line numbers are also used for reporting positions of validation +errors. + +IMPORTANT: Due to limitations in the libxml2 library line numbers greater than +65535 will be returned as 65535. Unfortunatelly, this is a long and sad story, +please see L<<<<<< http://bugzilla.gnome.org/show_bug.cgi?id=325533 >>>>>> for more details. + + +=item encoding + +/html/ + +character encoding of the input + + +=item recover + +/parser, html, reader/ + +recover from errors; possible values are 0, 1, and 2 + +A true value turns on recovery mode which allows one to parse broken XML or +HTML data. The recovery mode allows the parser to return the successfully +parsed portion of the input document. This is useful for almost well-formed +documents, where for example a closing tag is missing somewhere. Still, +XML::LibXML will only parse until the first fatal (non-recoverable) error +occurs, reporting recoverable parsing errors as warnings. To suppress even +these warnings, use recover=>2. + +Note that validation is switched off automatically in recovery mode. + + +=item expand_entities + +/parser, reader/ + +substitute entities; possible values are 0 and 1; default is 1 + +Note that although this flag disables entity substitution, it does not prevent +the parser from loading external entities; when substitution of an external +entity is disabled, the entity will be represented in the document tree by a +XML_ENTITY_REF_NODE node whose subtree will be the content obtained by parsing +the external resource; Although this is level of nesting is visible from the +DOM it is transparent to XPath data model, so it is possible to match nodes in +an unexpanded entity by the same XPath expression as if the entity was +expanded. See also ext_ent_handler. + + +=item ext_ent_handler + +/parser/ + +Provide a custom external entity handler to be used when expand_entities is set +to 1. Possible value is a subroutine reference. + +This feature does not work properly in libxml2 < 2.6.27! + +The subroutine provided is called whenever the parser needs to retrieve the +content of an external entity. It is called with two arguments: the system ID +(URI) and the public ID. The value returned by the subroutine is parsed as the +content of the entity. + +This method can be used to completely disable entity loading, e.g. to prevent +exploits of the type described at (L<<<<<< http://searchsecuritychannel.techtarget.com/generic/0,295582,sid97_gci1304703,00.html >>>>>>), where a service is tricked to expose its private data by letting it parse a +remote file (RSS feed) that contains an entity reference to a local file (e.g. C<<<<<< /etc/fstab >>>>>>). + +A more granular solution to this problem, however, is provided by custom URL +resolvers, as in + + my $c = XML::LibXML::InputCallback->new(); + sub match { # accept file:/ URIs except for XML catalogs in /etc/xml/ + my ($uri) = @_; + return ($uri=~m{^file:/} + and $uri !~ m{^file:///etc/xml/}) + ? 1 : 0; + } + $c->register_callbacks([ \&match, sub{}, sub{}, sub{} ]); + $parser->input_callbacks($c); + + + + +=item load_ext_dtd + +/parser, reader/ + +load the external DTD subset while parsing; possible values are 0 and 1. Unless +specified, XML::LibXML sets this option to 1. + +This flag is also required for DTD Validation, to provide complete attribute, +and to expand entities, regardless if the document has an internal subset. Thus +switching off external DTD loading, will disable entity expansion, validation, +and complete attributes on internal subsets as well. + + +=item complete_attributes + +/parser, reader/ + +create default DTD attributes; possible values are 0 and 1 + + +=item validation + +/parser, reader/ + +validate with the DTD; possible values are 0 and 1 + + +=item suppress_errors + +/parser, html, reader/ + +suppress error reports; possible values are 0 and 1 + + +=item suppress_warnings + +/parser, html, reader/ + +suppress warning reports; possible values are 0 and 1 + + +=item pedantic_parser + +/parser, html, reader/ + +pedantic error reporting; possible values are 0 and 1 + + +=item no_blanks + +/parser, html, reader/ + +remove blank nodes; possible values are 0 and 1 + + +=item expand_xinclude or xinclude + +/parser, reader/ + +Implement XInclude substitution; possible values are 0 and 1 + +Expands XIinclude tags immediately while parsing the document. Note that the +parser will use the URI resolvers installed via C<<<<<< XML::LibXML::InputCallback >>>>>> to parse the included document (if any). + + +=item no_xinclude_nodes + +/parser, reader/ + +do not generate XINCLUDE START/END nodes; possible values are 0 and 1 + + +=item no_network + +/parser, html, reader/ + +Forbid network access; possible values are 0 and 1 + +If set to true, all attempts to fetch non-local resources (such as DTD or +external entities) will fail (unless custom callbacks are defined). + +It may be necessary to use the flag C<<<<<< recover >>>>>> for processing documents requiring such resources while networking is off. + + +=item clean_namespaces + +/parser, reader/ + +remove redundant namespaces declarations during parsing; possible values are 0 +and 1. + + +=item no_cdata + +/parser, html, reader/ + +merge CDATA as text nodes; possible values are 0 and 1 + + +=item no_basefix + +/parser, reader/ + +not fixup XINCLUDE xml#base URIS; possible values are 0 and 1 + + +=item huge + +/parser, html, reader/ + +relax any hardcoded limit from the parser; possible values are 0 and 1. Unless +specified, XML::LibXML sets this option to 1. + + +=item gdome + +/parser/ + +THIS OPTION IS EXPERIMENTAL! + +Although quite powerful, XML:LibXML's DOM implementation is incomplete with +respect to the DOM level 2 or level 3 specifications. XML::GDOME is based on +libxml2 as well and and provides a rather complete DOM implementation by +wrapping libgdome. This flag allows you to make use of XML::LibXML's full +parser options and XML::GDOME's DOM implementation at the same time. + +To make use of this function, one has to install libgdome and configure +XML::LibXML to use this library. For this you need to rebuild XML::LibXML! + +Note: this feature was not seriously tested in recent XML::LibXML releases. + + + +=back + +For compatibility with XML::LibXML versions prior to 1.70, the following +methods are also supported for querying and setting the corresponding parser +options (if called without arguments, the methods return the current value of +the corresponding parser options; with an argument sets the option to a given +value): + + + + $parser->validation(); + $parser->recover(); + $parser->pedantic_parser(); + $parser->line_numbers(); + $parser->load_ext_dtd(); + $parser->complete_attributes(); + $parser->expand_xinclude(); + $parser->gdome_dom(); + $parser->clean_namespaces(); + $parser->no_network(); + +The following obsolete methods trigger parser options in some special way: + +=over 4 + +=item recover_silently + + + + $parser->recover_silently(1);; + +If called without an argument, returns true if the current value of the C<<<<<< recover >>>>>> parser option is 2 and returns false otherwise. With a true argument sets the C<<<<<< recover >>>>>> parser option to 2; with a false argument sets the C<<<<<< recover >>>>>> parser option to 0. + + +=item expand_entities + + + + $parser->expand_entities(0); + +Get/set the C<<<<<< expand_entities >>>>>> option. If called with a true argument, also turns the C<<<<<< load_ext_dtd >>>>>> option to 1. + + +=item keep_blanks + + + + $parser->keep_blanks(0); + +This is actually an oposite of the C<<<<<< no_blanks >>>>>> parser option. If used without an argument retrieves negated value of C<<<<<< no_blanks >>>>>>. If used with an argument sets C<<<<<< no_blanks >>>>>> to the oposite value. + + +=item base_uri + + + + $parser->base_uri( $your_base_uri ); + +Get/set the C<<<<<< URI >>>>>> option. + + + +=back + + +=head1 XML CATALOGS + +C<<<<<< libxml2 >>>>>> supports XML catalogs. Catalogs are used to map remote resources to their local +copies. Using catalogs can speed up parsing processes if many external +resources from remote addresses are loaded into the parsed documents (such as +DTDs or XIncludes). + +Note that libxml2 has a global pool of loaded catalogs, so if you apply the +method C<<<<<< load_catalog >>>>>> to one parser instance, all parser instances will start using the catalog (in +addition to other previously loaded catalogs). + +Note also that catalogs are not used when a custom external entity handler is +specified. At the current state it is not possible to make use of both types of +resolving systems at the same time. + +=over 4 + +=item load_catalog + + $parser->load_catalog( $catalog_file ); + +Loads the XML catalog file $catalog_file. + + + +=back + + +=head1 ERROR REPORTING + +XML::LibXML throws exceptions during parsing, validation or XPath processing +(and some other occasions). These errors can be caught by using I<<<<<< eval >>>>>> blocks. The error is stored in I<<<<<< $@ >>>>>>. There are two implementations: the old one throws $@ which is just a message +string, in the new one $@ is an object from the class XML::LibXML::Error; this +class overrides the operator "" so that when printed, the object flattens to +the usual error message. + +XML::LibXML throws errors as they occur. This is a very common misunderstanding +in the use of XML::LibXML. If the eval is omitted, XML::LibXML will always halt +your script by "croaking" (see Carp man page for details). + +Also note that an increasing number of functions throw errors if bad data is +passed as arguments. If you cannot assure valid data passed to XML::LibXML you +should eval these functions. + +Note: since version 1.59, get_last_error() is no longer available in +XML::LibXML for thread-safety reasons. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Pattern.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Pattern.pod new file mode 100755 index 00000000000..f8a05c67b91 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Pattern.pod @@ -0,0 +1,107 @@ +=head1 NAME + +XML::LibXML::Pattern - XML::LibXML::Pattern - interface to libxml2 XPath patterns + +=head1 SYNOPSIS + + + + use XML::LibXML; + my $pattern = new XML::LibXML::Pattern('/x:html/x:body//x:div', { 'x' => 'http://www.w3.org/1999/xhtml' }); + # test a match on a XML::LibXML::Node $node + + if ($pattern->matchesNode($node)) { ... } + + # or on a XML::LibXML::Reader + + if ($reader->matchesPattern($pattern)) { ... } + + # or skip reading all nodes that do not match + + print $reader->nodePath while $reader->nextPatternMatch($pattern); + + $pattern = XML::LibXML::Pattern->new( pattern, { prefix => namespace_URI, ... } ); + $bool = $pattern->matchesNode($node); + +=head1 DESCRIPTION + +This is a perl interface to libxml2's pattern matching support I<<<<<< http://xmlsoft.org/html/libxml-pattern.html >>>>>>. This feature requires recent versions of libxml2. + +Patterns are a small subset of XPath language, which is limitted to +(disjunctions of) location paths involving the child and descendant axes in +abbreviated form as described by the extended BNF given below: + + + + Selector ::= Path ( '|' Path )* + Path ::= ('.//' | '//' | '/' )? Step ( '/' Step )* + Step ::= '.' | NameTest + NameTest ::= QName | '*' | NCName ':' '*' + +For readability, whitespace may be used in selector XPath expressions even +though not explicitly allowed by the grammar: whitespace may be freely added +within patterns before or after any token, where + + + + token ::= '.' | '/' | '//' | '|' | NameTest + +Note that no predicates or attribute tests are allowed. + +Patterns are particularly useful for stream parsing provided via the C<<<<<< XML::LibXML::Reader >>>>>> interface. + +=over 4 + +=item new() + + $pattern = XML::LibXML::Pattern->new( pattern, { prefix => namespace_URI, ... } ); + +The constructor of a pattern takes a pattern expression (as described by the +BNF grammar above) and an optional HASH reference mapping prefixes to namespace +URIs. The method returns a compiled pattern object. + +Note that if the document has a default namespace, it must still be given an +prefix in order to be matched (as demanded by the XPath 1.0 specification). For +example, to match an element C<<<<<< <a xmlns="http://foo.bar"</a> >>>>>>, one should use a pattern like this: + + + + $pattern = XML::LibXML::Pattern->new( 'foo:a', { foo => 'http://foo.bar' }); + + +=item matchesNode($node) + + $bool = $pattern->matchesNode($node); + +Given a XML::LibXML::Node object, returns a true value if the node is matched +by the compiled pattern expression. + + + +=back + + +=head1 SEE ALSO + +L<<<<<< XML::LibXML::Reader >>>>>> for other methods involving compiled patterns. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Reader.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/Reader.pm new file mode 100755 index 00000000000..ec7b54451ab --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Reader.pm @@ -0,0 +1,212 @@ +# $Id: Reader.pm,v 1.1.2.1 2004/04/20 20:09:48 pajas Exp $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# +package XML::LibXML::Reader; + +use XML::LibXML; +use Carp; +use strict; +use warnings; + +use vars qw ($VERSION); +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use 5.008_000; + +BEGIN { + UNIVERSAL::can('XML::LibXML::Reader','_newForFile') or + croak("Cannot use XML::LibXML::Reader module - ". + "your libxml2 is compiled without reader support!"); +} + +use base qw(Exporter); +use constant { + XML_READER_TYPE_NONE => 0, + XML_READER_TYPE_ELEMENT => 1, + XML_READER_TYPE_ATTRIBUTE => 2, + XML_READER_TYPE_TEXT => 3, + XML_READER_TYPE_CDATA => 4, + XML_READER_TYPE_ENTITY_REFERENCE => 5, + XML_READER_TYPE_ENTITY => 6, + XML_READER_TYPE_PROCESSING_INSTRUCTION => 7, + XML_READER_TYPE_COMMENT => 8, + XML_READER_TYPE_DOCUMENT => 9, + XML_READER_TYPE_DOCUMENT_TYPE => 10, + XML_READER_TYPE_DOCUMENT_FRAGMENT => 11, + XML_READER_TYPE_NOTATION => 12, + XML_READER_TYPE_WHITESPACE => 13, + XML_READER_TYPE_SIGNIFICANT_WHITESPACE => 14, + XML_READER_TYPE_END_ELEMENT => 15, + XML_READER_TYPE_END_ENTITY => 16, + XML_READER_TYPE_XML_DECLARATION => 17, + + XML_READER_NONE => -1, + XML_READER_START => 0, + XML_READER_ELEMENT => 1, + XML_READER_END => 2, + XML_READER_EMPTY => 3, + XML_READER_BACKTRACK => 4, + XML_READER_DONE => 5, + XML_READER_ERROR => 6 +}; +use vars qw( @EXPORT @EXPORT_OK %EXPORT_TAGS ); + +sub CLONE_SKIP { 1 } + +BEGIN { + +%EXPORT_TAGS = ( + types => + [qw( + XML_READER_TYPE_NONE + XML_READER_TYPE_ELEMENT + XML_READER_TYPE_ATTRIBUTE + XML_READER_TYPE_TEXT + XML_READER_TYPE_CDATA + XML_READER_TYPE_ENTITY_REFERENCE + XML_READER_TYPE_ENTITY + XML_READER_TYPE_PROCESSING_INSTRUCTION + XML_READER_TYPE_COMMENT + XML_READER_TYPE_DOCUMENT + XML_READER_TYPE_DOCUMENT_TYPE + XML_READER_TYPE_DOCUMENT_FRAGMENT + XML_READER_TYPE_NOTATION + XML_READER_TYPE_WHITESPACE + XML_READER_TYPE_SIGNIFICANT_WHITESPACE + XML_READER_TYPE_END_ELEMENT + XML_READER_TYPE_END_ENTITY + XML_READER_TYPE_XML_DECLARATION + )], + states => + [qw( + XML_READER_NONE + XML_READER_START + XML_READER_ELEMENT + XML_READER_END + XML_READER_EMPTY + XML_READER_BACKTRACK + XML_READER_DONE + XML_READER_ERROR + )] +); +@EXPORT = (@{$EXPORT_TAGS{types}},@{$EXPORT_TAGS{states}}); +@EXPORT_OK = @EXPORT; +$EXPORT_TAGS{all}=\@EXPORT_OK; +} + +{ + my %props = ( + load_ext_dtd => 1, # load the external subset + complete_attributes => 2, # default DTD attributes + validation => 3, # validate with the DTD + expand_entities => 4, # substitute entities + ); + sub getParserProp { + my ($self, $name) = @_; + my $prop = $props{$name}; + return undef unless defined $prop; + return $self->_getParserProp($prop); + } + sub setParserProp { + my $self = shift; + my %args = map { ref($_) eq 'HASH' ? (%$_) : $_ } @_; + my ($key, $value); + while (($key,$value) = each %args) { + my $prop = $props{ $key }; + $self->_setParserProp($prop,$value); + } + return; + } + + my (%string_pool,%rng_pool,%xsd_pool); # used to preserve data passed to the reader + sub new { + my ($class) = shift; + my %args = map { ref($_) eq 'HASH' ? (%$_) : $_ } @_; + my $encoding = $args{encoding}; + my $URI = $args{URI}; + $URI="$URI" if defined $URI; # stringify in case it is an URI object + my $options = XML::LibXML->_parser_options(\%args); + + my $self = undef; + if ( defined $args{location} ) { + $self = $class->_newForFile( $args{location}, $encoding, $options ); + } + elsif ( defined $args{string} ) { + $self = $class->_newForString( $args{string}, $URI, $encoding, $options ); + $string_pool{$self} = \$args{string}; + } + elsif ( defined $args{IO} ) { + $self = $class->_newForIO( $args{IO}, $URI, $encoding, $options ); + } + elsif ( defined $args{DOM} ) { + croak("DOM must be a XML::LibXML::Document node") + unless UNIVERSAL::isa($args{DOM}, 'XML::LibXML::Document'); + $self = $class->_newForDOM( $args{DOM} ); + } + elsif ( defined $args{FD} ) { + my $fd = fileno($args{FD}); + $self = $class->_newForFd( $fd, $URI, $encoding, $options ); + } + else { + croak("XML::LibXML::Reader->new: specify location, string, IO, DOM, or FD"); + } + if ($args{RelaxNG}) { + if (ref($args{RelaxNG})) { + $rng_pool{$self} = \$args{RelaxNG}; + $self->_setRelaxNG($args{RelaxNG}); + } else { + $self->_setRelaxNGFile($args{RelaxNG}); + } + } + if ($args{Schema}) { + if (ref($args{Schema})) { + $xsd_pool{$self} = \$args{Schema}; + $self->_setXSD($args{Schema}); + } else { + $self->_setXSDFile($args{Schema}); + } + } + return $self; + } + sub DESTROY { + my $self = shift; + delete $string_pool{$self}; + delete $rng_pool{$self}; + delete $xsd_pool{$self}; + $self->_DESTROY; + } +} +sub close { + my ($reader) = @_; + # _close return -1 on failure, 0 on success + # perl close returns 0 on failure, 1 on success + return $reader->_close == 0 ? 1 : 0; +} + +sub preservePattern { + my $reader=shift; + my ($pattern,$ns_map)=@_; + if (ref($ns_map) eq 'HASH') { + # translate prefix=>URL hash to a (URL,prefix) list + $reader->_preservePattern($pattern,[reverse %$ns_map]); + } else { + $reader->_preservePattern(@_); + } +} + +sub nodePath { + my $reader=shift; + my $path = $reader->_nodePath; + $path=~s/\[\d+\]//g; # make /foo[1]/bar[1] just /foo/bar, since + # sibling count in the buffered fragment is + # basically random and generally misleading + return $path; +} + +1; +__END__ diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Reader.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Reader.pod new file mode 100755 index 00000000000..5c787ba3b30 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Reader.pod @@ -0,0 +1,669 @@ +=head1 NAME + +XML::LibXML::Reader - XML::LibXML::Reader - interface to libxml2 pull parser + +=head1 SYNOPSIS + + + + use XML::LibXML::Reader; + + + + my $reader = new XML::LibXML::Reader(location => "file.xml") + or die "cannot read file.xml\n"; + while ($reader->read) { + processNode($reader); + } + + + + sub processNode { + $reader = shift; + printf "%d %d %s %d\n", ($reader->depth, + $reader->nodeType, + $reader->name, + $reader->isEmptyElement); + } + +or + + + + $reader = new XML::LibXML::Reader(location => "file.xml") + or die "cannot read file.xml\n"; + $reader->preservePattern('//table/tr'); + $reader->finish; + print $reader->document->toString(1); + + +=head1 DESCRIPTION + +This is a perl interface to libxml2's pull-parser implementation xmlTextReader I<<<<<< http://xmlsoft.org/html/libxml-xmlreader.html >>>>>>. This feature requires at least libxml2-2.6.21. Pull-parser (StAX in Java, +XmlReader in C#) use an iterator approach to parse a xml-file. They are easier +to program than event-based parser (SAX) and much more lightweight than +tree-based parser (DOM), which load the complete tree into memory. + +The Reader acts as a cursor going forward on the document stream and stopping +at each node in the way. At every point DOM-like methods of the Reader object +allow to examine the current node (name, namespace, attributes, etc.) + +The user's code keeps control of the progress and simply calls the C<<<<<< read() >>>>>> function repeatedly to progress to the next node in the document order. Other +functions provide means for skipping complete sub-trees, or nodes until a +specific element, etc. + +At every time, only a very limited portion of the document is kept in the +memory, which makes the API more memory-efficient than using DOM. However, it +is also possible to mix Reader with DOM. At every point the user may copy the +current node (optionally expanded into a complete sub-tree) from the processed +document to another DOM tree, or to instruct the Reader to collect sub-document +in form of a DOM tree consisting of selected nodes. + +Reader API also supports namespaces, xml:base, entity handling, and DTD +validation. Schema and RelaxNG validation support will probably be added in +some later revision of the Perl interface. + +The naming of methods compared to libxml2 and C# XmlTextReader has been changed +slightly to match the conventions of XML::LibXML. Some functions have been +changed or added with respect to the C interface. + + +=head1 CONSTRUCTOR + +Depending on the XML source, the Reader object can be created with either of: + + + + my $reader = XML::LibXML::Reader->new( location => "file.xml", ... ); + my $reader = XML::LibXML::Reader->new( string => $xml_string, ... ); + my $reader = XML::LibXML::Reader->new( IO => $file_handle, ... ); + my $reader = XML::LibXML::Reader->new( FD => fileno(STDIN), ... ); + my $reader = XML::LibXML::Reader->new( DOM => $dom, ... ); + +where ... are (optional) reader options described below in L<<<<<< Reader options >>>>>> or various parser options described in L<<<<<< XML::LibXML::Parser >>>>>>. The constructor recognizes the following XML sources: + + +=head2 Source specification + +=over 4 + +=item location + +Read XML from a local file or URL. + + +=item string + +Read XML from a string. + + +=item IO + +Read XML a Perl IO filehandle. + + +=item FD + +Read XML from a file descriptor (bypasses Perl I/O layer, only applicable to +filehandles for regular files or pipes). Possibly faster than IO. + + +=item DOM + +Use reader API to walk through a pre-parsed L<<<<<< XML::LibXML::Document >>>>>>. + + + +=back + + +=head2 Reader options + +=over 4 + +=item encoding => $encoding + +override document encoding. + + +=item RelaxNG => $rng_schema + +can be used to pass either a L<<<<<< XML::LibXML::RelaxNG >>>>>> object or a filename or URL of a RelaxNG schema to the constructor. The schema +is then used to validate the document as it is processed. + + +=item Schema => $xsd_schema + +can be used to pass either a L<<<<<< XML::LibXML::Schema >>>>>> object or a filename or URL of a W3C XSD schema to the constructor. The schema +is then used to validate the document as it is processed. + + +=item ... + +the reader further supports various parser options described in L<<<<<< XML::LibXML::Parser >>>>>> (specificly those labeled by /reader/). + + + +=back + + +=head1 METHODS CONTROLLING PARSING PROGRESS + +=over 4 + +=item read () + +Moves the position to the next node in the stream, exposing its properties. + +Returns 1 if the node was read successfully, 0 if there is no more nodes to +read, or -1 in case of error + + +=item readAttributeValue () + +Parses an attribute value into one or more Text and EntityReference nodes. + +Returns 1 in case of success, 0 if the reader was not positioned on an +attribute node or all the attribute values have been read, or -1 in case of +error. + + +=item readState () + +Gets the read state of the reader. Returns the state value, or -1 in case of +error. The module exports constants for the Reader states, see STATES below. + + +=item depth () + +The depth of the node in the tree, starts at 0 for the root node. + + +=item next () + +Skip to the node following the current one in the document order while avoiding +the sub-tree if any. Returns 1 if the node was read successfully, 0 if there is +no more nodes to read, or -1 in case of error. + + +=item nextElement (localname?,nsURI?) + +Skip nodes following the current one in the document order until a specific +element is reached. The element's name must be equal to a given localname if +defined, and its namespace must equal to a given nsURI if defined. Either of +the arguments can be undefined (or omitted, in case of the latter or both). + +Returns 1 if the element was found, 0 if there is no more nodes to read, or -1 +in case of error. + + +=item nextPatternMatch (compiled_pattern) + +Skip nodes following the current one in the document order until an element +matching a given compiled pattern is reached. See L<<<<<< XML::LibXML::Pattern >>>>>> for information on compiled patterns. See also the C<<<<<< matchesPattern >>>>>> method. + +Returns 1 if the element was found, 0 if there is no more nodes to read, or -1 +in case of error. + + +=item skipSiblings () + +Skip all nodes on the same or lower level until the first node on a higher +level is reached. In particular, if the current node occurs in an element, the +reader stops at the end tag of the parent element, otherwise it stops at a node +immediately following the parent node. + +Returns 1 if successful, 0 if end of the document is reached, or -1 in case of +error. + + +=item nextSibling () + +It skips to the node following the current one in the document order while +avoiding the sub-tree if any. + +Returns 1 if the node was read successfully, 0 if there is no more nodes to +read, or -1 in case of error + + +=item nextSiblingElement (name?,nsURI?) + +Like nextElement but only processes sibling elements of the current node +(moving forward using C<<<<<< nextSibling () >>>>>> rather than C<<<<<< read () >>>>>>, internally). + +Returns 1 if the element was found, 0 if there is no more sibling nodes, or -1 +in case of error. + + +=item finish () + +Skip all remaining nodes in the document, reaching end of the document. + +Returns 1 if successful, 0 in case of error. + + +=item close () + +This method releases any resources allocated by the current instance and closes +any underlying input. It returns 0 on failure and 1 on success. This method is +automatically called by the destructor when the reader is forgotten, therefore +you do not have to call it directly. + + + +=back + + +=head1 METHODS EXTRACTING INFORMATION + +=over 4 + +=item name () + +Returns the qualified name of the current node, equal to (Prefix:)LocalName. + + +=item nodeType () + +Returns the type of the current node. See NODE TYPES below. + + +=item localName () + +Returns the local name of the node. + + +=item prefix () + +Returns the prefix of the namespace associated with the node. + + +=item namespaceURI () + +Returns the URI defining the namespace associated with the node. + + +=item isEmptyElement () + +Check if the current node is empty, this is a bit bizarre in the sense that +<a/> will be considered empty while <a></a> will not. + + +=item hasValue () + +Returns true if the node can have a text value. + + +=item value () + +Provides the text value of the node if present or undef if not available. + + +=item readInnerXml () + +Reads the contents of the current node, including child nodes and markup. +Returns a string containing the XML of the node's content, or undef if the +current node is neither an element nor attribute, or has no child nodes. + + +=item readOuterXml () + +Reads the contents of the current node, including child nodes and markup. + +Returns a string containing the XML of the node including its content, or undef +if the current node is neither an element nor attribute. + + +=item nodePath() + +Returns a cannonical location path to the current element from the root node to +the current node. Namespaced elements are matched by '*', because there is no +way to declare prefixes within XPath patterns. Unlike C<<<<<< XML::LibXML::Node::nodePath() >>>>>>, this function does not provide sibling counts (i.e. instead of e.g. '/a/b[1]' +and '/a/b[2]' you get '/a/b' for both matches). + + +=item matchesPattern(compiled_pattern) + +Returns a true value if the current node matches a compiled pattern. See L<<<<<< XML::LibXML::Pattern >>>>>> for information on compiled patterns. See also the C<<<<<< nextPatternMatch >>>>>> method. + + + +=back + + +=head1 METHODS EXTRACTING DOM NODES + +=over 4 + +=item document () + +Provides access to the document tree built by the reader. This function can be +used to collect the preserved nodes (see C<<<<<< preserveNode() >>>>>> and preservePattern). + +CAUTION: Never use this function to modify the tree unless reading of the whole +document is completed! + + +=item copyCurrentNode (deep) + +This function is similar a DOM function C<<<<<< copyNode() >>>>>>. It returns a copy of the currently processed node as a corresponding DOM +object. Use deep = 1 to obtain the full sub-tree. + + +=item preserveNode () + +This tells the XML Reader to preserve the current node in the document tree. A +document tree consisting of the preserved nodes and their content can be +obtained using the method C<<<<<< document() >>>>>> once parsing is finished. + +Returns the node or NULL in case of error. + + +=item preservePattern (pattern,\%ns_map) + +This tells the XML Reader to preserve all nodes matched by the pattern (which +is a streaming XPath subset). A document tree consisting of the preserved nodes +and their content can be obtained using the method C<<<<<< document() >>>>>> once parsing is finished. + +An optional second argument can be used to provide a HASH reference mapping +prefixes used by the XPath to namespace URIs. + +The XPath subset available with this function is described at + + + + http://www.w3.org/TR/xmlschema-1/#Selector + +and matches the production + + + + Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) + +Returns a positive number in case of success and -1 in case of error + + + +=back + + +=head1 METHODS PROCESSING ATTRIBUTES + +=over 4 + +=item attributeCount () + +Provides the number of attributes of the current node. + + +=item hasAttributes () + +Whether the node has attributes. + + +=item getAttribute (name) + +Provides the value of the attribute with the specified qualified name. + +Returns a string containing the value of the specified attribute, or undef in +case of error. + + +=item getAttributeNs (localName, namespaceURI) + +Provides the value of the specified attribute. + +Returns a string containing the value of the specified attribute, or undef in +case of error. + + +=item getAttributeNo (no) + +Provides the value of the attribute with the specified index relative to the +containing element. + +Returns a string containing the value of the specified attribute, or undef in +case of error. + + +=item isDefault () + +Returns true if the current attribute node was generated from the default value +defined in the DTD. + + +=item moveToAttribute (name) + +Moves the position to the attribute with the specified local name and namespace +URI. + +Returns 1 in case of success, -1 in case of error, 0 if not found + + +=item moveToAttributeNo (no) + +Moves the position to the attribute with the specified index relative to the +containing element. + +Returns 1 in case of success, -1 in case of error, 0 if not found + + +=item moveToAttributeNs (localName,namespaceURI) + +Moves the position to the attribute with the specified local name and namespace +URI. + +Returns 1 in case of success, -1 in case of error, 0 if not found + + +=item moveToFirstAttribute () + +Moves the position to the first attribute associated with the current node. + +Returns 1 in case of success, -1 in case of error, 0 if not found + + +=item moveToNextAttribute () + +Moves the position to the next attribute associated with the current node. + +Returns 1 in case of success, -1 in case of error, 0 if not found + + +=item moveToElement () + +Moves the position to the node that contains the current attribute node. + +Returns 1 in case of success, -1 in case of error, 0 if not moved + + +=item isNamespaceDecl () + +Determine whether the current node is a namespace declaration rather than a +regular attribute. + +Returns 1 if the current node is a namespace declaration, 0 if it is a regular +attribute or other type of node, or -1 in case of error. + + + +=back + + +=head1 OTHER METHODS + +=over 4 + +=item lookupNamespace (prefix) + +Resolves a namespace prefix in the scope of the current element. + +Returns a string containing the namespace URI to which the prefix maps or undef +in case of error. + + +=item encoding () + +Returns a string containing the encoding of the document or undef in case of +error. + + +=item standalone () + +Determine the standalone status of the document being read. Returns 1 if the +document was declared to be standalone, 0 if it was declared to be not +standalone, or -1 if the document did not specify its standalone status or in +case of error. + + +=item xmlVersion () + +Determine the XML version of the document being read. Returns a string +containing the XML version of the document or undef in case of error. + + +=item baseURI () + +Returns the base URI of a given node. + + +=item isValid () + +Retrieve the validity status from the parser. + +Returns 1 if valid, 0 if no, and -1 in case of error. + + +=item xmlLang () + +The xml:lang scope within which the node resides. + + +=item lineNumber () + +Provide the line number of the current parsing point. + + +=item columnNumber () + +Provide the column number of the current parsing point. + + +=item byteConsumed () + +This function provides the current index of the parser relative to the start of +the current entity. This function is computed in bytes from the beginning +starting at zero and finishing at the size in bytes of the file if parsing a +file. The function is of constant cost if the input is UTF-8 but can be costly +if run on non-UTF-8 input. + + +=item setParserProp (prop => value, ...) + +Change the parser processing behaviour by changing some of its internal +properties. The following properties are available with this function: +``load_ext_dtd'', ``complete_attributes'', ``validation'', ``expand_entities''. + +Since some of the properties can only be changed before any read has been done, +it is best to set the parsing properties at the constructor. + +Returns 0 if the call was successful, or -1 in case of error + + +=item getParserProp (prop) + +Get value of an parser internal property. The following property names can be +used: ``load_ext_dtd'', ``complete_attributes'', ``validation'', +``expand_entities''. + +Returns the value, usually 0 or 1, or -1 in case of error. + + + +=back + + +=head1 DESTRUCTION + +XML::LibXML takes care of the reader object destruction when the last reference +to the reader object goes out of scope. The document tree is preserved, though, +if either of $reader->document or $reader->preserveNode was used and references +to the document tree exist. + + +=head1 NODE TYPES + +The reader interface provides the following constants for node types (the +constant symbols are exported by default or if tag C<<<<<< :types >>>>>> is used). + + + + XML_READER_TYPE_NONE => 0 + XML_READER_TYPE_ELEMENT => 1 + XML_READER_TYPE_ATTRIBUTE => 2 + XML_READER_TYPE_TEXT => 3 + XML_READER_TYPE_CDATA => 4 + XML_READER_TYPE_ENTITY_REFERENCE => 5 + XML_READER_TYPE_ENTITY => 6 + XML_READER_TYPE_PROCESSING_INSTRUCTION => 7 + XML_READER_TYPE_COMMENT => 8 + XML_READER_TYPE_DOCUMENT => 9 + XML_READER_TYPE_DOCUMENT_TYPE => 10 + XML_READER_TYPE_DOCUMENT_FRAGMENT => 11 + XML_READER_TYPE_NOTATION => 12 + XML_READER_TYPE_WHITESPACE => 13 + XML_READER_TYPE_SIGNIFICANT_WHITESPACE => 14 + XML_READER_TYPE_END_ELEMENT => 15 + XML_READER_TYPE_END_ENTITY => 16 + XML_READER_TYPE_XML_DECLARATION => 17 + + +=head1 STATES + +The following constants represent the values returned by C<<<<<< readState() >>>>>>. They are exported by default, or if tag C<<<<<< :states >>>>>> is used: + + + + XML_READER_NONE => -1 + XML_READER_START => 0 + XML_READER_ELEMENT => 1 + XML_READER_END => 2 + XML_READER_EMPTY => 3 + XML_READER_BACKTRACK => 4 + XML_READER_DONE => 5 + XML_READER_ERROR => 6 + + +=head1 SEE ALSO + +L<<<<<< XML::LibXML::Pattern >>>>>> for information about compiled patterns. + +http://xmlsoft.org/html/libxml-xmlreader.html + +http://dotgnu.org/pnetlib-doc/System/Xml/XmlTextReader.html + + +=head1 ORIGINAL IMPLEMENTATION + +Heiko Klein, <H.Klein@gmx.net<gt> and Petr Pajas + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/RegExp.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/RegExp.pod new file mode 100755 index 00000000000..509de9f5ffd --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/RegExp.pod @@ -0,0 +1,71 @@ +=head1 NAME + +XML::LibXML::RegExp - XML::LibXML::RegExp - interface to libxml2 regular expressions + +=head1 SYNOPSIS + + + + use XML::LibXML; + my $compiled_re = new XML::LibXML::RegExp('[0-9]{5}(-[0-9]{4})?'); + if ($compiled_re->isDeterministic()) { ... } + if ($compiled_re->matches($string)) { ... } + + $compiled_re = XML::LibXML::RegExp->new( $regexp_str ); + $bool = $compiled_re->matches($string); + $bool = $compiled_re->isDeterministic(); + +=head1 DESCRIPTION + +This is a perl interface to libxml2's implementation of regular expressions, +which are used e.g. for validation of XML Schema simple types (pattern facet). + +=over 4 + +=item new() + + $compiled_re = XML::LibXML::RegExp->new( $regexp_str ); + +The constructor takes a string containing a regular expression and returns a +compiled regexp object. + + +=item matches($string) + + $bool = $compiled_re->matches($string); + +Given a string value, returns a true value if the value is matched by the +compiled regular expression. + + +=item isDeterministic() + + $bool = $compiled_re->isDeterministic(); + +Returns a true value if the regular expression is deterministic; returns false +otherwise. (See the definition of determinism in the XML spec (L<<<<<< http://www.w3.org/TR/REC-xml/#determinism >>>>>>)) + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/RelaxNG.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/RelaxNG.pod new file mode 100755 index 00000000000..7c2e530aadb --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/RelaxNG.pod @@ -0,0 +1,81 @@ +=head1 NAME + +XML::LibXML::RelaxNG - RelaxNG Schema Validation + +=head1 SYNOPSIS + + + + use XML::LibXML; + $doc = XML::LibXML->new->parse_file($url); + + $rngschema = XML::LibXML::RelaxNG->new( location => $filename_or_url ); + $rngschema = XML::LibXML::RelaxNG->new( string => $xmlschemastring ); + $rngschema = XML::LibXML::RelaxNG->new( DOM => $doc ); + eval { $rngschema->validate( $doc ); }; + +=head1 DESCRIPTION + +The XML::LibXML::RelaxNG class is a tiny frontend to libxml2's RelaxNG +implementation. Currently it supports only schema parsing and document +validation. + + +=head1 METHODS + +=over 4 + +=item new + + $rngschema = XML::LibXML::RelaxNG->new( location => $filename_or_url ); + $rngschema = XML::LibXML::RelaxNG->new( string => $xmlschemastring ); + $rngschema = XML::LibXML::RelaxNG->new( DOM => $doc ); + +The constructor of XML::LibXML::RelaxNG may get called with either one of three +parameters. The parameter tells the class from which source it should generate +a validation schema. It is important, that each schema only have a single +source. + +The location parameter allows to parse a schema from the filesystem or a URL. + +The string parameter will parse the schema from the given XML string. + +The DOM parameter allows to parse the schema from a pre-parsed L<<<<<< XML::LibXML::Document >>>>>>. + +Note that the constructor will die() if the schema does not meed the +constraints of the RelaxNG specification. + + +=item validate + + eval { $rngschema->validate( $doc ); }; + +This function allows to validate a (parsed) document against the given RelaxNG +schema. The argument of this function should be a XML::LibXML::Document object. +If this function succeeds, it will return 0, otherwise it will die() and report +the errors found. Because of this validate() should be always evaluated. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/SAX.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX.pm new file mode 100755 index 00000000000..8877240b5e6 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX.pm @@ -0,0 +1,97 @@ +# $Id: SAX.pm 785 2009-07-16 14:17:46Z pajas $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::SAX; + +use strict; +use vars qw($VERSION @ISA); + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +use XML::LibXML; +use XML::SAX::Base; + +use base qw(XML::SAX::Base); + +use Carp; +use IO::File; + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +sub _parse_characterstream { + my ( $self, $fh ) = @_; + # this my catch the xml decl, so the parser won't get confused about + # a possibly wrong encoding. + croak( "not implemented yet" ); +} + +sub _parse_bytestream { + my ( $self, $fh ) = @_; + $self->{ParserOptions}{LibParser} = XML::LibXML->new; + $self->{ParserOptions}{ParseFunc} = \&XML::LibXML::parse_fh; + $self->{ParserOptions}{ParseFuncParam} = $fh; + $self->_parse; + return $self->end_document({}); +} + +sub _parse_string { + my ( $self, $string ) = @_; +# $self->{ParserOptions}{LibParser} = XML::LibXML->new; + $self->{ParserOptions}{LibParser} = XML::LibXML->new() unless defined $self->{ParserOptions}{LibParser}; + $self->{ParserOptions}{ParseFunc} = \&XML::LibXML::parse_string; + $self->{ParserOptions}{ParseFuncParam} = $string; + $self->_parse; + return $self->end_document({}); +} + +sub _parse_systemid { + my $self = shift; + $self->{ParserOptions}{LibParser} = XML::LibXML->new; + $self->{ParserOptions}{ParseFunc} = \&XML::LibXML::parse_file; + $self->{ParserOptions}{ParseFuncParam} = shift; + $self->_parse; + return $self->end_document({}); +} + +sub parse_chunk { + my ( $self, $chunk ) = @_; + $self->{ParserOptions}{LibParser} = XML::LibXML->new; + $self->{ParserOptions}{ParseFunc} = \&XML::LibXML::parse_xml_chunk; + $self->{ParserOptions}{LibParser}->{IS_FILTER}=1; # a hack to prevent parse_xml_chunk from issuing end_document + $self->{ParserOptions}{ParseFuncParam} = $chunk; + $self->_parse; + return; +} + +sub _parse { + my $self = shift; + my $args = bless $self->{ParserOptions}, ref($self); + + $args->{LibParser}->set_handler( $self ); + eval { + $args->{ParseFunc}->($args->{LibParser}, $args->{ParseFuncParam}); + }; + + if ( $args->{LibParser}->{SAX}->{State} == 1 ) { + croak( "SAX Exception not implemented, yet; Data ended before document ended\n" ); + } + + # break a possible circular reference + $args->{LibParser}->set_handler( undef ); + if ( $@ ) { + croak $@; + } + return; +} + + +1; + diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/SAX.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX.pod new file mode 100755 index 00000000000..0a892598f00 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX.pod @@ -0,0 +1,49 @@ +=head1 NAME + +XML::LibXML::SAX - XML::LibXML direct SAX parser + +=head1 DESCRIPTION + +XML::LibXML provides an interface to libxml2 direct SAX interface. Through this +interface it is possible to generate SAX events directly while parsing a +document. While using the SAX parser XML::LibXML will not create a DOM Document +tree. + +Such an interface is useful if very large XML documents have to be processed +and no DOM functions are required. By using this interface it is possible to +read data stored within a XML document directly into the application data +structures without loading the document into memory. + +The SAX interface of XML::LibXML is based on the famous XML::SAX interface. It +uses the generic interface as provided by XML::SAX::Base. + +Additionally to the generic functions, which are only able to process entire +documents, XML::LibXML::SAX provides I<<<<<< parse_chunk() >>>>>>. This method generates SAX events from well balanced data such as is often +provided by databases. + +I<<<<<< NOTE: >>>>>> At the moment XML::LibXML provides only an incomplete interface to libxml2's +native SAX implementation. The current implementation is not tested in +production environment. It may causes significant memory problems or shows +wrong behaviour. If you run into specific problems using this part of +XML::LibXML, let me know. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Builder.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Builder.pm new file mode 100755 index 00000000000..8ebd042ddd0 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Builder.pm @@ -0,0 +1,332 @@ +# $Id: Builder.pm 785 2009-07-16 14:17:46Z pajas $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::SAX::Builder; + +use XML::LibXML; +use XML::NamespaceSupport; + +use vars qw ($VERSION); + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +sub new { + my $class = shift; + return bless {@_}, $class; +} + +sub result { $_[0]->{LAST_DOM}; } + +sub done { + my ($self) = @_; + my $dom = $self->{DOM}; + $dom = $self->{Parent} unless defined $dom; # this is for parsing document chunks + + delete $self->{NamespaceStack}; + delete $self->{Parent}; + delete $self->{DOM}; + + $self->{LAST_DOM} = $dom; + + return $dom; +} + +sub set_document_locator { +} + +sub start_dtd { + my ($self, $dtd) = @_; + if (defined $dtd->{Name} and + (defined $dtd->{SystemId} or defined $dtd->{PublicId})) { + $self->{DOM}->createExternalSubset($dtd->{Name},$dtd->{PublicId},$dtd->{SystemId}); + } +} + +sub end_dtd { +} + +sub start_document { + my ($self, $doc) = @_; + $self->{DOM} = XML::LibXML::Document->createDocument(); + + if ( defined $self->{Encoding} ) { + $self->xml_decl({Version => ($self->{Version} || '1.0') , Encoding => $self->{Encoding}}); + } + + $self->{NamespaceStack} = XML::NamespaceSupport->new; + $self->{NamespaceStack}->push_context; + $self->{Parent} = undef; + return (); +} + +sub xml_decl { + my $self = shift; + my $decl = shift; + + if ( defined $decl->{Version} ) { + $self->{DOM}->setVersion( $decl->{Version} ); + } + if ( defined $decl->{Encoding} ) { + $self->{DOM}->setEncoding( $decl->{Encoding} ); + } + return (); +} + +sub end_document { + my ($self, $doc) = @_; + my $d = $self->done(); + return $d; +} + +sub start_prefix_mapping { + my $self = shift; + my $ns = shift; + + unless ( defined $self->{DOM} or defined $self->{Parent} ) { + $self->{Parent} = XML::LibXML::DocumentFragment->new(); + $self->{NamespaceStack} = XML::NamespaceSupport->new; + $self->{NamespaceStack}->push_context; + } + + $self->{USENAMESPACESTACK} = 1; + + $self->{NamespaceStack}->declare_prefix( $ns->{Prefix}, $ns->{NamespaceURI} ); + return (); +} + + +sub end_prefix_mapping { + my $self = shift; + my $ns = shift; + $self->{NamespaceStack}->undeclare_prefix( $ns->{Prefix} ); + return (); +} + + +sub start_element { + my ($self, $el) = @_; + my $node; + + unless ( defined $self->{DOM} or defined $self->{Parent} ) { + $self->{Parent} = XML::LibXML::DocumentFragment->new(); + $self->{NamespaceStack} = XML::NamespaceSupport->new; + $self->{NamespaceStack}->push_context; + } + + if ( defined $self->{Parent} ) { + $el->{NamespaceURI} ||= ""; + $node = $self->{Parent}->addNewChild( $el->{NamespaceURI}, + $el->{Name} ); + } + else { + if ($el->{NamespaceURI}) { + if ( defined $self->{DOM} ) { + $node = $self->{DOM}->createRawElementNS($el->{NamespaceURI}, + $el->{Name}); + } + else { + $node = XML::LibXML::Element->new( $el->{Name} ); + $node->setNamespace( $el->{NamespaceURI}, + $el->{Prefix} , 1 ); + } + } + else { + if ( defined $self->{DOM} ) { + $node = $self->{DOM}->createRawElement($el->{Name}); + } + else { + $node = XML::LibXML::Element->new( $el->{Name} ); + } + } + + $self->{DOM}->setDocumentElement($node); + } + + # build namespaces + my $skip_ns= 0; + foreach my $p ( $self->{NamespaceStack}->get_declared_prefixes() ) { + $skip_ns= 1; + my $uri = $self->{NamespaceStack}->get_uri($p); + my $nodeflag = 0; + if ( defined $uri + and defined $el->{NamespaceURI} + and $uri eq $el->{NamespaceURI} ) { + # $nodeflag = 1; + next; + } + $node->setNamespace($uri, $p, 0 ); + } + + $self->{Parent} = $node; + + $self->{NamespaceStack}->push_context; + + # do attributes + foreach my $key (keys %{$el->{Attributes}}) { + my $attr = $el->{Attributes}->{$key}; + if (ref($attr)) { + # catch broken name/value pairs + next unless $attr->{Name} ; + next if $self->{USENAMESPACESTACK} + and ( $attr->{Name} eq "xmlns" + or ( defined $attr->{Prefix} + and $attr->{Prefix} eq "xmlns" ) ); + + + if ( defined $attr->{Prefix} + and $attr->{Prefix} eq "xmlns" and $skip_ns == 0 ) { + # ok, the generator does not set namespaces correctly! + my $uri = $attr->{Value}; + $node->setNamespace($uri, + $attr->{Localname}, + $uri eq $el->{NamespaceURI} ? 1 : 0 ); + } + else { + $node->setAttributeNS($attr->{NamespaceURI} || "", + $attr->{Name}, $attr->{Value}); + } + } + else { + $node->setAttribute($key => $attr); + } + } + return (); +} + +sub end_element { + my ($self, $el) = @_; + return unless $self->{Parent}; + + $self->{NamespaceStack}->pop_context; + $self->{Parent} = $self->{Parent}->parentNode(); + return (); +} + +sub start_cdata { + my $self = shift; + $self->{IN_CDATA} = 1; + return (); +} + +sub end_cdata { + my $self = shift; + $self->{IN_CDATA} = 0; + return (); +} + +sub characters { + my ($self, $chars) = @_; + if ( not defined $self->{DOM} and not defined $self->{Parent} ) { + $self->{Parent} = XML::LibXML::DocumentFragment->new(); + $self->{NamespaceStack} = XML::NamespaceSupport->new; + $self->{NamespaceStack}->push_context; + } + return unless $self->{Parent}; + my $node; + + unless ( defined $chars and defined $chars->{Data} ) { + return; + } + + if ( defined $self->{DOM} ) { + if ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) { + $node = $self->{DOM}->createCDATASection($chars->{Data}); + } + else { + $node = $self->{Parent}->appendText($chars->{Data}); + return; + } + } + elsif ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) { + $node = XML::LibXML::CDATASection->new($chars->{Data}); + } + else { + $node = XML::LibXML::Text->new($chars->{Data}); + } + + $self->{Parent}->addChild($node); + return (); +} + +sub comment { + my ($self, $chars) = @_; + my $comment; + if ( not defined $self->{DOM} and not defined $self->{Parent} ) { + $self->{Parent} = XML::LibXML::DocumentFragment->new(); + $self->{NamespaceStack} = XML::NamespaceSupport->new; + $self->{NamespaceStack}->push_context; + } + + unless ( defined $chars and defined $chars->{Data} ) { + return; + } + + if ( defined $self->{DOM} ) { + $comment = $self->{DOM}->createComment( $chars->{Data} ); + } + else { + $comment = XML::LibXML::Comment->new( $chars->{Data} ); + } + + if ( defined $self->{Parent} ) { + $self->{Parent}->addChild($comment); + } + else { + $self->{DOM}->addChild($comment); + } + return (); +} + +sub processing_instruction { + my ( $self, $pi ) = @_; + my $PI; + return unless defined $self->{DOM}; + $PI = $self->{DOM}->createPI( $pi->{Target}, $pi->{Data} ); + + if ( defined $self->{Parent} ) { + $self->{Parent}->addChild( $PI ); + } + else { + $self->{DOM}->addChild( $PI ); + } + return (); +} + +sub warning { + my $self = shift; + my $error = shift; + # fill $@ but do not die seriously + eval { $error->throw; }; +} + +sub error { + my $self = shift; + my $error = shift; + delete $self->{NamespaceStack}; + delete $self->{Parent}; + delete $self->{DOM}; + $error->throw; +} + +sub fatal_error { + my $self = shift; + my $error = shift; + delete $self->{NamespaceStack}; + delete $self->{Parent}; + delete $self->{DOM}; + $error->throw; +} + +1; + +__END__ diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Builder.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Builder.pod new file mode 100755 index 00000000000..4d327a76ec3 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Builder.pod @@ -0,0 +1,51 @@ +=head1 NAME + +XML::LibXML::SAX::Builder - Building DOM trees from SAX events. + +=head1 SYNOPSIS + + + + use XML::LibXML::SAX::Builder; + my $builder = XML::LibXML::SAX::Builder->new(); + + my $gen = XML::Generator::DBI->new(Handler => $builder, dbh => $dbh); + $gen->execute("SELECT * FROM Users"); + + my $doc = $builder->result(); + + +=head1 DESCRIPTION + +This is a SAX handler that generates a DOM tree from SAX events. Usage is as +above. Input is accepted from any SAX1 or SAX2 event generator. + +Building DOM trees from SAX events is quite easy with +XML::LibXML::SAX::Builder. The class is designed as a SAX2 final handler not as +a filter! + +Since SAX is strictly stream oriented, you should not expect anything to return +from a generator. Instead you have to ask the builder instance directly to get +the document built. XML::LibXML::SAX::Builder's result() function holds the +document generated from the last SAX stream. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Generator.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Generator.pm new file mode 100755 index 00000000000..337b0277734 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Generator.pm @@ -0,0 +1,157 @@ +# $Id: Generator.pm 772 2009-01-23 21:42:09Z pajas +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::SAX::Generator; + +use strict; + +use XML::LibXML; +use vars qw ($VERSION); + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +warn("This class (", __PACKAGE__, ") is deprecated!"); + +sub new { + my $class = shift; + unshift @_, 'Handler' unless @_ != 1; + my %p = @_; + return bless \%p, $class; +} + +sub generate { + my $self = shift; + my ($node) = @_; + + my $document = { Parent => undef }; + $self->{Handler}->start_document($document); + + process_node($self->{Handler}, $node); + + $self->{Handler}->end_document($document); +} + +sub process_node { + my ($handler, $node) = @_; + + my $node_type = $node->getType(); + if ($node_type == XML_COMMENT_NODE) { + $handler->comment( { Data => $node->getData } ); + } + elsif ($node_type == XML_TEXT_NODE || $node_type == XML_CDATA_SECTION_NODE) { + # warn($node->getData . "\n"); + $handler->characters( { Data => $node->getData } ); + } + elsif ($node_type == XML_ELEMENT_NODE) { + # warn("<" . $node->getName . ">\n"); + process_element($handler, $node); + # warn("</" . $node->getName . ">\n"); + } + elsif ($node_type == XML_ENTITY_REF_NODE) { + foreach my $kid ($node->getChildnodes) { + # warn("child of entity ref: " . $kid->getType() . " called: " . $kid->getName . "\n"); + process_node($handler, $kid); + } + } + elsif ($node_type == XML_DOCUMENT_NODE) { + # just get root element. Ignore other cruft. + foreach my $kid ($node->getChildnodes) { + if ($kid->getType() == XML_ELEMENT_NODE) { + process_element($handler, $kid); + last; + } + } + } + else { + warn("unknown node type: $node_type"); + } +} + +sub process_element { + my ($handler, $element) = @_; + + my @attr; + + foreach my $attr ($element->getAttributes) { + push @attr, XML::LibXML::SAX::AttributeNode->new( + Name => $attr->getName, + Value => $attr->getData, + NamespaceURI => $attr->getNamespaceURI, + Prefix => $attr->getPrefix, + LocalName => $attr->getLocalName, + ); + } + + my $node = { + Name => $element->getName, + Attributes => { map { $_->{Name} => $_ } @attr }, + NamespaceURI => $element->getNamespaceURI, + Prefix => $element->getPrefix, + LocalName => $element->getLocalName, + }; + + $handler->start_element($node); + + foreach my $child ($element->getChildnodes) { + process_node($handler, $child); + } + + $handler->end_element($node); +} + +package XML::LibXML::SAX::AttributeNode; + +use overload '""' => "stringify"; + +sub new { + my $class = shift; + my %p = @_; + return bless \%p, $class; +} + +sub stringify { + my $self = shift; + return $self->{Value}; +} + +1; + +__END__ + +=head1 NAME + +XML::LibXML::SAX::Generator - Generate SAX events from a LibXML tree + +=head1 SYNOPSIS + + my $handler = MySAXHandler->new(); + my $generator = XML::LibXML::SAX::Generator->new(Handler => $handler); + my $dom = XML::LibXML->new->parse_file("foo.xml"); + + $generator->generate($dom); + +=head1 DESCRIPTION + +THIS CLASS IS DEPRACED! Use XML::LibXML::SAX::Parser instead! + +This helper class allows you to generate SAX events from any XML::LibXML +node, and all it's sub-nodes. This basically gives you interop from +XML::LibXML to other modules that may implement SAX. + +It uses SAX2 style, but should be compatible with anything SAX1, by use +of stringification overloading. + +There is nothing to really know about, beyond the synopsis above, and +a general knowledge of how to use SAX, which is beyond the scope here. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Parser.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Parser.pm new file mode 100755 index 00000000000..086997970d3 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/SAX/Parser.pm @@ -0,0 +1,265 @@ +# $Id: Parser.pm 785 2009-07-16 14:17:46Z pajas $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::SAX::Parser; + +use strict; +use vars qw($VERSION @ISA); + +use XML::LibXML; +use XML::LibXML::Common qw(:libxml); +use XML::SAX::Base; +use XML::SAX::DocumentLocator; + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE +@ISA = ('XML::SAX::Base'); + +sub CLONE_SKIP { + return $XML::LibXML::__threads_shared ? 0 : 1; +} + +sub _parse_characterstream { + my ($self, $fh, $options) = @_; + die "parsing a characterstream is not supported at this time"; +} + +sub _parse_bytestream { + my ($self, $fh, $options) = @_; + my $parser = XML::LibXML->new(); + my $doc = exists($options->{Source}{SystemId}) ? $parser->parse_fh($fh, $options->{Source}{SystemId}) : $parser->parse_fh($fh); + $self->generate($doc); +} + +sub _parse_string { + my ($self, $str, $options) = @_; + my $parser = XML::LibXML->new(); + my $doc = exists($options->{Source}{SystemId}) ? $parser->parse_string($str, $options->{Source}{SystemId}) : $parser->parse_string($str); + $self->generate($doc); +} + +sub _parse_systemid { + my ($self, $sysid, $options) = @_; + my $parser = XML::LibXML->new(); + my $doc = $parser->parse_file($sysid); + $self->generate($doc); +} + +sub generate { + my $self = shift; + my ($node) = @_; + + my $doc = $node->ownerDocument(); + { + # precompute some DocumentLocator values + my %locator = ( + PublicId => undef, + SystemId => undef, + Encoding => undef, + XMLVersion => undef, + ); + my $dtd = defined $doc ? $doc->externalSubset() : undef; + if (defined $dtd) { + $locator{PublicId} = $dtd->publicId(); + $locator{SystemId} = $dtd->systemId(); + } + if (defined $doc) { + $locator{Encoding} = $doc->encoding(); + $locator{XMLVersion} = $doc->version(); + } + $self->set_document_locator( + XML::SAX::DocumentLocator->new( + sub { $locator{PublicId} }, + sub { $locator{SystemId} }, + sub { defined($self->{current_node}) ? $self->{current_node}->line_number() : undef }, + sub { 1 }, + sub { $locator{Encoding} }, + sub { $locator{XMLVersion} }, + ), + ); + } + + if ( $node->nodeType() == XML_DOCUMENT_NODE + || $node->nodeType == XML_HTML_DOCUMENT_NODE ) { + $self->start_document({}); + $self->xml_decl({Version => $node->getVersion, Encoding => $node->getEncoding}); + $self->process_node($node); + $self->end_document({}); + } +} + +sub process_node { + my ($self, $node) = @_; + + local $self->{current_node} = $node; + + my $node_type = $node->nodeType(); + if ($node_type == XML_COMMENT_NODE) { + $self->comment( { Data => $node->getData } ); + } + elsif ($node_type == XML_TEXT_NODE + || $node_type == XML_CDATA_SECTION_NODE) { + # warn($node->getData . "\n"); + $self->characters( { Data => $node->nodeValue } ); + } + elsif ($node_type == XML_ELEMENT_NODE) { + # warn("<" . $node->getName . ">\n"); + $self->process_element($node); + # warn("</" . $node->getName . ">\n"); + } + elsif ($node_type == XML_ENTITY_REF_NODE) { + foreach my $kid ($node->childNodes) { + # warn("child of entity ref: " . $kid->getType() . " called: " . $kid->getName . "\n"); + $self->process_node($kid); + } + } + elsif ($node_type == XML_DOCUMENT_NODE + || $node_type == XML_HTML_DOCUMENT_NODE + || $node_type == XML_DOCUMENT_FRAG_NODE) { + # some times it is just usefull to generate SAX events from + # a document fragment (very good with filters). + foreach my $kid ($node->childNodes) { + $self->process_node($kid); + } + } + elsif ($node_type == XML_PI_NODE) { + $self->processing_instruction( { Target => $node->getName, Data => $node->getData } ); + } + elsif ($node_type == XML_COMMENT_NODE) { + $self->comment( { Data => $node->getData } ); + } + elsif ( $node_type == XML_XINCLUDE_START + || $node_type == XML_XINCLUDE_END ) { + # ignore! + # i may want to handle this one day, dunno yet + } + elsif ($node_type == XML_DTD_NODE ) { + # ignore! + # i will support DTDs, but had no time yet. + } + else { + # warn("unsupported node type: $node_type"); + } + +} + +sub process_element { + my ($self, $element) = @_; + + my $attribs = {}; + my @ns_maps = $element->getNamespaces; + + foreach my $ns (@ns_maps) { + $self->start_prefix_mapping( + { + NamespaceURI => $ns->href, + Prefix => ( defined $ns->localname ? $ns->localname : ''), + } + ); + } + + foreach my $attr ($element->attributes) { + my $key; + # warn("Attr: $attr -> ", $attr->getName, " = ", $attr->getData, "\n"); + # this isa dump thing... + if ($attr->isa('XML::LibXML::Namespace')) { + # TODO This needs fixing modulo agreeing on what + # is the right thing to do here. + unless ( defined $attr->name ) { + ## It's an atter like "xmlns='foo'" + $attribs->{"{}xmlns"} = + { + Name => "xmlns", + LocalName => "xmlns", + Prefix => "", + Value => $attr->href, + NamespaceURI => "", + }; + } + else { + my $prefix = "xmlns"; + my $localname = $attr->localname; + my $key = "{http://www.w3.org/2000/xmlns/}"; + my $name = "xmlns"; + + if ( defined $localname ) { + $key .= $localname; + $name.= ":".$localname; + } + + $attribs->{$key} = + { + Name => $name, + Value => $attr->href, + NamespaceURI => "http://www.w3.org/2000/xmlns/", + Prefix => $prefix, + LocalName => $localname, + }; + } + } + else { + my $ns = $attr->namespaceURI; + + $ns = '' unless defined $ns; + $key = "{$ns}".$attr->localname; + ## Not sure why, but $attr->name is coming through stripped + ## of its prefix, so we need to hand-assemble a real name. + my $name = $attr->name; + $name = "" unless defined $name; + + my $prefix = $attr->prefix; + $prefix = "" unless defined $prefix; + $name = "$prefix:$name" + if index( $name, ":" ) < 0 && length $prefix; + + $attribs->{$key} = + { + Name => $name, + Value => $attr->value, + NamespaceURI => $ns, + Prefix => $prefix, + LocalName => $attr->localname, + }; + } + # use Data::Dumper; + # warn("Attr made: ", Dumper($attribs->{$key}), "\n"); + } + + my $node = { + Name => $element->nodeName, + Attributes => $attribs, + NamespaceURI => $element->namespaceURI, + Prefix => $element->prefix || "", + LocalName => $element->localname, + }; + + $self->start_element($node); + + foreach my $child ($element->childNodes) { + $self->process_node($child); + } + + my $end_node = { %$node }; + + delete $end_node->{Attributes}; + + $self->end_element($end_node); + + foreach my $ns (@ns_maps) { + $self->end_prefix_mapping( + { + NamespaceURI => $ns->href, + Prefix => ( defined $ns->localname ? $ns->localname : ''), + } + ); + } +} + +1; + +__END__ diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Schema.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Schema.pod new file mode 100755 index 00000000000..2697ccc9c54 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Schema.pod @@ -0,0 +1,78 @@ +=head1 NAME + +XML::LibXML::Schema - XML Schema Validation + +=head1 SYNOPSIS + + + + use XML::LibXML; + $doc = XML::LibXML->new->parse_file($url); + + $xmlschema = XML::LibXML::Schema->new( location => $filename_or_url ); + $xmlschema = XML::LibXML::Schema->new( string => $xmlschemastring ); + eval { $xmlschema->validate( $doc ); }; + +=head1 DESCRIPTION + +The XML::LibXML::Schema class is a tiny frontend to libxml2's XML Schema +implementation. Currently it supports only schema parsing and document +validation. As of 2.6.32, libxml2 only supports decimal types up to 24 digits +(the standard requires at least 18). + + +=head1 METHODS + +=over 4 + +=item new + + $xmlschema = XML::LibXML::Schema->new( location => $filename_or_url ); + $xmlschema = XML::LibXML::Schema->new( string => $xmlschemastring ); + +The constructor of XML::LibXML::Schema may get called with either one of two +parameters. The parameter tells the class from which source it should generate +a validation schema. It is important, that each schema only have a single +source. + +The location parameter allows to parse a schema from the filesystem or a URL. + +The string parameter will parse the schema from the given XML string. + +Note that the constructor will die() if the schema does not meed the +constraints of the XML Schema specification. + + +=item validate + + eval { $xmlschema->validate( $doc ); }; + +This function allows to validate a (parsed) document against the given XML +Schema. The argument of this function should be a L<<<<<< XML::LibXML::Document >>>>>> object. If this function succeeds, it will return 0, otherwise it will die() +and report the errors found. Because of this validate() should be always +evaluated. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/Text.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/Text.pod new file mode 100755 index 00000000000..f29b2fd100f --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/Text.pod @@ -0,0 +1,183 @@ +=head1 NAME + +XML::LibXML::Text - XML::LibXML Class for Text Nodes + +=head1 SYNOPSIS + + + + use XML::LibXML; + # Only methods specific to Text nodes are listed here, + # see XML::LibXML::Node manpage for other methods + + $text = XML::LibXML::Text->new( $content ); + $nodedata = $text->data; + $text->setData( $text_content ); + $text->substringData($offset, $length); + $text->appendData( $somedata ); + $text->insertData($offset, $string); + $text->deleteData($offset, $length); + $text->deleteDataString($remstring, $all); + $text->replaceData($offset, $length, $string); + $text->replaceDataString($old, $new, $flag); + $text->replaceDataRegEx( $search_cond, $replace_cond, $reflags ); + +=head1 DESCRIPTION + +Unlike the DOM specification, XML::LibXML implements the text node as the base +class of all character data node. Therefor there exists no CharacterData class. +This allows one to apply methods of text nodes also to Comments and +CDATA-sections. + + +=head1 METHODS + +The class inherits from L<<<<<< XML::LibXML::Node >>>>>>. The documentation for Inherited methods is not listed here. + +Many functions listed here are extensively documented in the DOM Level 3 specification (L<<<<<< http://www.w3.org/TR/DOM-Level-3-Core/ >>>>>>). Please refer to the specification for extensive documentation. + +=over 4 + +=item new + + $text = XML::LibXML::Text->new( $content ); + +The constructor of the class. It creates an unbound text node. + + +=item data + + $nodedata = $text->data; + +Although there exists the C<<<<<< nodeValue >>>>>> attribute in the Node class, the DOM specification defines data as a separate +attribute. C<<<<<< XML::LibXML >>>>>> implements these two attributes not as different attributes, but as aliases, +such as C<<<<<< libxml2 >>>>>> does. Therefore + + + + $text->data; + +and + + + + $text->nodeValue; + +will have the same result and are not different entities. + + +=item setData($string) + + $text->setData( $text_content ); + +This function sets or replaces text content to a node. The node has to be of +the type "text", "cdata" or "comment". + + +=item substringData($offset,$length) + + $text->substringData($offset, $length); + +Extracts a range of data from the node. (DOM Spec) This function takes the two +parameters $offset and $length and returns the sub-string, if available. + +If the node contains no data or $offset refers to an non-existing string index, +this function will return I<<<<<< undef >>>>>>. If $length is out of range C<<<<<< substringData >>>>>> will return the data starting at $offset instead of causing an error. + + +=item appendData($string) + + $text->appendData( $somedata ); + +Appends a string to the end of the existing data. If the current text node +contains no data, this function has the same effect as C<<<<<< setData >>>>>>. + + +=item insertData($offset,$string) + + $text->insertData($offset, $string); + +Inserts the parameter $string at the given $offset of the existing data of the +node. This operation will not remove existing data, but change the order of the +existing data. + +The $offset has to be a positive value. If $offset is out of range, C<<<<<< insertData >>>>>> will have the same behaviour as C<<<<<< appendData >>>>>>. + + +=item deleteData($offset, $length) + + $text->deleteData($offset, $length); + +This method removes a chunk from the existing node data at the given offset. +The $length parameter tells, how many characters should be removed from the +string. + + +=item deleteDataString($string, [$all]) + + $text->deleteDataString($remstring, $all); + +This method removes a chunk from the existing node data. Since the DOM spec is +quite unhandy if you already know C<<<<<< which >>>>>> string to remove from a text node, this method allows more perlish code :) + +The functions takes two parameters: I<<<<<< $string >>>>>> and optional the I<<<<<< $all >>>>>> flag. If $all is not set, I<<<<<< undef >>>>>> or I<<<<<< 0 >>>>>>, C<<<<<< deleteDataString >>>>>> will remove only the first occurrence of $string. If $all is I<<<<<< TRUE >>>>>>C<<<<<< deleteDataString >>>>>> will remove all occurrences of I<<<<<< $string >>>>>> from the node data. + + +=item replaceData($offset, $length, $string) + + $text->replaceData($offset, $length, $string); + +The DOM style version to replace node data. + + +=item replaceDataString($oldstring, $newstring, [$all]) + + $text->replaceDataString($old, $new, $flag); + +The more programmer friendly version of replaceData() :) + +Instead of giving offsets and length one can specify the exact string (I<<<<<< $oldstring >>>>>>) to be replaced. Additionally the I<<<<<< $all >>>>>> flag allows to replace all occurrences of I<<<<<< $oldstring >>>>>>. + + +=item replaceDataRegEx( $search_cond, $replace_cond, $reflags ) + + $text->replaceDataRegEx( $search_cond, $replace_cond, $reflags ); + +This method replaces the node's data by a C<<<<<< simple >>>>>> regular expression. Optional, this function allows to pass some flags that will +be added as flag to the replace statement. + +I<<<<<< NOTE: >>>>>> This is a shortcut for + + + + my $datastr = $node->getData(); + $datastr =~ s/somecond/replacement/g; # 'g' is just an example for any flag + $node->setData( $datastr ); + +This function can make things easier to read for simple replacements. For more +complex variants it is recommended to use the code snippet above. + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/XPathContext.pm b/Master/tlpkg/tlperl/lib/XML/LibXML/XPathContext.pm new file mode 100755 index 00000000000..81408dbd84d --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/XPathContext.pm @@ -0,0 +1,146 @@ +# $Id: XPathContext.pm 422 2002-11-08 17:10:30Z phish $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas +# +# + +package XML::LibXML::XPathContext; + +use strict; +use vars qw($VERSION @ISA $USE_LIBXML_DATA_TYPES); + +use Carp; +use XML::LibXML; +use XML::LibXML::NodeList; + +$VERSION = "1.70"; # VERSION TEMPLATE: DO NOT CHANGE + +# should LibXML XPath data types be used for simple objects +# when passing parameters to extension functions (default: no) +$USE_LIBXML_DATA_TYPES = 0; + +sub CLONE_SKIP { 1 } + +sub findnodes { + my ($self, $xpath, $node) = @_; + + my @nodes = $self->_guarded_find_call('_findnodes', $node, $xpath); + + if (wantarray) { + return @nodes; + } + else { + return XML::LibXML::NodeList->new(@nodes); + } +} + +sub find { + my ($self, $xpath, $node) = @_; + + my ($type, @params) = $self->_guarded_find_call('_find', $node, $xpath,0); + + if ($type) { + return $type->new(@params); + } + return undef; +} + +sub exists { + my ($self, $xpath, $node) = @_; + my (undef, $value) = $self->_guarded_find_call('_find', $node, $xpath,1); + return $value; +} + +sub findvalue { + my $self = shift; + return $self->find(@_)->to_literal->value; +} + +sub _guarded_find_call { + my ($self, $method, $node)=(shift,shift,shift); + + my $prev_node; + if (ref($node)) { + $prev_node = $self->getContextNode(); + $self->setContextNode($node); + } + my @ret; + eval { + @ret = $self->$method(@_); + }; + $self->_free_node_pool; + $self->setContextNode($prev_node) if ref($node); + + if ($@) { + my $err = $@; + chomp $err; + croak $err; + } + + return @ret; +} + +sub registerFunction { + my ($self, $name, $sub) = @_; + $self->registerFunctionNS($name, undef, $sub); + return; +} + +sub unregisterNs { + my ($self, $prefix) = @_; + $self->registerNs($prefix, undef); + return; +} + +sub unregisterFunction { + my ($self, $name) = @_; + $self->registerFunctionNS($name, undef, undef); + return; +} + +sub unregisterFunctionNS { + my ($self, $name, $ns) = @_; + $self->registerFunctionNS($name, $ns, undef); + return; +} + +sub unregisterVarLookupFunc { + my ($self) = @_; + $self->registerVarLookupFunc(undef, undef); + return; +} + +# extension function perl dispatcher +# borrowed from XML::LibXSLT + +sub _perl_dispatcher { + my $func = shift; + my @params = @_; + my @perlParams; + + my $i = 0; + while (@params) { + my $type = shift(@params); + if ($type eq 'XML::LibXML::Literal' or + $type eq 'XML::LibXML::Number' or + $type eq 'XML::LibXML::Boolean') + { + my $val = shift(@params); + unshift(@perlParams, $USE_LIBXML_DATA_TYPES ? $type->new($val) : $val); + } + elsif ($type eq 'XML::LibXML::NodeList') { + my $node_count = shift(@params); + unshift(@perlParams, $type->new(splice(@params, 0, $node_count))); + } + } + + $func = "main::$func" unless ref($func) || $func =~ /(.+)::/; + no strict 'refs'; + my $res = $func->(@perlParams); + return $res; +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/XPathContext.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/XPathContext.pod new file mode 100755 index 00000000000..80ceff6435e --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/XPathContext.pod @@ -0,0 +1,372 @@ +=head1 NAME + +XML::LibXML::XPathContext - XPath Evaluation + +=head1 SYNOPSIS + + my $xpc = XML::LibXML::XPathContext->new(); + my $xpc = XML::LibXML::XPathContext->new($node); + $xpc->registerNs($prefix, $namespace_uri) + $xpc->unregisterNs($prefix) + $uri = $xpc->lookupNs($prefix) + $xpc->registerVarLookupFunc($callback, $data) + $data = $xpc->getVarLookupData(); + $callback = $xpc->getVarLookupFunc(); + $xpc->unregisterVarLookupFunc($name); + $xpc->registerFunctionNS($name, $uri, $callback) + $xpc->unregisterFunctionNS($name, $uri) + $xpc->registerFunction($name, $callback) + $xpc->unregisterFunction($name) + @nodes = $xpc->findnodes($xpath) + @nodes = $xpc->findnodes($xpath, $context_node ) + $nodelist = $xpc->findnodes($xpath, $context_node ) + $object = $xpc->find($xpath ) + $object = $xpc->find($xpath, $context_node ) + $value = $xpc->findvalue($xpath ) + $value = $xpc->findvalue($xpath, $context_node ) + $bool = $xpc->exists( $xpath_expression, $context_node ); + $xpc->setContextNode($node) + my $node = $xpc->getContextNode; + $xpc->setContextPosition($position) + my $position = $xpc->getContextPosition; + $xpc->setContextSize($size) + my $size = $xpc->getContextSize; + $xpc->setContextNode($node) +The XML::LibXML::XPathContext class provides an almost complete interface to +libxml2's XPath implementation. With XML::LibXML::XPathContext is is possible +to evaluate XPath expressions in the context of arbitrary node, context size, +and context position, with a user-defined namespace-prefix mapping, custom +XPath functions written in Perl, and even a custom XPath variable resolver. + + +=head1 EXAMPLES + + +=head2 Namespaces + +This example demonstrates C<<<<<< registerNs() >>>>>> method. It finds all paragraph nodes in an XHTML document. + + + + my $xc = XML::LibXML::XPathContext->new($xhtml_doc); + $xc->registerNs('xhtml', 'http://www.w3.org/1999/xhtml'); + my @nodes = $xc->findnodes('//xhtml:p'); + + +=head2 Custom XPath functions + +This example demonstrates C<<<<<< registerFunction() >>>>>> method by defining a function filtering nodes based on a Perl regular +expression: + + + + sub grep_nodes { + my ($nodelist,$regexp) = @_; + my $result = XML::LibXML::NodeList->new; + for my $node ($nodelist->get_nodelist()) { + $result->push($node) if $node->textContent =~ $regexp; + } + return $result; + }; + + my $xc = XML::LibXML::XPathContext->new($node); + $xc->registerFunction('grep_nodes', \&grep_nodes); + my @nodes = $xc->findnodes('//section[grep_nodes(para,"\bsearch(ing|es)?\b")]'); + + +=head2 Variables + +This example demonstrates C<<<<<< registerVarLookup() >>>>>> method. We use XPath variables to recycle results of previous evaluations: + + + + sub var_lookup { + my ($varname,$ns,$data)=@_; + return $data->{$varname}; + } + + my $areas = XML::LibXML->new->parse_file('areas.xml'); + my $empl = XML::LibXML->new->parse_file('employees.xml'); + + my $xc = XML::LibXML::XPathContext->new($empl); + + my %variables = ( + A => $xc->find('/employees/employee[@salary>10000]'), + B => $areas->find('/areas/area[district='Brooklyn']/street'), + ); + + # get names of employees from $A working in an area listed in $B + $xc->registerVarLookupFunc(\&var_lookup, \%variables); + my @nodes = $xc->findnodes('$A[work_area/street = $B]/name'); + + +=head1 METHODS + +=over 4 + +=item new + + my $xpc = XML::LibXML::XPathContext->new(); + +Creates a new XML::LibXML::XPathContext object without a context node. + + my $xpc = XML::LibXML::XPathContext->new($node); + +Creates a new XML::LibXML::XPathContext object with the context node set to C<<<<<< $node >>>>>>. + + +=item registerNs + + $xpc->registerNs($prefix, $namespace_uri) + +Registers namespace C<<<<<< $prefix >>>>>> to C<<<<<< $namespace_uri >>>>>>. + + +=item unregisterNs + + $xpc->unregisterNs($prefix) + +Unregisters namespace C<<<<<< $prefix >>>>>>. + + +=item lookupNs + + $uri = $xpc->lookupNs($prefix) + +Returns namespace URI registered with C<<<<<< $prefix >>>>>>. If C<<<<<< $prefix >>>>>> is not registered to any namespace URI returns C<<<<<< undef >>>>>>. + + +=item registerVarLookupFunc + + $xpc->registerVarLookupFunc($callback, $data) + +Registers variable lookup function C<<<<<< $prefix >>>>>>. The registered function is executed by the XPath engine each time an XPath +variable is evaluated. It takes three arguments: C<<<<<< $data >>>>>>, variable name, and variable ns-URI and must return one value: a number or +string or any C<<<<<< XML::LibXML:: >>>>>> object that can be a result of findnodes: Boolean, Literal, Number, Node (e.g. +Document, Element, etc.), or NodeList. For convenience, simple (non-blessed) +array references containing only L<<<<<< XML::LibXML::Node >>>>>> objects can be used instead of a L<<<<<< XML::LibXML::NodeList >>>>>>. + + +=item getVarLookupData + + $data = $xpc->getVarLookupData(); + +Returns the data that have been associated with a variable lookup function +during a previous call to C<<<<<< registerVarLookupFunc >>>>>>. + + +=item getVarLookupFunc + + $callback = $xpc->getVarLookupFunc(); + +Returns the variable lookup function previously registered with C<<<<<< registerVarLookupFunc >>>>>>. + + +=item unregisterVarLookupFunc + + $xpc->unregisterVarLookupFunc($name); + +Unregisters variable lookup function and the associated lookup data. + + +=item registerFunctionNS + + $xpc->registerFunctionNS($name, $uri, $callback) + +Registers an extension function C<<<<<< $name >>>>>> in C<<<<<< $uri >>>>>> namespace. C<<<<<< $callback >>>>>> must be a CODE reference. The arguments of the callback function are either +simple scalars or C<<<<<< XML::LibXML::* >>>>>> objects depending on the XPath argument types. The function is responsible for +checking the argument number and types. Result of the callback code must be a +single value of the following types: a simple scalar (number, string) or an +arbitrary C<<<<<< XML::LibXML::* >>>>>> object that can be a result of findnodes: Boolean, Literal, Number, Node (e.g. +Document, Element, etc.), or NodeList. For convenience, simple (non-blessed) +array references containing only L<<<<<< XML::LibXML::Node >>>>>> objects can be used instead of a L<<<<<< XML::LibXML::NodeList >>>>>>. + + +=item unregisterFunctionNS + + $xpc->unregisterFunctionNS($name, $uri) + +Unregisters extension function C<<<<<< $name >>>>>> in C<<<<<< $uri >>>>>> namespace. Has the same effect as passing C<<<<<< undef >>>>>> as C<<<<<< $callback >>>>>> to registerFunctionNS. + + +=item registerFunction + + $xpc->registerFunction($name, $callback) + +Same as C<<<<<< registerFunctionNS >>>>>> but without a namespace. + + +=item unregisterFunction + + $xpc->unregisterFunction($name) + +Same as C<<<<<< unregisterFunctionNS >>>>>> but without a namespace. + + +=item findnodes + + @nodes = $xpc->findnodes($xpath) + + @nodes = $xpc->findnodes($xpath, $context_node ) + + $nodelist = $xpc->findnodes($xpath, $context_node ) + +Performs the xpath statement on the current node and returns the result as an +array. In scalar context returns a L<<<<<< XML::LibXML::NodeList >>>>>> object. Optionally, a node may be passed as a second argument to set the +context node for the query. + +The xpath expression can be passed either as a string or or as a L<<<<<< XML::LibXML::XPathExpression >>>>>> object. + + +=item find + + $object = $xpc->find($xpath ) + + $object = $xpc->find($xpath, $context_node ) + +Performs the xpath expression using the current node as the context of the +expression, and returns the result depending on what type of result the XPath +expression had. For example, the XPath C<<<<<< 1 * 3 + 52 >>>>>> results in a L<<<<<< XML::LibXML::Number >>>>>> object being returned. Other expressions might return a L<<<<<< XML::LibXML::Boolean >>>>>> object, or a L<<<<<< XML::LibXML::Literal >>>>>> object (a string). Each of those objects uses Perl's overload feature to ``do +the right thing'' in different contexts. Optionally, a node may be passed as a +second argument to set the context node for the query. + +The xpath expression can be passed either as a string or or as a L<<<<<< XML::LibXML::XPathExpression >>>>>> object. + + +=item findvalue + + $value = $xpc->findvalue($xpath ) + + $value = $xpc->findvalue($xpath, $context_node ) + +Is exactly equivalent to: + + + + $xpc->find( $xpath, $context_node )->to_literal; + +That is, it returns the literal value of the results. This enables you to +ensure that you get a string back from your search, allowing certain shortcuts. +This could be used as the equivalent of <xsl:value-of select=``some_xpath''/>. +Optionally, a node may be passed in the second argument to set the context node +for the query. + +The xpath expression can be passed either as a string or or as a L<<<<<< XML::LibXML::XPathExpression >>>>>> object. + + +=item exists + + $bool = $xpc->exists( $xpath_expression, $context_node ); + +This method behaves like I<<<<<< findnodes >>>>>>, except that it only returns a boolean value (1 if the expression matches a +node, 0 otherwise) and may be faster than I<<<<<< findnodes >>>>>>, because the XPath evaluation may stop early on the first match (this is true +for libxml2 >= 2.6.27). + +For XPath expressions that do not return node-set, the method returns true if +the returned value is a non-zero number or a non-empty string. + + +=item setContextNode + + $xpc->setContextNode($node) + +Set the current context node. + + +=item getContextNode + + my $node = $xpc->getContextNode; + +Get the current context node. + + +=item setContextPosition + + $xpc->setContextPosition($position) + +Set the current context position. By default, this value is -1 (and evaluating +XPath function C<<<<<< position() >>>>>> in the initial context raises an XPath error), but can be set to any value up +to context size. This usually only serves to cheat the XPath engine to return +given position when C<<<<<< position() >>>>>> XPath function is called. Setting this value to -1 restores the default +behavior. + + +=item getContextPosition + + my $position = $xpc->getContextPosition; + +Get the current context position. + + +=item setContextSize + + $xpc->setContextSize($size) + +Set the current context size. By default, this value is -1 (and evaluating +XPath function C<<<<<< last() >>>>>> in the initial context raises an XPath error), but can be set to any +non-negative value. This usually only serves to cheat the XPath engine to +return the given value when C<<<<<< last() >>>>>> XPath function is called. If context size is set to 0, position is +automatically also set to 0. If context size is positive, position is +automatically set to 1. Setting context size to -1 restores the default +behavior. + + +=item getContextSize + + my $size = $xpc->getContextSize; + +Get the current context size. + + +=item setContextNode + + $xpc->setContextNode($node) + +Set the current context node. + + + +=back + + +=head1 BUGS AND CAVEATS + +XML::LibXML::XPathContext objects I<<<<<< are >>>>>> reentrant, meaning that you can call methods of an XML::LibXML::XPathContext +even from XPath extension functions registered with the same object or from a +variable lookup function. On the other hand, you should rather avoid +registering new extension functions, namespaces and a variable lookup function +from within extension functions and a variable lookup function, unless you want +to experience untested behavior. + + +=head1 AUTHORS + +Ilya Martynov and Petr Pajas, based on XML::LibXML and XML::LibXSLT code by +Matt Sergeant and Christian Glahn. + + +=head1 HISTORICAL REMARK + +Prior to XML::LibXML 1.61 this module was distributed separately for +maintenance reasons. + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXML/XPathExpression.pod b/Master/tlpkg/tlperl/lib/XML/LibXML/XPathExpression.pod new file mode 100755 index 00000000000..742b8747450 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXML/XPathExpression.pod @@ -0,0 +1,65 @@ +=head1 NAME + +XML::LibXML::XPathExpression - XML::LibXML::XPathExpression - interface to libxml2 pre-compiled XPath expressions + +=head1 SYNOPSIS + + + + use XML::LibXML; + my $compiled_xpath = new XML::LibXML::XPathExpression('//foo[@bar="baz"][position()<4]'); + + # interface from XML::LibXML::Node + + my $result = $node->find($compiled_xpath); + my @nodes = $node->findnodes($compiled_xpath); + my $value = $node->findvalue($compiled_xpath); + + # interface from XML::LibXML::XPathContext + + my $result = $xpc->find($compiled_xpath,$node); + my @nodes = $xpc->findnodes($compiled_xpath,$node); + my $value = $xpc->findvalue($compiled_xpath,$node); + + $compiled = XML::LibXML::XPathExpression->new( xpath_string ); + +=head1 DESCRIPTION + +This is a perl interface to libxml2's pre-compiled XPath expressions. +Pre-compiling an XPath expression can give in some performance benefit if the +same XPath query is evaluated many times. C<<<<<< XML::LibXML::XPathExpression >>>>>> objects can be passed to all C<<<<<< find... >>>>>> functions C<<<<<< XML::LibXML >>>>>> that expect an XPath expression. + +=over 4 + +=item new() + + $compiled = XML::LibXML::XPathExpression->new( xpath_string ); + +The constructor takes an XPath 1.0 expression as a string and returns an object +representing the pre-compiled expressions (the actual data structure is +internal to libxml2). + + + +=back + +=head1 AUTHORS + +Matt Sergeant, +Christian Glahn, +Petr Pajas + + +=head1 VERSION + +1.70 + +=head1 COPYRIGHT + +2001-2007, AxKit.com Ltd. + +2002-2006, Christian Glahn. + +2006-2009, Petr Pajas. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/LibXSLT.pm b/Master/tlpkg/tlperl/lib/XML/LibXSLT.pm new file mode 100755 index 00000000000..034f52a180d --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/LibXSLT.pm @@ -0,0 +1,1008 @@ +# $Id: LibXSLT.pm 228 2009-10-07 12:25:23Z pajas $ +# +# This is free software, you may use it and distribute it under the same terms as +# Perl itself. +# +# Copyright 2001-2009 AxKit.com Ltd. +# +# +package XML::LibXSLT; + +use strict; +use vars qw($VERSION @ISA $USE_LIBXML_DATA_TYPES $MatchCB $ReadCB $OpenCB $CloseCB); + +sub REQUIRE_XML_LIBXML_ABI_VERSION { 2 } + +use XML::LibXML 1.70; +use XML::LibXML::Literal; +use XML::LibXML::Boolean; +use XML::LibXML::Number; +use XML::LibXML::NodeList; + + +BEGIN { +use Carp; + +require Exporter; + +$VERSION = "1.70"; + +require DynaLoader; + +@ISA = qw(DynaLoader); + +# avoid possible shared library name conflict on Win32 +# not using this trick on 5.10.0 (suffering from DynaLoader bug) +local $DynaLoader::dl_dlext = "xs.$DynaLoader::dl_dlext" if (($^O eq 'MSWin32') && ($] ne '5.010000')); + +bootstrap XML::LibXSLT $VERSION; + +# the following magic lets XML::LibXSLT internals know +# where to register XML::LibXML proxy nodes +INIT_THREAD_SUPPORT() if XML::LibXML::threads_shared_enabled(); +$USE_LIBXML_DATA_TYPES = 0; +} + + +sub new { + my $class = shift; + my %options = @_; + my $self = bless \%options, $class; + return $self; +} + +# ido - perl dispatcher +sub perl_dispatcher { + my $func = shift; + my @params = @_; + my @perlParams; + + my $i = 0; + while (@params) { + my $type = shift(@params); + if ($type eq 'XML::LibXML::Literal' or + $type eq 'XML::LibXML::Number' or + $type eq 'XML::LibXML::Boolean') + { + my $val = shift(@params); + unshift(@perlParams, $USE_LIBXML_DATA_TYPES ? $type->new($val) : $val); + } + elsif ($type eq 'XML::LibXML::NodeList') { + my $node_count = shift(@params); + my @nodes = splice(@params, 0, $node_count); + # warn($_->getName) for @nodes; + unshift(@perlParams, $type->new(@nodes)); + } + } + + $func = "main::$func" unless ref($func) || $func =~ /(.+)::/; + no strict 'refs'; + my $res = $func->(@perlParams); + return $res; +} + + +sub xpath_to_string { + my @results; + while (@_) { + my $value = shift(@_); $value = '' unless defined $value; + push @results, $value; + if (@results % 2) { + # key + $results[-1] =~ s/:/_/g; # XSLT doesn't like names with colons + } + else { + if ($value =~ s/'/', "'", '/g) { + $results[-1] = "concat('$value')"; + } + else { + $results[-1] = "'$results[-1]'"; + } + } + } + return @results; +} + +#-------------------------------------------------------------------------# +# callback functions # +#-------------------------------------------------------------------------# + +sub security_callbacks { + my $self = shift; + my $scbclass = shift; + + if ( defined $scbclass ) { + $self->{XML_LIBXSLT_SECPREFS} = $scbclass; + } + return $self->{XML_LIBXSLT_SECPREFS}; +} + +sub input_callbacks { + my $self = shift; + my $icbclass = shift; + + if ( defined $icbclass ) { + $self->{XML_LIBXSLT_CALLBACK_STACK} = $icbclass; + } + return $self->{XML_LIBXSLT_CALLBACK_STACK}; +} + +sub match_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_MATCH_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_MATCH_CB}; + } + else { + $MatchCB = shift if scalar @_; + return $MatchCB; + } +} + +sub read_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_READ_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_READ_CB}; + } + else { + $ReadCB = shift if scalar @_; + return $ReadCB; + } +} + +sub close_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_CLOSE_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_CLOSE_CB}; + } + else { + $CloseCB = shift if scalar @_; + return $CloseCB; + } +} + +sub open_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_OPEN_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_OPEN_CB}; + } + else { + $OpenCB = shift if scalar @_; + return $OpenCB; + } +} + +sub callbacks { + my $self = shift; + if ( ref $self ) { + if (@_) { + my ($match, $open, $read, $close) = @_; + @{$self}{qw(XML_LIBXSLT_MATCH_CB XML_LIBXSLT_OPEN_CB XML_LIBXSLT_READ_CB XML_LIBXSLT_CLOSE_CB)} = ($match, $open, $read, $close); + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + else { + return @{$self}{qw(XML_LIBXSLT_MATCH_CB XML_LIBXSLT_OPEN_CB XML_LIBXSLT_READ_CB XML_LIBXSLT_CLOSE_CB)}; + } + } + else { + if (@_) { + ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ) = @_; + } + else { + return ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ); + } + } +} + +sub _init_callbacks{ + my $self = shift; + my $icb = $self->{XML_LIBXSLT_CALLBACK_STACK}; + + unless ( defined $icb ) { + $self->{XML_LIBXSLT_CALLBACK_STACK} = XML::LibXML::InputCallback->new(); + $icb = $self->{XML_LIBXSLT_CALLBACK_STACK}; + } + + my $mcb = $self->match_callback(); + my $ocb = $self->open_callback(); + my $rcb = $self->read_callback(); + my $ccb = $self->close_callback(); + + if ( defined $mcb and defined $ocb and defined $rcb and defined $ccb ) { + $icb->register_callbacks( [$mcb, $ocb, $rcb, $ccb] ); + } + + $self->lib_init_callbacks(); + $icb->init_callbacks(); +} + +sub _cleanup_callbacks { + my $self = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK}->cleanup_callbacks(); + my $mcb = $self->match_callback(); + if ( defined $mcb ) { + $self->{XML_LIBXSLT_CALLBACK_STACK}->unregister_callbacks( [$mcb] ); + } +} + +sub parse_stylesheet { + my $self = shift; + + $self->_init_callbacks(); + + my $stylesheet; + eval { $stylesheet = $self->_parse_stylesheet(@_); }; + + $self->_cleanup_callbacks(); + + my $err = $@; + if ($err) { + croak $err; + } + + my $rv = { + XML_LIBXSLT_STYLESHEET => $stylesheet, + XML_LIBXSLT_CALLBACK_STACK => $self->{XML_LIBXSLT_CALLBACK_STACK}, + XML_LIBXSLT_MATCH_CB => $self->{XML_LIBXSLT_MATCH_CB}, + XML_LIBXSLT_OPEN_CB => $self->{XML_LIBXSLT_OPEN_CB}, + XML_LIBXSLT_READ_CB => $self->{XML_LIBXSLT_READ_CB}, + XML_LIBXSLT_CLOSE_CB => $self->{XML_LIBXSLT_CLOSE_CB}, + XML_LIBXSLT_SECPREFS => $self->{XML_LIBXSLT_SECPREFS}, + }; + + return bless $rv, "XML::LibXSLT::StylesheetWrapper"; +} + +sub parse_stylesheet_file { + my $self = shift; + + $self->_init_callbacks(); + + my $stylesheet; + eval { $stylesheet = $self->_parse_stylesheet_file(@_); }; + + $self->_cleanup_callbacks(); + + my $err = $@; + if ($err) { + croak $err; + } + + my $rv = { + XML_LIBXSLT_STYLESHEET => $stylesheet, + XML_LIBXSLT_CALLBACK_STACK => $self->{XML_LIBXSLT_CALLBACK_STACK}, + XML_LIBXSLT_MATCH_CB => $self->{XML_LIBXSLT_MATCH_CB}, + XML_LIBXSLT_OPEN_CB => $self->{XML_LIBXSLT_OPEN_CB}, + XML_LIBXSLT_READ_CB => $self->{XML_LIBXSLT_READ_CB}, + XML_LIBXSLT_CLOSE_CB => $self->{XML_LIBXSLT_CLOSE_CB}, + XML_LIBXSLT_SECPREFS => $self->{XML_LIBXSLT_SECPREFS}, + }; + + return bless $rv, "XML::LibXSLT::StylesheetWrapper"; +} + +sub register_xslt_module { + my $self = shift; + my $module = shift; + # Not implemented +} + +1; + +package XML::LibXSLT::StylesheetWrapper; + +use strict; +use vars qw($MatchCB $ReadCB $OpenCB $CloseCB); + +use XML::LibXML; +use Carp; + +sub security_callbacks { + my $self = shift; + my $scbclass = shift; + + if ( defined $scbclass ) { + $self->{XML_LIBXSLT_SECPREFS} = $scbclass; + } + return $self->{XML_LIBXSLT_SECPREFS}; +} + +sub input_callbacks { + my $self = shift; + my $icbclass = shift; + + if ( defined $icbclass ) { + $self->{XML_LIBXSLT_CALLBACK_STACK} = $icbclass; + } + return $self->{XML_LIBXSLT_CALLBACK_STACK}; +} + +sub match_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_MATCH_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_MATCH_CB}; + } + else { + $MatchCB = shift if scalar @_; + return $MatchCB; + } +} + +sub read_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_READ_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_READ_CB}; + } + else { + $ReadCB = shift if scalar @_; + return $ReadCB; + } +} + +sub close_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_CLOSE_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_CLOSE_CB}; + } + else { + $CloseCB = shift if scalar @_; + return $CloseCB; + } +} + +sub open_callback { + my $self = shift; + if ( ref $self ) { + if ( scalar @_ ) { + $self->{XML_LIBXSLT_OPEN_CB} = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + return $self->{XML_LIBXSLT_OPEN_CB}; + } + else { + $OpenCB = shift if scalar @_; + return $OpenCB; + } +} + +sub callbacks { + my $self = shift; + if ( ref $self ) { + if (@_) { + my ($match, $open, $read, $close) = @_; + @{$self}{qw(XML_LIBXSLT_MATCH_CB XML_LIBXSLT_OPEN_CB XML_LIBXSLT_READ_CB XML_LIBXSLT_CLOSE_CB)} = ($match, $open, $read, $close); + $self->{XML_LIBXSLT_CALLBACK_STACK} = undef; + } + else { + return @{$self}{qw(XML_LIBXSLT_MATCH_CB XML_LIBXSLT_OPEN_CB XML_LIBXSLT_READ_CB XML_LIBXSLT_CLOSE_CB)}; + } + } + else { + if (@_) { + ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ) = @_; + } + else { + return ( $MatchCB, $OpenCB, $ReadCB, $CloseCB ); + } + } +} + +sub _init_callbacks { + my $self = shift; + my $icb = $self->{XML_LIBXSLT_CALLBACK_STACK}; + + unless ( defined $icb ) { + $self->{XML_LIBXSLT_CALLBACK_STACK} = XML::LibXML::InputCallback->new(); + $icb = $self->{XML_LIBXSLT_CALLBACK_STACK}; + } + + my $mcb = $self->match_callback(); + my $ocb = $self->open_callback(); + my $rcb = $self->read_callback(); + my $ccb = $self->close_callback(); + + if ( defined $mcb and defined $ocb and defined $rcb and defined $ccb ) { + $icb->register_callbacks( [$mcb, $ocb, $rcb, $ccb] ); + } + $self->XML::LibXSLT::lib_init_callbacks(); + $icb->init_callbacks(); + + my $scb = $self->{XML_LIBXSLT_SECPREFS}; + if ( $scb ) { + $scb->init_callbacks(); + } +} + +sub _cleanup_callbacks { + my $self = shift; + $self->{XML_LIBXSLT_CALLBACK_STACK}->cleanup_callbacks(); + my $mcb = $self->match_callback(); + if ( defined $mcb ) { + $self->{XML_LIBXSLT_CALLBACK_STACK}->unregister_callbacks( [$mcb] ); + } + + my $scb = $self->{XML_LIBXSLT_SECPREFS}; + if ( $scb ) { + $scb->cleanup_callbacks(); + } +} + +sub transform { + my $self = shift; + my $doc; + + $self->_init_callbacks(); + eval { $doc = $self->{XML_LIBXSLT_STYLESHEET}->transform($self,@_); }; + $self->_cleanup_callbacks(); + + my $err = $@; + if ($err) { + croak $err; + } + + return $doc; +} + +sub transform_file { + my $self = shift; + my $doc; + + $self->_init_callbacks(); + eval { $doc = $self->{XML_LIBXSLT_STYLESHEET}->transform_file($self,@_); }; + $self->_cleanup_callbacks(); + + my $err = $@; + if ($err) { + croak $err; + } + + return $doc; +} + +sub output_string { shift->{XML_LIBXSLT_STYLESHEET}->_output_string($_[0],0) } +sub output_as_bytes { shift->{XML_LIBXSLT_STYLESHEET}->_output_string($_[0],1) } +sub output_as_chars { shift->{XML_LIBXSLT_STYLESHEET}->_output_string($_[0],2) } +sub output_fh { shift->{XML_LIBXSLT_STYLESHEET}->output_fh(@_) } +sub output_file { shift->{XML_LIBXSLT_STYLESHEET}->output_file(@_) } +sub media_type { shift->{XML_LIBXSLT_STYLESHEET}->media_type(@_) } +sub output_encoding { shift->{XML_LIBXSLT_STYLESHEET}->output_encoding(@_) } + +1; + +# XML::LibXSLT::Security Interface # +#-------------------------------------------------------------------------# +package XML::LibXSLT::Security; + +use strict; +use Carp; + +use vars qw(%OPTION_MAP %_GLOBAL_CALLBACKS); + +# Maps the option names used in the perl interface to the numeric values +# used by libxslt. +my %OPTION_MAP = ( + read_file => 1, + write_file => 2, + create_dir => 3, + read_net => 4, + write_net => 5, +); + +%_GLOBAL_CALLBACKS = (); + + +#-------------------------------------------------------------------------# +# global callback # +#-------------------------------------------------------------------------# +sub _security_check { + my $option = shift; + my $retval = 1; + + if ($option == 3) { + $retval = 0; # Default create_dir to no access + } + + if (exists $_GLOBAL_CALLBACKS{$option}) { + $retval = $_GLOBAL_CALLBACKS{$option}->(@_); + } + + return $retval; +} + +#-------------------------------------------------------------------------# +# member functions and methods # +#-------------------------------------------------------------------------# + +sub new { + my $class = shift; + return bless {'_CALLBACKS' => {}}, $class; +} + +# Add a callback for the given security option (read_file, write_file, +# create_dir, read_net, write_net). +# +# To register a callback that handle network read requests: +# $scb->register_callback( read_net => \&callback ); +sub register_callback { + my $self = shift; + my $option = shift; + my $callback = shift; + + unless ( exists $OPTION_MAP{$option} ) { + croak "Invalid security option '$option'. Must be one of: " . + join(', ', keys %OPTION_MAP) . "."; + } + + if ( ref $callback eq 'CODE' ) { + $self->{_CALLBACKS}{ $OPTION_MAP{$option} } = $callback; + } + else { + croak "Invalid argument. The callback must be a reference to a subroutine"; + } +} + +# Removes the callback for the given security option. Causes the given option +# to use the default security handler (which always allows the action). +sub unregister_callback { + my $self = shift; + my $option = shift; + + unless ( exists $OPTION_MAP{$option} ) { + croak "Invalid security option '$option'. Must be one of: " . + join(', ', keys %OPTION_MAP) . "."; + } + + delete $self->{_CALLBACKS}{ $OPTION_MAP{$option} }; +} + + +# make it so libxslt can use the callbacks +sub init_callbacks { + my $self = shift; + + %_GLOBAL_CALLBACKS = %{ $self->{_CALLBACKS} }; +} + +# reset libxslt callbacks +sub cleanup_callbacks { + my $self = shift; + + %_GLOBAL_CALLBACKS = (); +} + +1; + +__END__ + +=head1 NAME + +XML::LibXSLT - Interface to the gnome libxslt library + +=head1 SYNOPSIS + + use XML::LibXSLT; + use XML::LibXML; + + my $xslt = XML::LibXSLT->new(); + + my $source = XML::LibXML->load_xml(location => 'foo.xml'); + my $style_doc = XML::LibXML->load_xml(location=>'bar.xsl', no_cdata=>1); + + my $stylesheet = $xslt->parse_stylesheet($style_doc); + + my $results = $stylesheet->transform($source); + + print $stylesheet->output_as_bytes($results); + +=head1 DESCRIPTION + +This module is an interface to the gnome project's libxslt. This is an +extremely good XSLT engine, highly compliant and also very fast. I have +tests showing this to be more than twice as fast as Sablotron. + +=head1 OPTIONS + +XML::LibXSLT has some global options. Note that these are probably not +thread or even fork safe - so only set them once per process. Each one +of these options can be called either as class methods, or as instance +methods. However either way you call them, it still sets global options. + +Each of the option methods returns its previous value, and can be called +without a parameter to retrieve the current value. + +=over + +=item max_depth + + XML::LibXSLT->max_depth(1000); + +This option sets the maximum recursion depth for a stylesheet. See the +very end of section 5.4 of the XSLT specification for more details on +recursion and detecting it. If your stylesheet or XML file requires +seriously deep recursion, this is the way to set it. Default value is +250. + +=item debug_callback + + XML::LibXSLT->debug_callback($subref); + +Sets a callback to be used for debug messages. If you don't set this, +debug messages will be ignored. + +=item register_function + + XML::LibXSLT->register_function($uri, $name, $subref); + +Registers an XSLT extension function mapped to the given URI. For example: + + XML::LibXSLT->register_function("urn:foo", "bar", + sub { scalar localtime }); + +Will register a C<bar> function in the C<urn:foo> namespace (which you +have to define in your XSLT using C<xmlns:...>) that will return the +current date and time as a string: + + <xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:foo="urn:foo"> + <xsl:template match="/"> + The time is: <xsl:value-of select="foo:bar()"/> + </xsl:template> + </xsl:stylesheet> + +Parameters can be in whatever format you like. If you pass in a nodelist +it will be a XML::LibXML::NodeList object in your perl code, but ordinary +values (strings, numbers and booleans) will be ordinary perl scalars. If +you wish them to be C<XML::LibXML::Literal>, C<XML::LibXML::Number> and +C<XML::LibXML::Number> values respectively then set the variable +C<$XML::LibXSLT::USE_LIBXML_DATA_TYPES> to a true value. Return values can +be a nodelist or a plain value - the code will just do the right thing. +But only a single return value is supported (a list is not converted to +a nodelist). + +=back + +=head1 API + +The following methods are available on the new XML::LibXSLT object: + +=over + +=item parse_stylesheet($stylesheet_doc) + +C<$stylesheet_doc> here is an XML::LibXML::Document object (see L<XML::LibXML>) +representing an XSLT file. This method will return a +XML::LibXSLT::Stylesheet object, or undef on failure. If the XSLT is +invalid, an exception will be thrown, so wrap the call to +parse_stylesheet in an eval{} block to trap this. + +IMPORTANT: C<$stylesheet_doc> should not contain CDATA sections, +otherwise libxslt may misbehave. The best way to assure this is to +load the stylesheet with no_cdata flag, e.g. + + my $stylesheet_doc = XML::LibXML->load_xml(location=>"some.xsl", no_cdata=>1); + +=item parse_stylesheet_file($filename) + +Exactly the same as the above, but parses the given filename directly. + +=back + +=head1 Input Callbacks + +To define XML::LibXSLT or XML::LibXSLT::Stylesheet specific input +callbacks, reuse the XML::LibXML input callback API as described in +L<XML::LibXML::InputCallback(3)>. + +=head1 Security Callbacks + +To create security preferences for the transformation see +L<XML::LibXSLT::Security>. Once the security preferences have been defined you +can apply them to an XML::LibXSLT or XML::LibXSLT::Stylesheet instance using +the C<security_callbacks()> method. + +=head1 XML::LibXSLT::Stylesheet + +The main API is on the stylesheet, though it is fairly minimal. + +One of the main advantages of XML::LibXSLT is that you have a generic +stylesheet object which you call the transform() method passing in a +document to transform. This allows you to have multiple transformations +happen with one stylesheet without requiring a reparse. + +=over + +=item transform(doc, %params) + + my $results = $stylesheet->transform($doc, foo => "value); + print $stylesheet->output_as_bytes($results); + +Transforms the passed in XML::LibXML::Document object, and returns a +new XML::LibXML::Document. Extra hash entries are used as parameters. +See output_string + +=item transform_file(filename, %params) + + my $results = $stylesheet->transform_file($filename, bar => "value"); + +=item output_as_bytes(result) + +Returns a scalar that is the XSLT rendering of the +XML::LibXML::Document object using the desired output format +(specified in the xsl:output tag in the stylesheet). Note that you can +also call $result->toString, but that will *always* output the +document in XML format which may not be what you asked for in the +xsl:output tag. The scalar is a byte string encoded in the output +encoding specified in the stylesheet. + +=item output_as_chars(result) + +Like C<output_as_bytes(result)>, but always return the output as (UTF-8 +encoded) string of characters. + +=item output_string(result) + +DEPRECATED: This method is something between +C<output_as_bytes(result)> and C<output_as_bytes(result)>: The scalar +returned by this function appears to Perl as characters (UTF8 flag is +on) if the output encoding specified in the XSLT stylesheet was UTF-8 +and as bytes if no output encoding was specified or if the output +encoding was other than UTF-8. Since the behavior of this function +depends on the particular stylesheet, it is deprecated in favor of +C<output_as_bytes(result)> and C<output_as_chars(result)>. + +=item output_fh(result, fh) + +Outputs the result to the filehandle given in C<$fh>. + +=item output_file(result, filename) + +Outputs the result to the file named in C<$filename>. + +=item output_encoding() + +Returns the output encoding of the results. Defaults to "UTF-8". + +=item media_type() + +Returns the output media_type of the results. Defaults to "text/html". + +=back + +=head1 Parameters + +LibXSLT expects parameters in XPath format. That is, if you wish to pass +a string to the XSLT engine, you actually have to pass it as a quoted +string: + + $stylesheet->transform($doc, param => "'string'"); + +Note the quotes within quotes there! + +Obviously this isn't much fun, so you can make it easy on yourself: + + $stylesheet->transform($doc, XML::LibXSLT::xpath_to_string( + param => "string" + )); + +The utility function does the right thing with respect to strings in XPath, +including when you have quotes already embedded within your string. + + +=head1 XML::LibXSLT::Security + +Provides an interface to the libxslt security framework by allowing callbacks +to be defined that can restrict access to various resources (files or URLs) +during a transformation. + +The libxslt security framework allows callbacks to be defined for certain +actions that a stylesheet may attempt during a transformation. It may be +desirable to restrict some of these actions (for example, writing a new file +using exsl:document). The actions that may be restricted are: + +=over + +=item read_file + +Called when the stylesheet attempts to open a local file (ie: when using the +document() function). + +=item write_file + +Called when an attempt is made to write a local file (ie: when using the +exsl:document element). + +=item create_dir + +Called when a directory needs to be created in order to write a file. + +NOTE: By default, create_dir is not allowed. To enable it a callback must be +registered. + +=item read_net + +Called when the stylesheet attempts to read from the network. + +=item write_net + +Called when the stylesheet attempts to write to the network. + +=back + +=head2 Using XML::LibXSLT::Security + +The interface for this module is similar to XML::LibXML::InputCallback. After +creating a new instance you may register callbacks for each of the security +options listed above. Then you apply the security preferences to the +XML::LibXSLT or XML::LibXSLT::Stylesheet object using C<security_callbacks()>. + + my $security = XML::LibXSLT::Security->new(); + $security->register_callback( read_file => $read_cb ); + $security->register_callback( write_file => $write_cb ); + $security->register_callback( create_dir => $create_cb ); + $security->register_callback( read_net => $read_net_cb ); + $security->register_callback( write_net => $write_net_cb ); + + $xslt->security_callbacks( $security ); + -OR- + $stylesheet->security_callbacks( $security ); + + +The registered callback functions are called when access to a resource is +requested. If the access should be allowed the callback should return 1, if +not it should return 0. The callback functions should accept the following +arguments: + +=over + +=item $tctxt + +This is the transform context (XML::LibXSLT::TransformContext). You can use +this to get the current XML::LibXSLT::Stylesheet object by calling +C<stylesheet()>. + + my $stylesheet = $tctxt->stylesheet(); + +The stylesheet object can then be used to share contextual information between +different calls to the security callbacks. + +=item $value + +This is the name of the resource (file or URI) that has been requested. + +=back + +If a particular option (except for C<create_dir>) doesn't have a registered +callback, then the stylesheet will have full access for that action. + +=head2 Interface + +=over + +=item new() + +Creates a new XML::LibXSLT::Security object. + +=item register_callback( $option, $callback ) + +Registers a callback function for the given security option (listed above). + +=item unregister_callback( $option ) + +Removes the callback for the given option. This has the effect of allowing all +access for the given option (except for C<create_dir>). + +=back + +=head1 BENCHMARK + +Included in the distribution is a simple benchmark script, which has two +drivers - one for LibXSLT and one for Sablotron. The benchmark requires +the testcases files from the XSLTMark distribution which you can find +at http://www.datapower.com/XSLTMark/ + +Put the testcases directory in the directory created by this distribution, +and then run: + + perl benchmark.pl -h + +to get a list of options. + +The benchmark requires XML::XPath at the moment, but I hope to factor that +out of the equation fairly soon. It also requires Time::HiRes, which I +could be persuaded to factor out, replacing it with Benchmark.pm, but I +haven't done so yet. + +I would love to get drivers for XML::XSLT and XML::Transformiix, if you +would like to contribute them. Also if you get this running on Win32, I'd +love to get a driver for MSXSLT via OLE, to see what we can do against +those Redmond boys! + +=head1 LIBRARY VERSIONS + +For debugging purposes, XML::LibXSLT provides version information +about the libxslt C library (but do not confuse it with the version +number of XML::LibXSLT module itself, i.e. with +C<$XML::LibXSLT::VERSION>). XML::LibXSLT issues a warning if the +runtime version of the library is less then the compile-time version. + +=over + +=item XML::LibXSLT::LIBXSLT_VERSION() + +Returns version number of libxslt library which was used to compile +XML::LibXSLT as an integer. For example, for libxslt-1.1.18, it will +return 10118. + +=item XML::LibXSLT::LIBXSLT_DOTTED_VERSION() + +Returns version number of libxslt library which was used to compile +XML::LibXSLT as a string, e.g. "1.1.18". + +=item XML::LibXSLT::LIBXSLT_RUNTIME_VERSION() + +Returns version number of libxslt library to which XML::LibXSLT is +linked at runtime (either dynamically or statically). For example, for +example, for libxslt.so.1.1.18, it will return 10118. + +=item XML::LibXSLT::HAVE_EXLT() + +Returns 1 if the module was compiled with libexslt, 0 otherwised. + +=back + +=head1 LICENSE + +This is free software, you may use it and distribute it under the same terms as +Perl itself. + +Copyright 2001-2009, AxKit.com Ltd. + +=head1 AUTHOR + +Matt Sergeant, matt@sergeant.org + +Security callbacks implementation contributed by Shane Corgatelli. + +=head1 MAINTAINER + +Petr Pajas , pajas@matfyz.org + +=head1 BUGS + +Please report bugs via + + http://rt.cpan.org/NoAuth/Bugs.html?Dist=XML-LibXSLT + +=head1 SEE ALSO + +XML::LibXML + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/NamespaceSupport.pm b/Master/tlpkg/tlperl/lib/XML/NamespaceSupport.pm new file mode 100755 index 00000000000..0f57a578397 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/NamespaceSupport.pm @@ -0,0 +1,583 @@ + +### +# XML::NamespaceSupport - a simple generic namespace processor +# Robin Berjon <robin@knowscape.com> +### + +package XML::NamespaceSupport; +use strict; +use constant FATALS => 0; # root object +use constant NSMAP => 1; +use constant UNKNOWN_PREF => 2; +use constant AUTO_PREFIX => 3; +use constant XMLNS_11 => 4; +use constant DEFAULT => 0; # maps +use constant PREFIX_MAP => 1; +use constant DECLARATIONS => 2; + +use vars qw($VERSION $NS_XMLNS $NS_XML); +$VERSION = '1.10'; +$NS_XMLNS = 'http://www.w3.org/2000/xmlns/'; +$NS_XML = 'http://www.w3.org/XML/1998/namespace'; + + +# add the ns stuff that baud wants based on Java's xml-writer + + +#-------------------------------------------------------------------# +# constructor +#-------------------------------------------------------------------# +sub new { + my $class = ref($_[0]) ? ref(shift) : shift; + my $options = shift; + my $self = [ + 1, # FATALS + [[ # NSMAP + undef, # DEFAULT + { xml => $NS_XML }, # PREFIX_MAP + undef, # DECLARATIONS + ]], + 'aaa', # UNKNOWN_PREF + 0, # AUTO_PREFIX + 1, # XML_11 + ]; + $self->[NSMAP]->[0]->[PREFIX_MAP]->{xmlns} = $NS_XMLNS if $options->{xmlns}; + $self->[FATALS] = $options->{fatal_errors} if defined $options->{fatal_errors}; + $self->[AUTO_PREFIX] = $options->{auto_prefix} if defined $options->{auto_prefix}; + $self->[XMLNS_11] = $options->{xmlns_11} if defined $options->{xmlns_11}; + return bless $self, $class; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# reset() - return to the original state (for reuse) +#-------------------------------------------------------------------# +sub reset { + my $self = shift; + $#{$self->[NSMAP]} = 0; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# push_context() - add a new empty context to the stack +#-------------------------------------------------------------------# +sub push_context { + my $self = shift; + push @{$self->[NSMAP]}, [ + $self->[NSMAP]->[-1]->[DEFAULT], + { %{$self->[NSMAP]->[-1]->[PREFIX_MAP]} }, + [], + ]; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# pop_context() - remove the topmost context fromt the stack +#-------------------------------------------------------------------# +sub pop_context { + my $self = shift; + die 'Trying to pop context without push context' unless @{$self->[NSMAP]} > 1; + pop @{$self->[NSMAP]}; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# declare_prefix() - declare a prefix in the current scope +#-------------------------------------------------------------------# +sub declare_prefix { + my $self = shift; + my $prefix = shift; + my $value = shift; + + warn <<' EOWARN' unless defined $prefix or $self->[AUTO_PREFIX]; + Prefix was undefined. + If you wish to set the default namespace, use the empty string ''. + If you wish to autogenerate prefixes, set the auto_prefix option + to a true value. + EOWARN + + no warnings 'uninitialized'; + if ($prefix eq 'xml' and $value ne $NS_XML) { + die "The xml prefix can only be bound to the $NS_XML namespace." + } + elsif ($value eq $NS_XML and $prefix ne 'xml') { + die "the $NS_XML namespace can only be bound to the xml prefix."; + } + elsif ($value eq $NS_XML and $prefix eq 'xml') { + return 1; + } + return 0 if index(lc($prefix), 'xml') == 0; + use warnings 'uninitialized'; + + if (defined $prefix and $prefix eq '') { + $self->[NSMAP]->[-1]->[DEFAULT] = $value; + } + else { + die "Cannot undeclare prefix $prefix" if $value eq '' and not $self->[XMLNS_11]; + if (not defined $prefix and $self->[AUTO_PREFIX]) { + while (1) { + $prefix = $self->[UNKNOWN_PREF]++; + last if not exists $self->[NSMAP]->[-1]->[PREFIX_MAP]->{$prefix}; + } + } + elsif (not defined $prefix and not $self->[AUTO_PREFIX]) { + return 0; + } + $self->[NSMAP]->[-1]->[PREFIX_MAP]->{$prefix} = $value; + } + push @{$self->[NSMAP]->[-1]->[DECLARATIONS]}, $prefix; + return 1; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# declare_prefixes() - declare several prefixes in the current scope +#-------------------------------------------------------------------# +sub declare_prefixes { + my $self = shift; + my %prefixes = @_; + while (my ($k,$v) = each %prefixes) { + $self->declare_prefix($k,$v); + } +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# undeclare_prefix +#-------------------------------------------------------------------# +sub undeclare_prefix { + my $self = shift; + my $prefix = shift; + return unless not defined $prefix or $prefix eq ''; + return unless exists $self->[NSMAP]->[-1]->[PREFIX_MAP]->{$prefix}; + + my ( $tfix ) = grep { $_ eq $prefix } @{$self->[NSMAP]->[-1]->[DECLARATIONS]}; + if ( not defined $tfix ) { + die "prefix $prefix not declared in this context\n"; + } + + @{$self->[NSMAP]->[-1]->[DECLARATIONS]} = grep { $_ ne $prefix } @{$self->[NSMAP]->[-1]->[DECLARATIONS]}; + delete $self->[NSMAP]->[-1]->[PREFIX_MAP]->{$prefix}; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_prefix() - get a (random) prefix for a given URI +#-------------------------------------------------------------------# +sub get_prefix { + my $self = shift; + my $uri = shift; + + # we have to iterate over the whole hash here because if we don't + # the iterator isn't reset and the next pass will fail + my $pref; + while (my ($k, $v) = each %{$self->[NSMAP]->[-1]->[PREFIX_MAP]}) { + $pref = $k if $v eq $uri; + } + return $pref; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_prefixes() - get all the prefixes for a given URI +#-------------------------------------------------------------------# +sub get_prefixes { + my $self = shift; + my $uri = shift; + + return keys %{$self->[NSMAP]->[-1]->[PREFIX_MAP]} unless defined $uri; + return grep { $self->[NSMAP]->[-1]->[PREFIX_MAP]->{$_} eq $uri } keys %{$self->[NSMAP]->[-1]->[PREFIX_MAP]}; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_declared_prefixes() - get all prefixes declared in the last context +#-------------------------------------------------------------------# +sub get_declared_prefixes { + return @{$_[0]->[NSMAP]->[-1]->[DECLARATIONS]}; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_uri() - get an URI given a prefix +#-------------------------------------------------------------------# +sub get_uri { + my $self = shift; + my $prefix = shift; + + warn "Prefix must not be undef in get_uri(). The emtpy prefix must be ''" unless defined $prefix; + + return $self->[NSMAP]->[-1]->[DEFAULT] if $prefix eq ''; + return $self->[NSMAP]->[-1]->[PREFIX_MAP]->{$prefix} if exists $self->[NSMAP]->[-1]->[PREFIX_MAP]->{$prefix}; + return undef; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# process_name() - provide details on a name +#-------------------------------------------------------------------# +sub process_name { + my $self = shift; + my $qname = shift; + my $aflag = shift; + + if ($self->[FATALS]) { + return( ($self->_get_ns_details($qname, $aflag))[0,2], $qname ); + } + else { + eval { return( ($self->_get_ns_details($qname, $aflag))[0,2], $qname ); } + } +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# process_element_name() - provide details on a element's name +#-------------------------------------------------------------------# +sub process_element_name { + my $self = shift; + my $qname = shift; + + if ($self->[FATALS]) { + return $self->_get_ns_details($qname, 0); + } + else { + eval { return $self->_get_ns_details($qname, 0); } + } +} +#-------------------------------------------------------------------# + + +#-------------------------------------------------------------------# +# process_attribute_name() - provide details on a attribute's name +#-------------------------------------------------------------------# +sub process_attribute_name { + my $self = shift; + my $qname = shift; + + if ($self->[FATALS]) { + return $self->_get_ns_details($qname, 1); + } + else { + eval { return $self->_get_ns_details($qname, 1); } + } +} +#-------------------------------------------------------------------# + + +#-------------------------------------------------------------------# +# ($ns, $prefix, $lname) = $self->_get_ns_details($qname, $f_attr) +# returns ns, prefix, and lname for a given attribute name +# >> the $f_attr flag, if set to one, will work for an attribute +#-------------------------------------------------------------------# +sub _get_ns_details { + my $self = shift; + my $qname = shift; + my $aflag = shift; + + my ($ns, $prefix, $lname); + (my ($tmp_prefix, $tmp_lname) = split /:/, $qname, 3) + < 3 or die "Invalid QName: $qname"; + + # no prefix + my $cur_map = $self->[NSMAP]->[-1]; + if (not defined($tmp_lname)) { + $prefix = undef; + $lname = $qname; + # attr don't have a default namespace + $ns = ($aflag) ? undef : $cur_map->[DEFAULT]; + } + + # prefix + else { + if (exists $cur_map->[PREFIX_MAP]->{$tmp_prefix}) { + $prefix = $tmp_prefix; + $lname = $tmp_lname; + $ns = $cur_map->[PREFIX_MAP]->{$prefix} + } + else { # no ns -> lname == name, all rest undef + die "Undeclared prefix: $tmp_prefix"; + } + } + + return ($ns, $prefix, $lname); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# parse_jclark_notation() - parse the Clarkian notation +#-------------------------------------------------------------------# +sub parse_jclark_notation { + shift; + my $jc = shift; + $jc =~ m/^\{(.*)\}([^}]+)$/; + return $1, $2; +} +#-------------------------------------------------------------------# + + +#-------------------------------------------------------------------# +# Java names mapping +#-------------------------------------------------------------------# +*XML::NamespaceSupport::pushContext = \&push_context; +*XML::NamespaceSupport::popContext = \&pop_context; +*XML::NamespaceSupport::declarePrefix = \&declare_prefix; +*XML::NamespaceSupport::declarePrefixes = \&declare_prefixes; +*XML::NamespaceSupport::getPrefix = \&get_prefix; +*XML::NamespaceSupport::getPrefixes = \&get_prefixes; +*XML::NamespaceSupport::getDeclaredPrefixes = \&get_declared_prefixes; +*XML::NamespaceSupport::getURI = \&get_uri; +*XML::NamespaceSupport::processName = \&process_name; +*XML::NamespaceSupport::processElementName = \&process_element_name; +*XML::NamespaceSupport::processAttributeName = \&process_attribute_name; +*XML::NamespaceSupport::parseJClarkNotation = \&parse_jclark_notation; +*XML::NamespaceSupport::undeclarePrefix = \&undeclare_prefix; +#-------------------------------------------------------------------# + + +1; +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#`,`, Documentation `,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,`,# +#```````````````````````````````````````````````````````````````````# + +=pod + +=head1 NAME + +XML::NamespaceSupport - a simple generic namespace support class + +=head1 SYNOPSIS + + use XML::NamespaceSupport; + my $nsup = XML::NamespaceSupport->new; + + # add a new empty context + $nsup->push_context; + # declare a few prefixes + $nsup->declare_prefix($prefix1, $uri1); + $nsup->declare_prefix($prefix2, $uri2); + # the same shorter + $nsup->declare_prefixes($prefix1 => $uri1, $prefix2 => $uri2); + + # get a single prefix for a URI (randomly) + $prefix = $nsup->get_prefix($uri); + # get all prefixes for a URI (probably better) + @prefixes = $nsup->get_prefixes($uri); + # get all prefixes in scope + @prefixes = $nsup->get_prefixes(); + # get all prefixes that were declared for the current scope + @prefixes = $nsup->get_declared_prefixes; + # get a URI for a given prefix + $uri = $nsup->get_uri($prefix); + + # get info on a qname (java-ish way, it's a bit weird) + ($ns_uri, $local_name, $qname) = $nsup->process_name($qname, $is_attr); + # the same, more perlish + ($ns_uri, $prefix, $local_name) = $nsup->process_element_name($qname); + ($ns_uri, $prefix, $local_name) = $nsup->process_attribute_name($qname); + + # remove the current context + $nsup->pop_context; + + # reset the object for reuse in another document + $nsup->reset; + + # a simple helper to process Clarkian Notation + my ($ns, $lname) = $nsup->parse_jclark_notation('{http://foo}bar'); + # or (given that it doesn't care about the object + my ($ns, $lname) = XML::NamespaceSupport->parse_jclark_notation('{http://foo}bar'); + + +=head1 DESCRIPTION + +This module offers a simple to process namespaced XML names (unames) +from within any application that may need them. It also helps maintain +a prefix to namespace URI map, and provides a number of basic checks. + +The model for this module is SAX2's NamespaceSupport class, readable at +http://www.megginson.com/SAX/Java/javadoc/org/xml/sax/helpers/NamespaceSupport.html. +It adds a few perlisations where we thought it appropriate. + +=head1 METHODS + +=over 4 + +=item * XML::NamespaceSupport->new(\%options) + +A simple constructor. + +The options are C<xmlns>, C<fatal_errors>, and C<auto_prefix> + +If C<xmlns> is turned on (it is off by default) the mapping from the +xmlns prefix to the URI defined for it in DOM level 2 is added to the +list of predefined mappings (which normally only contains the xml +prefix mapping). + +If C<fatal_errors> is turned off (it is on by default) a number of +validity errors will simply be flagged as failures, instead of +die()ing. + +If C<auto_prefix> is turned on (it is off by default) when one +provides a prefix of C<undef> to C<declare_prefix> it will generate a +random prefix mapped to that namespace. Otherwise an undef prefix will +trigger a warning (you should probably know what you're doing if you +turn this option on). + +If C<xmlns_11> us turned off, it becomes illegal to undeclare namespace +prefixes. It is on by default. This behaviour is compliant with Namespaces +in XML 1.1, turning it off reverts you to version 1.0. + +=item * $nsup->push_context + +Adds a new empty context to the stack. You can then populate it with +new prefixes defined at this level. + +=item * $nsup->pop_context + +Removes the topmost context in the stack and reverts to the previous +one. It will die() if you try to pop more than you have pushed. + +=item * $nsup->declare_prefix($prefix, $uri) + +Declares a mapping of $prefix to $uri, at the current level. + +Note that with C<auto_prefix> turned on, if you declare a prefix +mapping in which $prefix is undef(), you will get an automatic prefix +selected for you. If it is off you will get a warning. + +This is useful when you deal with code that hasn't kept prefixes around +and need to reserialize the nodes. It also means that if you want to +set the default namespace (ie with an empty prefix) you must use the +empty string instead of undef. This behaviour is consistent with the +SAX 2.0 specification. + +=item * $nsup->declare_prefixes(%prefixes2uris) + +Declares a mapping of several prefixes to URIs, at the current level. + +=item * $nsup->get_prefix($uri) + +Returns a prefix given an URI. Note that as several prefixes may be +mapped to the same URI, it returns an arbitrary one. It'll return +undef on failure. + +=item * $nsup->get_prefixes($uri) + +Returns an array of prefixes given an URI. It'll return all the +prefixes if the uri is undef. + +=item * $nsup->get_declared_prefixes + +Returns an array of all the prefixes that have been declared within +this context, ie those that were declared on the last element, not +those that were declared above and are simply in scope. + +=item * $nsup->get_uri($prefix) + +Returns a URI for a given prefix. Returns undef on failure. + +=item * $nsup->process_name($qname, $is_attr) + +Given a qualified name and a boolean indicating whether this is an +attribute or another type of name (those are differently affected by +default namespaces), it returns a namespace URI, local name, qualified +name tuple. I know that that is a rather abnormal list to return, but +it is so for compatibility with the Java spec. See below for more +Perlish alternatives. + +If the prefix is not declared, or if the name is not valid, it'll +either die or return undef depending on the current setting of +C<fatal_errors>. + +=item * $nsup->undeclare_prefix($prefix); + +Removes a namespace prefix from the current context. This function may +be used in SAX's end_prefix_mapping when there is fear that a namespace +declaration might be available outside their scope (which shouldn't +normally happen, but you never know ;). This may be needed in order to +properly support Namespace 1.1. + +=item * $nsup->process_element_name($qname) + +Given a qualified name, it returns a namespace URI, prefix, and local +name tuple. This method applies to element names. + +If the prefix is not declared, or if the name is not valid, it'll +either die or return undef depending on the current setting of +C<fatal_errors>. + +=item * $nsup->process_attribute_name($qname) + +Given a qualified name, it returns a namespace URI, prefix, and local +name tuple. This method applies to attribute names. + +If the prefix is not declared, or if the name is not valid, it'll +either die or return undef depending on the current setting of +C<fatal_errors>. + +=item * $nsup->reset + +Resets the object so that it can be reused on another document. + +=back + +All methods of the interface have an alias that is the name used in +the original Java specification. You can use either name +interchangeably. Here is the mapping: + + Java name Perl name + --------------------------------------------------- + pushContext push_context + popContext pop_context + declarePrefix declare_prefix + declarePrefixes declare_prefixes + getPrefix get_prefix + getPrefixes get_prefixes + getDeclaredPrefixes get_declared_prefixes + getURI get_uri + processName process_name + processElementName process_element_name + processAttributeName process_attribute_name + parseJClarkNotation parse_jclark_notation + undeclarePrefix undeclare_prefix + +=head1 VARIABLES + +Two global variables are made available to you. They used to be constants but +simple scalars are easier to use in a number of contexts. They are not +exported but can easily be accessed from any package, or copied into it. + +=over 4 + +=item * C<$NS_XMLNS> + +The namespace for xmlns prefixes, http://www.w3.org/2000/xmlns/. + +=item * C<$NS_XML> + +The namespace for xml prefixes, http://www.w3.org/XML/1998/namespace. + +=back + +=head1 TODO + + - add more tests + - optimise here and there + +=head1 AUTHOR + +Robin Berjon, robin@knowscape.com, with lots of it having been done +by Duncan Cameron, and a number of suggestions from the perl-xml +list. + +=head1 COPYRIGHT + +Copyright (c) 2001-2005 Robin Berjon. All rights reserved. This program is +free software; you can redistribute it and/or modify it under the same terms +as Perl itself. + +=head1 SEE ALSO + +XML::Parser::PerlSAX + +=cut + diff --git a/Master/tlpkg/tlperl/lib/XML/Parser.pm b/Master/tlpkg/tlperl/lib/XML/Parser.pm new file mode 100755 index 00000000000..064b021ec5b --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser.pm @@ -0,0 +1,840 @@ +# XML::Parser +# +# Copyright (c) 1998-2000 Larry Wall and Clark Cooper +# All rights reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. + +package XML::Parser; + +use Carp; + +BEGIN { + require XML::Parser::Expat; + $VERSION = '2.36'; + die "Parser.pm and Expat.pm versions don't match" + unless $VERSION eq $XML::Parser::Expat::VERSION; +} + +use strict; + +use vars qw($VERSION $LWP_load_failed); + +$LWP_load_failed = 0; + +sub new { + my ($class, %args) = @_; + my $style = $args{Style}; + + my $nonexopt = $args{Non_Expat_Options} ||= {}; + + $nonexopt->{Style} = 1; + $nonexopt->{Non_Expat_Options} = 1; + $nonexopt->{Handlers} = 1; + $nonexopt->{_HNDL_TYPES} = 1; + $nonexopt->{NoLWP} = 1; + + $args{_HNDL_TYPES} = {%XML::Parser::Expat::Handler_Setters}; + $args{_HNDL_TYPES}->{Init} = 1; + $args{_HNDL_TYPES}->{Final} = 1; + + $args{Handlers} ||= {}; + my $handlers = $args{Handlers}; + + if (defined($style)) { + my $stylepkg = $style; + + if ($stylepkg !~ /::/) { + $stylepkg = "\u$style"; + + eval { + my $fullpkg = 'XML::Parser::Style::' . $stylepkg; + my $stylefile = $fullpkg; + $stylefile =~ s/::/\//g; + require "$stylefile.pm"; + $stylepkg = $fullpkg; + }; + if ($@) { + # fallback to old behaviour + $stylepkg = 'XML::Parser::' . $stylepkg; + } + } + + my $htype; + foreach $htype (keys %{$args{_HNDL_TYPES}}) { + # Handlers explicity given override + # handlers from the Style package + unless (defined($handlers->{$htype})) { + + # A handler in the style package must either have + # exactly the right case as the type name or a + # completely lower case version of it. + + my $hname = "${stylepkg}::$htype"; + if (defined(&$hname)) { + $handlers->{$htype} = \&$hname; + next; + } + + $hname = "${stylepkg}::\L$htype"; + if (defined(&$hname)) { + $handlers->{$htype} = \&$hname; + next; + } + } + } + } + + unless (defined($handlers->{ExternEnt}) + or defined ($handlers->{ExternEntFin})) { + + if ($args{NoLWP} or $LWP_load_failed) { + $handlers->{ExternEnt} = \&file_ext_ent_handler; + $handlers->{ExternEntFin} = \&file_ext_ent_cleanup; + } + else { + # The following just bootstraps the real LWP external entity + # handler + + $handlers->{ExternEnt} = \&initial_ext_ent_handler; + + # No cleanup function available until LWPExternEnt.pl loaded + } + } + + $args{Pkg} ||= caller; + bless \%args, $class; +} # End of new + +sub setHandlers { + my ($self, @handler_pairs) = @_; + + croak("Uneven number of arguments to setHandlers method") + if (int(@handler_pairs) & 1); + + my @ret; + while (@handler_pairs) { + my $type = shift @handler_pairs; + my $handler = shift @handler_pairs; + unless (defined($self->{_HNDL_TYPES}->{$type})) { + my @types = sort keys %{$self->{_HNDL_TYPES}}; + + croak("Unknown Parser handler type: $type\n Valid types: @types"); + } + push(@ret, $type, $self->{Handlers}->{$type}); + $self->{Handlers}->{$type} = $handler; + } + + return @ret; +} + +sub parse_start { + my $self = shift; + my @expat_options = (); + + my ($key, $val); + while (($key, $val) = each %{$self}) { + push (@expat_options, $key, $val) + unless exists $self->{Non_Expat_Options}->{$key}; + } + + my %handlers = %{$self->{Handlers}}; + my $init = delete $handlers{Init}; + my $final = delete $handlers{Final}; + + my $expatnb = new XML::Parser::ExpatNB(@expat_options, @_); + $expatnb->setHandlers(%handlers); + + &$init($expatnb) + if defined($init); + + $expatnb->{_State_} = 1; + + $expatnb->{FinalHandler} = $final + if defined($final); + + return $expatnb; +} + +sub parse { + my $self = shift; + my $arg = shift; + my @expat_options = (); + my ($key, $val); + while (($key, $val) = each %{$self}) { + push(@expat_options, $key, $val) + unless exists $self->{Non_Expat_Options}->{$key}; + } + + my $expat = new XML::Parser::Expat(@expat_options, @_); + my %handlers = %{$self->{Handlers}}; + my $init = delete $handlers{Init}; + my $final = delete $handlers{Final}; + + $expat->setHandlers(%handlers); + + if ($self->{Base}) { + $expat->base($self->{Base}); + } + + &$init($expat) + if defined($init); + + my @result = (); + my $result; + eval { + $result = $expat->parse($arg); + }; + my $err = $@; + if ($err) { + $expat->release; + die $err; + } + + if ($result and defined($final)) { + if (wantarray) { + @result = &$final($expat); + } + else { + $result = &$final($expat); + } + } + + $expat->release; + + return unless defined wantarray; + return wantarray ? @result : $result; +} + +sub parsestring { + my $self = shift; + $self->parse(@_); +} + +sub parsefile { + my $self = shift; + my $file = shift; + local(*FILE); + open(FILE, $file) or croak "Couldn't open $file:\n$!"; + binmode(FILE); + my @ret; + my $ret; + + $self->{Base} = $file; + + if (wantarray) { + eval { + @ret = $self->parse(*FILE, @_); + }; + } + else { + eval { + $ret = $self->parse(*FILE, @_); + }; + } + my $err = $@; + close(FILE); + die $err if $err; + + return unless defined wantarray; + return wantarray ? @ret : $ret; +} + +sub initial_ext_ent_handler { + # This just bootstraps in the real lwp_ext_ent_handler which + # also loads the URI and LWP modules. + + unless ($LWP_load_failed) { + local($^W) = 0; + + my $stat = + eval { + require('XML/Parser/LWPExternEnt.pl'); + }; + + if ($stat) { + $_[0]->setHandlers(ExternEnt => \&lwp_ext_ent_handler, + ExternEntFin => \&lwp_ext_ent_cleanup); + + goto &lwp_ext_ent_handler; + } + + # Failed to load lwp handler, act as if NoLWP + + $LWP_load_failed = 1; + + my $cmsg = "Couldn't load LWP based external entity handler\n"; + $cmsg .= "Switching to file-based external entity handler\n"; + $cmsg .= " (To avoid this message, use NoLWP option to XML::Parser)\n"; + warn($cmsg); + } + + $_[0]->setHandlers(ExternEnt => \&file_ext_ent_handler, + ExternEntFin => \&file_ext_ent_cleanup); + goto &file_ext_ent_handler; + +} + +sub file_ext_ent_handler { + my ($xp, $base, $path) = @_; + + # Prepend base only for relative paths + + if (defined($base) + and not ($path =~ m!^(?:[\\/]|\w+:)!)) + { + my $newpath = $base; + $newpath =~ s![^\\/:]*$!$path!; + $path = $newpath; + } + + if ($path =~ /^\s*[|>+]/ + or $path =~ /\|\s*$/) { + $xp->{ErrorMessage} + .= "System ID ($path) contains Perl IO control characters"; + return undef; + } + + require IO::File; + my $fh = new IO::File($path); + unless (defined $fh) { + $xp->{ErrorMessage} + .= "Failed to open $path:\n$!"; + return undef; + } + + $xp->{_BaseStack} ||= []; + $xp->{_FhStack} ||= []; + + push(@{$xp->{_BaseStack}}, $base); + push(@{$xp->{_FhStack}}, $fh); + + $xp->base($path); + + return $fh; +} + +sub file_ext_ent_cleanup { + my ($xp) = @_; + + my $fh = pop(@{$xp->{_FhStack}}); + $fh->close; + + my $base = pop(@{$xp->{_BaseStack}}); + $xp->base($base); +} + +1; + +__END__ + +=head1 NAME + +XML::Parser - A perl module for parsing XML documents + +=head1 SYNOPSIS + + use XML::Parser; + + $p1 = new XML::Parser(Style => 'Debug'); + $p1->parsefile('REC-xml-19980210.xml'); + $p1->parse('<foo id="me">Hello World</foo>'); + + # Alternative + $p2 = new XML::Parser(Handlers => {Start => \&handle_start, + End => \&handle_end, + Char => \&handle_char}); + $p2->parse($socket); + + # Another alternative + $p3 = new XML::Parser(ErrorContext => 2); + + $p3->setHandlers(Char => \&text, + Default => \&other); + + open(FOO, 'xmlgenerator |'); + $p3->parse(*FOO, ProtocolEncoding => 'ISO-8859-1'); + close(FOO); + + $p3->parsefile('junk.xml', ErrorContext => 3); + +=begin man +.ds PI PI + +=end man + +=head1 DESCRIPTION + +This module provides ways to parse XML documents. It is built on top of +L<XML::Parser::Expat>, which is a lower level interface to James Clark's +expat library. Each call to one of the parsing methods creates a new +instance of XML::Parser::Expat which is then used to parse the document. +Expat options may be provided when the XML::Parser object is created. +These options are then passed on to the Expat object on each parse call. +They can also be given as extra arguments to the parse methods, in which +case they override options given at XML::Parser creation time. + +The behavior of the parser is controlled either by C<L</Style>> and/or +C<L</Handlers>> options, or by L</setHandlers> method. These all provide +mechanisms for XML::Parser to set the handlers needed by XML::Parser::Expat. +If neither C<Style> nor C<Handlers> are specified, then parsing just +checks the document for being well-formed. + +When underlying handlers get called, they receive as their first parameter +the I<Expat> object, not the Parser object. + +=head1 METHODS + +=over 4 + +=item new + +This is a class method, the constructor for XML::Parser. Options are passed +as keyword value pairs. Recognized options are: + +=over 4 + +=item * Style + +This option provides an easy way to create a given style of parser. The +built in styles are: L<"Debug">, L<"Subs">, L<"Tree">, L<"Objects">, +and L<"Stream">. These are all defined in separate packages under +C<XML::Parser::Style::*>, and you can find further documentation for +each style both below, and in those packages. + +Custom styles can be provided by giving a full package name containing +at least one '::'. This package should then have subs defined for each +handler it wishes to have installed. See L<"STYLES"> below +for a discussion of each built in style. + +=item * Handlers + +When provided, this option should be an anonymous hash containing as +keys the type of handler and as values a sub reference to handle that +type of event. All the handlers get passed as their 1st parameter the +instance of expat that is parsing the document. Further details on +handlers can be found in L<"HANDLERS">. Any handler set here +overrides the corresponding handler set with the Style option. + +=item * Pkg + +Some styles will refer to subs defined in this package. If not provided, +it defaults to the package which called the constructor. + +=item * ErrorContext + +This is an Expat option. When this option is defined, errors are reported +in context. The value should be the number of lines to show on either side +of the line in which the error occurred. + +=item * ProtocolEncoding + +This is an Expat option. This sets the protocol encoding name. It defaults +to none. The built-in encodings are: C<UTF-8>, C<ISO-8859-1>, C<UTF-16>, and +C<US-ASCII>. Other encodings may be used if they have encoding maps in one +of the directories in the @Encoding_Path list. Check L<"ENCODINGS"> for +more information on encoding maps. Setting the protocol encoding overrides +any encoding in the XML declaration. + +=item * Namespaces + +This is an Expat option. If this is set to a true value, then namespace +processing is done during the parse. See L<XML::Parser::Expat/"Namespaces"> +for further discussion of namespace processing. + +=item * NoExpand + +This is an Expat option. Normally, the parser will try to expand references +to entities defined in the internal subset. If this option is set to a true +value, and a default handler is also set, then the default handler will be +called when an entity reference is seen in text. This has no effect if a +default handler has not been registered, and it has no effect on the expansion +of entity references inside attribute values. + +=item * Stream_Delimiter + +This is an Expat option. It takes a string value. When this string is found +alone on a line while parsing from a stream, then the parse is ended as if it +saw an end of file. The intended use is with a stream of xml documents in a +MIME multipart format. The string should not contain a trailing newline. + +=item * ParseParamEnt + +This is an Expat option. Unless standalone is set to "yes" in the XML +declaration, setting this to a true value allows the external DTD to be read, +and parameter entities to be parsed and expanded. + +=item * NoLWP + +This option has no effect if the ExternEnt or ExternEntFin handlers are +directly set. Otherwise, if true, it forces the use of a file based external +entity handler. + +=item * Non-Expat-Options + +If provided, this should be an anonymous hash whose keys are options that +shouldn't be passed to Expat. This should only be of concern to those +subclassing XML::Parser. + +=back + +=item setHandlers(TYPE, HANDLER [, TYPE, HANDLER [...]]) + +This method registers handlers for various parser events. It overrides any +previous handlers registered through the Style or Handler options or through +earlier calls to setHandlers. By providing a false or undefined value as +the handler, the existing handler can be unset. + +This method returns a list of type, handler pairs corresponding to the +input. The handlers returned are the ones that were in effect prior to +the call. + +See a description of the handler types in L<"HANDLERS">. + +=item parse(SOURCE [, OPT => OPT_VALUE [...]]) + +The SOURCE parameter should either be a string containing the whole XML +document, or it should be an open IO::Handle. Constructor options to +XML::Parser::Expat given as keyword-value pairs may follow the SOURCE +parameter. These override, for this call, any options or attributes passed +through from the XML::Parser instance. + +A die call is thrown if a parse error occurs. Otherwise it will return 1 +or whatever is returned from the B<Final> handler, if one is installed. +In other words, what parse may return depends on the style. + +=item parsestring + +This is just an alias for parse for backwards compatibility. + +=item parsefile(FILE [, OPT => OPT_VALUE [...]]) + +Open FILE for reading, then call parse with the open handle. The file +is closed no matter how parse returns. Returns what parse returns. + +=item parse_start([ OPT => OPT_VALUE [...]]) + +Create and return a new instance of XML::Parser::ExpatNB. Constructor +options may be provided. If an init handler has been provided, it is +called before returning the ExpatNB object. Documents are parsed by +making incremental calls to the parse_more method of this object, which +takes a string. A single call to the parse_done method of this object, +which takes no arguments, indicates that the document is finished. + +If there is a final handler installed, it is executed by the parse_done +method before returning and the parse_done method returns whatever is +returned by the final handler. + +=back + +=head1 HANDLERS + +Expat is an event based parser. As the parser recognizes parts of the +document (say the start or end tag for an XML element), then any handlers +registered for that type of an event are called with suitable parameters. +All handlers receive an instance of XML::Parser::Expat as their first +argument. See L<XML::Parser::Expat/"METHODS"> for a discussion of the +methods that can be called on this object. + +=head2 Init (Expat) + +This is called just before the parsing of the document starts. + +=head2 Final (Expat) + +This is called just after parsing has finished, but only if no errors +occurred during the parse. Parse returns what this returns. + +=head2 Start (Expat, Element [, Attr, Val [,...]]) + +This event is generated when an XML start tag is recognized. Element is the +name of the XML element type that is opened with the start tag. The Attr & +Val pairs are generated for each attribute in the start tag. + +=head2 End (Expat, Element) + +This event is generated when an XML end tag is recognized. Note that +an XML empty tag (<foo/>) generates both a start and an end event. + +=head2 Char (Expat, String) + +This event is generated when non-markup is recognized. The non-markup +sequence of characters is in String. A single non-markup sequence of +characters may generate multiple calls to this handler. Whatever the +encoding of the string in the original document, this is given to the +handler in UTF-8. + +=head2 Proc (Expat, Target, Data) + +This event is generated when a processing instruction is recognized. + +=head2 Comment (Expat, Data) + +This event is generated when a comment is recognized. + +=head2 CdataStart (Expat) + +This is called at the start of a CDATA section. + +=head2 CdataEnd (Expat) + +This is called at the end of a CDATA section. + +=head2 Default (Expat, String) + +This is called for any characters that don't have a registered handler. +This includes both characters that are part of markup for which no +events are generated (markup declarations) and characters that +could generate events, but for which no handler has been registered. + +Whatever the encoding in the original document, the string is returned to +the handler in UTF-8. + +=head2 Unparsed (Expat, Entity, Base, Sysid, Pubid, Notation) + +This is called for a declaration of an unparsed entity. Entity is the name +of the entity. Base is the base to be used for resolving a relative URI. +Sysid is the system id. Pubid is the public id. Notation is the notation +name. Base and Pubid may be undefined. + +=head2 Notation (Expat, Notation, Base, Sysid, Pubid) + +This is called for a declaration of notation. Notation is the notation name. +Base is the base to be used for resolving a relative URI. Sysid is the system +id. Pubid is the public id. Base, Sysid, and Pubid may all be undefined. + +=head2 ExternEnt (Expat, Base, Sysid, Pubid) + +This is called when an external entity is referenced. Base is the base to be +used for resolving a relative URI. Sysid is the system id. Pubid is the public +id. Base, and Pubid may be undefined. + +This handler should either return a string, which represents the contents of +the external entity, or return an open filehandle that can be read to obtain +the contents of the external entity, or return undef, which indicates the +external entity couldn't be found and will generate a parse error. + +If an open filehandle is returned, it must be returned as either a glob +(*FOO) or as a reference to a glob (e.g. an instance of IO::Handle). + +A default handler is installed for this event. The default handler is +XML::Parser::lwp_ext_ent_handler unless the NoLWP option was provided with +a true value, otherwise XML::Parser::file_ext_ent_handler is the default +handler for external entities. Even without the NoLWP option, if the +URI or LWP modules are missing, the file based handler ends up being used +after giving a warning on the first external entity reference. + +The LWP external entity handler will use proxies defined in the environment +(http_proxy, ftp_proxy, etc.). + +Please note that the LWP external entity handler reads the entire +entity into a string and returns it, where as the file handler opens a +filehandle. + +Also note that the file external entity handler will likely choke on +absolute URIs or file names that don't fit the conventions of the local +operating system. + +The expat base method can be used to set a basename for +relative pathnames. If no basename is given, or if the basename is itself +a relative name, then it is relative to the current working directory. + +=head2 ExternEntFin (Expat) + +This is called after parsing an external entity. It's not called unless +an ExternEnt handler is also set. There is a default handler installed +that pairs with the default ExternEnt handler. + +If you're going to install your own ExternEnt handler, then you should +set (or unset) this handler too. + +=head2 Entity (Expat, Name, Val, Sysid, Pubid, Ndata, IsParam) + +This is called when an entity is declared. For internal entities, the Val +parameter will contain the value and the remaining three parameters will be +undefined. For external entities, the Val parameter will be undefined, the +Sysid parameter will have the system id, the Pubid parameter will have the +public id if it was provided (it will be undefined otherwise), the Ndata +parameter will contain the notation for unparsed entities. If this is a +parameter entity declaration, then the IsParam parameter is true. + +Note that this handler and the Unparsed handler above overlap. If both are +set, then this handler will not be called for unparsed entities. + +=head2 Element (Expat, Name, Model) + +The element handler is called when an element declaration is found. Name +is the element name, and Model is the content model as an XML::Parser::Content +object. See L<XML::Parser::Expat/"XML::Parser::ContentModel Methods"> +for methods available for this class. + +=head2 Attlist (Expat, Elname, Attname, Type, Default, Fixed) + +This handler is called for each attribute in an ATTLIST declaration. +So an ATTLIST declaration that has multiple attributes will generate multiple +calls to this handler. The Elname parameter is the name of the element with +which the attribute is being associated. The Attname parameter is the name +of the attribute. Type is the attribute type, given as a string. Default is +the default value, which will either be "#REQUIRED", "#IMPLIED" or a quoted +string (i.e. the returned string will begin and end with a quote character). +If Fixed is true, then this is a fixed attribute. + +=head2 Doctype (Expat, Name, Sysid, Pubid, Internal) + +This handler is called for DOCTYPE declarations. Name is the document type +name. Sysid is the system id of the document type, if it was provided, +otherwise it's undefined. Pubid is the public id of the document type, +which will be undefined if no public id was given. Internal is the internal +subset, given as a string. If there was no internal subset, it will be +undefined. Internal will contain all whitespace, comments, processing +instructions, and declarations seen in the internal subset. The declarations +will be there whether or not they have been processed by another handler +(except for unparsed entities processed by the Unparsed handler). However, +comments and processing instructions will not appear if they've been processed +by their respective handlers. + +=head2 * DoctypeFin (Parser) + +This handler is called after parsing of the DOCTYPE declaration has finished, +including any internal or external DTD declarations. + +=head2 XMLDecl (Expat, Version, Encoding, Standalone) + +This handler is called for xml declarations. Version is a string containg +the version. Encoding is either undefined or contains an encoding string. +Standalone will be either true, false, or undefined if the standalone attribute +is yes, no, or not made respectively. + +=head1 STYLES + +=head2 Debug + +This just prints out the document in outline form. Nothing special is +returned by parse. + +=head2 Subs + +Each time an element starts, a sub by that name in the package specified +by the Pkg option is called with the same parameters that the Start +handler gets called with. + +Each time an element ends, a sub with that name appended with an underscore +("_"), is called with the same parameters that the End handler gets called +with. + +Nothing special is returned by parse. + +=head2 Tree + +Parse will return a parse tree for the document. Each node in the tree +takes the form of a tag, content pair. Text nodes are represented with +a pseudo-tag of "0" and the string that is their content. For elements, +the content is an array reference. The first item in the array is a +(possibly empty) hash reference containing attributes. The remainder of +the array is a sequence of tag-content pairs representing the content +of the element. + +So for example the result of parsing: + + <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo> + +would be: + + Tag Content + ================================================================== + [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], + bar, [ {}, 0, "Howdy", ref, [{}]], + 0, "do" + ] + ] + +The root document "foo", has 3 children: a "head" element, a "bar" +element and the text "do". After the empty attribute hash, these are +represented in it's contents by 3 tag-content pairs. + +=head2 Objects + +This is similar to the Tree style, except that a hash object is created for +each element. The corresponding object will be in the class whose name +is created by appending "::" and the element name to the package set with +the Pkg option. Non-markup text will be in the ::Characters class. The +contents of the corresponding object will be in an anonymous array that +is the value of the Kids property for that object. + +=head2 Stream + +This style also uses the Pkg package. If none of the subs that this +style looks for is there, then the effect of parsing with this style is +to print a canonical copy of the document without comments or declarations. +All the subs receive as their 1st parameter the Expat instance for the +document they're parsing. + +It looks for the following routines: + +=over 4 + +=item * StartDocument + +Called at the start of the parse . + +=item * StartTag + +Called for every start tag with a second parameter of the element type. The $_ +variable will contain a copy of the tag and the %_ variable will contain +attribute values supplied for that element. + +=item * EndTag + +Called for every end tag with a second parameter of the element type. The $_ +variable will contain a copy of the end tag. + +=item * Text + +Called just before start or end tags with accumulated non-markup text in +the $_ variable. + +=item * PI + +Called for processing instructions. The $_ variable will contain a copy of +the PI and the target and data are sent as 2nd and 3rd parameters +respectively. + +=item * EndDocument + +Called at conclusion of the parse. + +=back + +=head1 ENCODINGS + +XML documents may be encoded in character sets other than Unicode as +long as they may be mapped into the Unicode character set. Expat has +further restrictions on encodings. Read the xmlparse.h header file in +the expat distribution to see details on these restrictions. + +Expat has built-in encodings for: C<UTF-8>, C<ISO-8859-1>, C<UTF-16>, and +C<US-ASCII>. Encodings are set either through the XML declaration +encoding attribute or through the ProtocolEncoding option to XML::Parser +or XML::Parser::Expat. + +For encodings other than the built-ins, expat calls the function +load_encoding in the Expat package with the encoding name. This function +looks for a file in the path list @XML::Parser::Expat::Encoding_Path, that +matches the lower-cased name with a '.enc' extension. The first one it +finds, it loads. + +If you wish to build your own encoding maps, check out the XML::Encoding +module from CPAN. + +=head1 AUTHORS + +Larry Wall <F<larry@wall.org>> wrote version 1.0. + +Clark Cooper <F<coopercc@netheaven.com>> picked up support, changed the API +for this version (2.x), provided documentation, +and added some standard package features. + +Matt Sergeant <F<matt@sergeant.org>> is now maintaining XML::Parser + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/Japanese_Encodings.msg b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/Japanese_Encodings.msg new file mode 100755 index 00000000000..6912e702264 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/Japanese_Encodings.msg @@ -0,0 +1,117 @@ +Mapping files for Japanese encodings + +1998 12/25 + +Fuji Xerox Information Systems +MURATA Makoto + +1. Overview + +This version of XML::Parser and XML::Encoding does not come with map files for +the charset "Shift_JIS" and the charset "euc-jp". Unfortunately, each of these +charsets has more than one mapping. None of these mappings are +considered as authoritative. + +Therefore, we have come to believe that it is dangerous to provide map files +for these charsets. Rather, we introduce several private charsets and map +files for these private charsets. If IANA, Unicode Consoritum, and JIS +eventually reach a consensus, we will be able to provide map files for +"Shift_JIS" and "euc-jp". + +2. Different mappings from existing charsets to Unicode + +1) Different mappings in JIS X0221 and Unicode + +The mapping between JIS X0208:1990 and Unicode 1.1 and the mapping +between JIS X0212:1990 and Unicode 1.1 are published from Unicode +consortium. They are available at +ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/JIS0208.TXT and +ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/JIS0212.TXT, +respectively.) These mapping files have a note as below: + +# The kanji mappings are a normative part of ISO/IEC 10646. The +# non-kanji mappings are provisional, pending definition of +# official mappings by Japanese standards bodies. + +Unfortunately, the non-kanji mappings in the Japanese standard for ISO 10646/1, +namely JIS X 0221:1995, is different from the Unicode Consortium mapping since +0x213D of JIS X 0208 is mapped to U+2014 (em dash) rather than U+2015 +(horizontal bar). Furthermore, JIS X 0221 clearly says that the mapping is +informational and non-normative. As a result, some companies (e.g., Microsoft and +Apple) have introduced slightly different mappings. Therefore, neither the +Unicode consortium mapping nor the JIS X 0221 mapping are considered as +authoritative. + +2) Shift-JIS + +This charset is especially problematic, since its definition has been unclear +since its inception. + +The current registration of the charset "Shift_JIS" is as below: + +>Name: Shift_JIS (preferred MIME name) +>MIBenum: 17 +>Source: A Microsoft code that extends csHalfWidthKatakana to include +> kanji by adding a second byte when the value of the first +> byte is in the ranges 81-9F or E0-EF. +>Alias: MS_Kanji +>Alias: csShiftJIS + +First, this does not reference to the mapping "Shift-JIS to Unicode" +published by the Unicode consortium (available at +ftp://ftp.unicode.org/Public/MAPPINGS/EASTASIA/JIS/SHIFTJIS.TXT). + +Second, "kanji" in this registration can be interepreted in different ways. +Does this "kanji" reference to JIS X0208:1978, JIS X0208:1983, or JIS +X0208:1990(== JIS X0208:1997)? These three standards are *incompatible* with +each other. Moreover, we can even argue that "kanji" refers to JIS X0212 or +ideographic characters in other countries. + +Third, each company has extended Shift JIS. For example, Microsoft introduced +OEM extensions (NEC extensionsand IBM extensions). + +Forth, Shift JIS uses JIS X0201, which is almost upper-compatible with US-ASCII +but is not quite. 5C and 7E of JIS X 0201 are different from backslash and +tilde, respectively. However, many programming languages (e.g., Java) +ignore this difference and assumes that 5C and 7E of Shift JIS are backslash +and tilde. + + +3. Proposed charsets and mappings + +As a tentative solution, we introduce two private charsets for EUC-JP and four +priviate charsets for Shift JIS. + +1) EUC-JP + +We have two charsets, namely "x-eucjp-unicode" and "x-eucjp-jisx0221". Their +difference is only one code point. The mapping for the former is based +on the Unicode Consortium mapping, while the latter is based on the JIS X0221 +mapping. + +2) Shift JIS + +We have four charsets, namely x-sjis-unicode, x-sjis-jisx0221, +x-sjis-jdk117, and x-sjis-cp932. + +The mapping for the charset x-sjis-unicode is the one published by the Unicode +consortium. The mapping for x-sjis-jisx0221 is almost equivalent to +x-sjis-unicode, but 0x213D of JIS X 0208 is mapped to U+2014 (em dash) rather +than U+2015. The charset x-sjis-jdk117 is again almost equivalent to +x-sjis-unicode, but 0x5C and 0x7E of JIS X0201 are mapped to backslash and +tilde. + +The charset x-sjis-cp932 is used by Microsoft Windows, and its mapping is +published from the Unicode Consortium (available at: +ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.txt). The +coded character set for this charset includes NEC-extensions and +IBM-extensions. 0x5C and 0x7E of JIS X0201 are mapped to backslash and tilde; +0x213D is mapped to U+2015; and 0x2140, 0x2141, 0x2142, and 0x215E of JIS X +0208 are mapped to compatibility characters. + +Makoto + +Fuji Xerox Information Systems + +Tel: +81-44-812-7230 Fax: +81-44-812-7231 +E-mail: murata@apsdc.ksp.fujixerox.co.jp diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/README b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/README new file mode 100755 index 00000000000..576323c8225 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/README @@ -0,0 +1,51 @@ +This directory contains binary encoding maps for some selected encodings. +If they are placed in a directoy listed in @XML::Parser::Expat::Encoding_Path, +then they are automaticly loaded by the XML::Parser::Expat::load_encoding +function as needed. Otherwise you may load what you need directly by +explicity calling this function. + +These maps were generated by a perl script that comes with the module +XML::Encoding, compile_encoding, from XML formatted encoding maps that +are distributed with that module. These XML encoding maps were generated +in turn with a different script, domap, from mapping information contained +on the Unicode version 2.0 CD-ROM. This CD-ROM comes with the Unicode +Standard reference manual and can be ordered from the Unicode Consortium +at http://www.unicode.org. The identical information is available on the +internet at ftp://ftp.unicode.org/Public/MAPPINGS. + +See the encoding.h header in the Expat sub-directory for a description of +the structure of these files. + +Clark Cooper +December 12, 1998 + +================================================================ + +Contributed maps + +This distribution contains four contributed encodings from MURATA Makoto +<murata@apsdc.ksp.fujixerox.co.jp> that are variations on the encoding +commonly called Shift_JIS: + +x-sjis-cp932.enc +x-sjis-jdk117.enc +x-sjis-jisx0221.enc +x-sjis-unicode.enc (This is the same encoding as the shift_jis.enc that + was distributed with this module in version 2.17) + +Please read his message (Japanese_Encodings.msg) about why these are here +and why I've removed the shift_jis.enc encoding. + +We also have two contributed encodings that are variations of the EUC-JP +encoding from Yoshida Masato <yoshidam@inse.co.jp>: + +x-euc-jp-jisx0221.enc +x-euc-jp-unicode.enc + +The comments that MURATA Makoto made in his message apply to these +encodings too. + +KangChan Lee <dolphin@comeng.chungnam.ac.kr> supplied the euc-kr encoding. + +Clark Cooper +December 26, 1998 diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/big5.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/big5.enc Binary files differnew file mode 100755 index 00000000000..94b2bd4bf40 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/big5.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/euc-kr.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/euc-kr.enc Binary files differnew file mode 100755 index 00000000000..3da8a13f3c3 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/euc-kr.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-2.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-2.enc Binary files differnew file mode 100755 index 00000000000..d320d7f8bc9 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-2.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-3.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-3.enc Binary files differnew file mode 100755 index 00000000000..ba4837852e9 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-3.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-4.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-4.enc Binary files differnew file mode 100755 index 00000000000..0294a24089c --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-4.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-5.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-5.enc Binary files differnew file mode 100755 index 00000000000..6dbd1692c4b --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-5.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-7.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-7.enc Binary files differnew file mode 100755 index 00000000000..02a4aee1c7b --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-7.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-8.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-8.enc Binary files differnew file mode 100755 index 00000000000..f211bd52342 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-8.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-9.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-9.enc Binary files differnew file mode 100755 index 00000000000..fdc574b1b98 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/iso-8859-9.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/windows-1250.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/windows-1250.enc Binary files differnew file mode 100755 index 00000000000..d4a64b55f10 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/windows-1250.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/windows-1252.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/windows-1252.enc Binary files differnew file mode 100755 index 00000000000..ab2d57c6778 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/windows-1252.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-euc-jp-jisx0221.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-euc-jp-jisx0221.enc Binary files differnew file mode 100755 index 00000000000..ca79c07a2bb --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-euc-jp-jisx0221.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-euc-jp-unicode.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-euc-jp-unicode.enc Binary files differnew file mode 100755 index 00000000000..34d4d0d31e7 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-euc-jp-unicode.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-cp932.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-cp932.enc Binary files differnew file mode 100755 index 00000000000..c2a6bc40de5 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-cp932.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-jdk117.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-jdk117.enc Binary files differnew file mode 100755 index 00000000000..b6c2c07c042 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-jdk117.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-jisx0221.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-jisx0221.enc Binary files differnew file mode 100755 index 00000000000..cbb2db5fbad --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-jisx0221.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-unicode.enc b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-unicode.enc Binary files differnew file mode 100755 index 00000000000..6f88a06fd96 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Encodings/x-sjis-unicode.enc diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Expat.pm b/Master/tlpkg/tlperl/lib/XML/Parser/Expat.pm new file mode 100755 index 00000000000..9413d80a843 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Expat.pm @@ -0,0 +1,1230 @@ +package XML::Parser::Expat; + +require 5.004; + +use strict; +use vars qw($VERSION @ISA %Handler_Setters %Encoding_Table @Encoding_Path + $have_File_Spec); +use Carp; + +require DynaLoader; + +@ISA = qw(DynaLoader); +$VERSION = "2.36" ; + +$have_File_Spec = $INC{'File/Spec.pm'} || do 'File/Spec.pm'; + +%Encoding_Table = (); +if ($have_File_Spec) { + @Encoding_Path = (grep(-d $_, + map(File::Spec->catdir($_, qw(XML Parser Encodings)), + @INC)), + File::Spec->curdir); +} +else { + @Encoding_Path = (grep(-d $_, map($_ . '/XML/Parser/Encodings', @INC)), '.'); +} + + +bootstrap XML::Parser::Expat $VERSION; + +%Handler_Setters = ( + Start => \&SetStartElementHandler, + End => \&SetEndElementHandler, + Char => \&SetCharacterDataHandler, + Proc => \&SetProcessingInstructionHandler, + Comment => \&SetCommentHandler, + CdataStart => \&SetStartCdataHandler, + CdataEnd => \&SetEndCdataHandler, + Default => \&SetDefaultHandler, + Unparsed => \&SetUnparsedEntityDeclHandler, + Notation => \&SetNotationDeclHandler, + ExternEnt => \&SetExternalEntityRefHandler, + ExternEntFin => \&SetExtEntFinishHandler, + Entity => \&SetEntityDeclHandler, + Element => \&SetElementDeclHandler, + Attlist => \&SetAttListDeclHandler, + Doctype => \&SetDoctypeHandler, + DoctypeFin => \&SetEndDoctypeHandler, + XMLDecl => \&SetXMLDeclHandler + ); + +sub new { + my ($class, %args) = @_; + my $self = bless \%args, $_[0]; + $args{_State_} = 0; + $args{Context} = []; + $args{Namespaces} ||= 0; + $args{ErrorMessage} ||= ''; + if ($args{Namespaces}) { + $args{Namespace_Table} = {}; + $args{Namespace_List} = [undef]; + $args{Prefix_Table} = {}; + $args{New_Prefixes} = []; + } + $args{_Setters} = \%Handler_Setters; + $args{Parser} = ParserCreate($self, $args{ProtocolEncoding}, + $args{Namespaces}); + $self; +} + +sub load_encoding { + my ($file) = @_; + + $file =~ s!([^/]+)$!\L$1\E!; + $file .= '.enc' unless $file =~ /\.enc$/; + unless ($file =~ m!^/!) { + foreach (@Encoding_Path) { + my $tmp = ($have_File_Spec + ? File::Spec->catfile($_, $file) + : "$_/$file"); + if (-e $tmp) { + $file = $tmp; + last; + } + } + } + + local(*ENC); + open(ENC, $file) or croak("Couldn't open encmap $file:\n$!\n"); + binmode(ENC); + my $data; + my $br = sysread(ENC, $data, -s $file); + croak("Trouble reading $file:\n$!\n") + unless defined($br); + close(ENC); + + my $name = LoadEncoding($data, $br); + croak("$file isn't an encmap file") + unless defined($name); + + $name; +} # End load_encoding + +sub setHandlers { + my ($self, @handler_pairs) = @_; + + croak("Uneven number of arguments to setHandlers method") + if (int(@handler_pairs) & 1); + + my @ret; + + while (@handler_pairs) { + my $type = shift @handler_pairs; + my $handler = shift @handler_pairs; + croak "Handler for $type not a Code ref" + unless (! defined($handler) or ! $handler or ref($handler) eq 'CODE'); + + my $hndl = $self->{_Setters}->{$type}; + + unless (defined($hndl)) { + my @types = sort keys %{$self->{_Setters}}; + croak("Unknown Expat handler type: $type\n Valid types: @types"); + } + + my $old = &$hndl($self->{Parser}, $handler); + push (@ret, $type, $old); + } + + return @ret; +} + +sub xpcroak + { + my ($self, $message) = @_; + + my $eclines = $self->{ErrorContext}; + my $line = GetCurrentLineNumber($_[0]->{Parser}); + $message .= " at line $line"; + $message .= ":\n" . $self->position_in_context($eclines) + if defined($eclines); + croak $message; +} + +sub xpcarp { + my ($self, $message) = @_; + + my $eclines = $self->{ErrorContext}; + my $line = GetCurrentLineNumber($_[0]->{Parser}); + $message .= " at line $line"; + $message .= ":\n" . $self->position_in_context($eclines) + if defined($eclines); + carp $message; +} + +sub default_current { + my $self = shift; + if ($self->{_State_} == 1) { + return DefaultCurrent($self->{Parser}); + } +} + +sub recognized_string { + my $self = shift; + if ($self->{_State_} == 1) { + return RecognizedString($self->{Parser}); + } +} + +sub original_string { + my $self = shift; + if ($self->{_State_} == 1) { + return OriginalString($self->{Parser}); + } +} + +sub current_line { + my $self = shift; + if ($self->{_State_} == 1) { + return GetCurrentLineNumber($self->{Parser}); + } +} + +sub current_column { + my $self = shift; + if ($self->{_State_} == 1) { + return GetCurrentColumnNumber($self->{Parser}); + } +} + +sub current_byte { + my $self = shift; + if ($self->{_State_} == 1) { + return GetCurrentByteIndex($self->{Parser}); + } +} + +sub base { + my ($self, $newbase) = @_; + my $p = $self->{Parser}; + my $oldbase = GetBase($p); + SetBase($p, $newbase) if @_ > 1; + return $oldbase; +} + +sub context { + my $ctx = $_[0]->{Context}; + @$ctx; +} + +sub current_element { + my ($self) = @_; + @{$self->{Context}} ? $self->{Context}->[-1] : undef; +} + +sub in_element { + my ($self, $element) = @_; + @{$self->{Context}} ? $self->eq_name($self->{Context}->[-1], $element) + : undef; +} + +sub within_element { + my ($self, $element) = @_; + my $cnt = 0; + foreach (@{$self->{Context}}) { + $cnt++ if $self->eq_name($_, $element); + } + return $cnt; +} + +sub depth { + my ($self) = @_; + int(@{$self->{Context}}); +} + +sub element_index { + my ($self) = @_; + + if ($self->{_State_} == 1) { + return ElementIndex($self->{Parser}); + } +} + +################ +# Namespace methods + +sub namespace { + my ($self, $name) = @_; + local($^W) = 0; + $self->{Namespace_List}->[int($name)]; +} + +sub eq_name { + my ($self, $nm1, $nm2) = @_; + local($^W) = 0; + + int($nm1) == int($nm2) and $nm1 eq $nm2; +} + +sub generate_ns_name { + my ($self, $name, $namespace) = @_; + + $namespace ? + GenerateNSName($name, $namespace, $self->{Namespace_Table}, + $self->{Namespace_List}) + : $name; +} + +sub new_ns_prefixes { + my ($self) = @_; + if ($self->{Namespaces}) { + return @{$self->{New_Prefixes}}; + } + return (); +} + +sub expand_ns_prefix { + my ($self, $prefix) = @_; + + if ($self->{Namespaces}) { + my $stack = $self->{Prefix_Table}->{$prefix}; + return (defined($stack) and @$stack) ? $stack->[-1] : undef; + } + + return undef; +} + +sub current_ns_prefixes { + my ($self) = @_; + + if ($self->{Namespaces}) { + my %set = %{$self->{Prefix_Table}}; + + if (exists $set{'#default'} and not defined($set{'#default'}->[-1])) { + delete $set{'#default'}; + } + + return keys %set; + } + + return (); +} + + +################################################################ +# Namespace declaration handlers +# + +sub NamespaceStart { + my ($self, $prefix, $uri) = @_; + + $prefix = '#default' unless defined $prefix; + my $stack = $self->{Prefix_Table}->{$prefix}; + + if (defined $stack) { + push(@$stack, $uri); + } + else { + $self->{Prefix_Table}->{$prefix} = [$uri]; + } + + # The New_Prefixes list gets emptied at end of startElement function + # in Expat.xs + + push(@{$self->{New_Prefixes}}, $prefix); +} + +sub NamespaceEnd { + my ($self, $prefix) = @_; + + $prefix = '#default' unless defined $prefix; + + my $stack = $self->{Prefix_Table}->{$prefix}; + if (@$stack > 1) { + pop(@$stack); + } + else { + delete $self->{Prefix_Table}->{$prefix}; + } +} + +################ + +sub specified_attr { + my $self = shift; + + if ($self->{_State_} == 1) { + return GetSpecifiedAttributeCount($self->{Parser}); + } +} + +sub finish { + my ($self) = @_; + if ($self->{_State_} == 1) { + my $parser = $self->{Parser}; + UnsetAllHandlers($parser); + } +} + +sub position_in_context { + my ($self, $lines) = @_; + if ($self->{_State_} == 1) { + my $parser = $self->{Parser}; + my ($string, $linepos) = PositionContext($parser, $lines); + + return '' unless defined($string); + + my $col = GetCurrentColumnNumber($parser); + my $ptr = ('=' x ($col - 1)) . '^' . "\n"; + my $ret; + my $dosplit = $linepos < length($string); + + $string .= "\n" unless $string =~ /\n$/; + + if ($dosplit) { + $ret = substr($string, 0, $linepos) . $ptr + . substr($string, $linepos); + } else { + $ret = $string . $ptr; + } + + return $ret; + } +} + +sub xml_escape { + my $self = shift; + my $text = shift; + + study $text; + $text =~ s/\&/\&/g; + $text =~ s/</\</g; + foreach (@_) { + croak "xml_escape: '$_' isn't a single character" if length($_) > 1; + + if ($_ eq '>') { + $text =~ s/>/\>/g; + } + elsif ($_ eq '"') { + $text =~ s/\"/\"/; + } + elsif ($_ eq "'") { + $text =~ s/\'/\'/; + } + else { + my $rep = '&#' . sprintf('x%X', ord($_)) . ';'; + if (/\W/) { + my $ptrn = "\\$_"; + $text =~ s/$ptrn/$rep/g; + } + else { + $text =~ s/$_/$rep/g; + } + } + } + $text; +} + +sub skip_until { + my $self = shift; + if ($self->{_State_} <= 1) { + SkipUntil($self->{Parser}, $_[0]); + } +} + +sub release { + my $self = shift; + ParserRelease($self->{Parser}); +} + +sub DESTROY { + my $self = shift; + ParserFree($self->{Parser}); +} + +sub parse { + my $self = shift; + my $arg = shift; + croak "Parse already in progress (Expat)" if $self->{_State_}; + $self->{_State_} = 1; + my $parser = $self->{Parser}; + my $ioref; + my $result = 0; + + if (defined $arg) { + if (ref($arg) and UNIVERSAL::isa($arg, 'IO::Handle')) { + $ioref = $arg; + } elsif (tied($arg)) { + my $class = ref($arg); + no strict 'refs'; + $ioref = $arg if defined &{"${class}::TIEHANDLE"}; + } + else { + require IO::Handle; + eval { + no strict 'refs'; + $ioref = *{$arg}{IO} if defined *{$arg}; + }; + undef $@; + } + } + + if (defined($ioref)) { + my $delim = $self->{Stream_Delimiter}; + my $prev_rs; + + $prev_rs = ref($ioref)->input_record_separator("\n$delim\n") + if defined($delim); + + $result = ParseStream($parser, $ioref, $delim); + + ref($ioref)->input_record_separator($prev_rs) + if defined($delim); + } else { + $result = ParseString($parser, $arg); + } + + $self->{_State_} = 2; + $result or croak $self->{ErrorMessage}; +} + +sub parsestring { + my $self = shift; + $self->parse(@_); +} + +sub parsefile { + my $self = shift; + croak "Parser has already been used" if $self->{_State_}; + local(*FILE); + open(FILE, $_[0]) or croak "Couldn't open $_[0]:\n$!"; + binmode(FILE); + my $ret = $self->parse(*FILE); + close(FILE); + $ret; +} + +################################################################ +package XML::Parser::ContentModel; +use overload '""' => \&asString, 'eq' => \&thiseq; + +sub EMPTY () {1} +sub ANY () {2} +sub MIXED () {3} +sub NAME () {4} +sub CHOICE () {5} +sub SEQ () {6} + + +sub isempty { + return $_[0]->{Type} == EMPTY; +} + +sub isany { + return $_[0]->{Type} == ANY; +} + +sub ismixed { + return $_[0]->{Type} == MIXED; +} + +sub isname { + return $_[0]->{Type} == NAME; +} + +sub name { + return $_[0]->{Tag}; +} + +sub ischoice { + return $_[0]->{Type} == CHOICE; +} + +sub isseq { + return $_[0]->{Type} == SEQ; +} + +sub quant { + return $_[0]->{Quant}; +} + +sub children { + my $children = $_[0]->{Children}; + if (defined $children) { + return @$children; + } + return undef; +} + +sub asString { + my ($self) = @_; + my $ret; + + if ($self->{Type} == NAME) { + $ret = $self->{Tag}; + } + elsif ($self->{Type} == EMPTY) { + return "EMPTY"; + } + elsif ($self->{Type} == ANY) { + return "ANY"; + } + elsif ($self->{Type} == MIXED) { + $ret = '(#PCDATA'; + foreach (@{$self->{Children}}) { + $ret .= '|' . $_; + } + $ret .= ')'; + } + else { + my $sep = $self->{Type} == CHOICE ? '|' : ','; + $ret = '(' . join($sep, map { $_->asString } @{$self->{Children}}) . ')'; + } + + $ret .= $self->{Quant} if $self->{Quant}; + return $ret; +} + +sub thiseq { + my $self = shift; + + return $self->asString eq $_[0]; +} + +################################################################ +package XML::Parser::ExpatNB; + +use vars qw(@ISA); +use Carp; + +@ISA = qw(XML::Parser::Expat); + +sub parse { + my $self = shift; + my $class = ref($self); + croak "parse method not supported in $class"; +} + +sub parsestring { + my $self = shift; + my $class = ref($self); + croak "parsestring method not supported in $class"; +} + +sub parsefile { + my $self = shift; + my $class = ref($self); + croak "parsefile method not supported in $class"; +} + +sub parse_more { + my ($self, $data) = @_; + + $self->{_State_} = 1; + my $ret = XML::Parser::Expat::ParsePartial($self->{Parser}, $data); + + croak $self->{ErrorMessage} unless $ret; +} + +sub parse_done { + my $self = shift; + + my $ret = XML::Parser::Expat::ParseDone($self->{Parser}); + unless ($ret) { + my $msg = $self->{ErrorMessage}; + $self->release; + croak $msg; + } + + $self->{_State_} = 2; + + my $result = $ret; + my @result = (); + my $final = $self->{FinalHandler}; + if (defined $final) { + if (wantarray) { + @result = &$final($self); + } + else { + $result = &$final($self); + } + } + + $self->release; + + return unless defined wantarray; + return wantarray ? @result : $result; +} + +################################################################ + +package XML::Parser::Encinfo; + +sub DESTROY { + my $self = shift; + XML::Parser::Expat::FreeEncoding($self); +} + +1; + +__END__ + +=head1 NAME + +XML::Parser::Expat - Lowlevel access to James Clark's expat XML parser + +=head1 SYNOPSIS + + use XML::Parser::Expat; + + $parser = new XML::Parser::Expat; + $parser->setHandlers('Start' => \&sh, + 'End' => \&eh, + 'Char' => \&ch); + open(FOO, 'info.xml') or die "Couldn't open"; + $parser->parse(*FOO); + close(FOO); + # $parser->parse('<foo id="me"> here <em>we</em> go </foo>'); + + sub sh + { + my ($p, $el, %atts) = @_; + $p->setHandlers('Char' => \&spec) + if ($el eq 'special'); + ... + } + + sub eh + { + my ($p, $el) = @_; + $p->setHandlers('Char' => \&ch) # Special elements won't contain + if ($el eq 'special'); # other special elements + ... + } + +=head1 DESCRIPTION + +This module provides an interface to James Clark's XML parser, expat. As in +expat, a single instance of the parser can only parse one document. Calls +to parsestring after the first for a given instance will die. + +Expat (and XML::Parser::Expat) are event based. As the parser recognizes +parts of the document (say the start or end of an XML element), then any +handlers registered for that type of an event are called with suitable +parameters. + +=head1 METHODS + +=over 4 + +=item new + +This is a class method, the constructor for XML::Parser::Expat. Options are +passed as keyword value pairs. The recognized options are: + +=over 4 + +=item * ProtocolEncoding + +The protocol encoding name. The default is none. The expat built-in +encodings are: C<UTF-8>, C<ISO-8859-1>, C<UTF-16>, and C<US-ASCII>. +Other encodings may be used if they have encoding maps in one of the +directories in the @Encoding_Path list. Setting the protocol encoding +overrides any encoding in the XML declaration. + +=item * Namespaces + +When this option is given with a true value, then the parser does namespace +processing. By default, namespace processing is turned off. When it is +turned on, the parser consumes I<xmlns> attributes and strips off prefixes +from element and attributes names where those prefixes have a defined +namespace. A name's namespace can be found using the L<"namespace"> method +and two names can be checked for absolute equality with the L<"eq_name"> +method. + +=item * NoExpand + +Normally, the parser will try to expand references to entities defined in +the internal subset. If this option is set to a true value, and a default +handler is also set, then the default handler will be called when an +entity reference is seen in text. This has no effect if a default handler +has not been registered, and it has no effect on the expansion of entity +references inside attribute values. + +=item * Stream_Delimiter + +This option takes a string value. When this string is found alone on a line +while parsing from a stream, then the parse is ended as if it saw an end of +file. The intended use is with a stream of xml documents in a MIME multipart +format. The string should not contain a trailing newline. + +=item * ErrorContext + +When this option is defined, errors are reported in context. The value +of ErrorContext should be the number of lines to show on either side of +the line in which the error occurred. + +=item * ParseParamEnt + +Unless standalone is set to "yes" in the XML declaration, setting this to +a true value allows the external DTD to be read, and parameter entities +to be parsed and expanded. + +=item * Base + +The base to use for relative pathnames or URLs. This can also be done by +using the base method. + +=back + +=item setHandlers(TYPE, HANDLER [, TYPE, HANDLER [...]]) + +This method registers handlers for the various events. If no handlers are +registered, then a call to parsestring or parsefile will only determine if +the corresponding XML document is well formed (by returning without error.) +This may be called from within a handler, after the parse has started. + +Setting a handler to something that evaluates to false unsets that +handler. + +This method returns a list of type, handler pairs corresponding to the +input. The handlers returned are the ones that were in effect before the +call to setHandlers. + +The recognized events and the parameters passed to the corresponding +handlers are: + +=over 4 + +=item * Start (Parser, Element [, Attr, Val [,...]]) + +This event is generated when an XML start tag is recognized. Parser is +an XML::Parser::Expat instance. Element is the name of the XML element that +is opened with the start tag. The Attr & Val pairs are generated for each +attribute in the start tag. + +=item * End (Parser, Element) + +This event is generated when an XML end tag is recognized. Note that +an XML empty tag (<foo/>) generates both a start and an end event. + +There is always a lower level start and end handler installed that wrap +the corresponding callbacks. This is to handle the context mechanism. +A consequence of this is that the default handler (see below) will not +see a start tag or end tag unless the default_current method is called. + +=item * Char (Parser, String) + +This event is generated when non-markup is recognized. The non-markup +sequence of characters is in String. A single non-markup sequence of +characters may generate multiple calls to this handler. Whatever the +encoding of the string in the original document, this is given to the +handler in UTF-8. + +=item * Proc (Parser, Target, Data) + +This event is generated when a processing instruction is recognized. + +=item * Comment (Parser, String) + +This event is generated when a comment is recognized. + +=item * CdataStart (Parser) + +This is called at the start of a CDATA section. + +=item * CdataEnd (Parser) + +This is called at the end of a CDATA section. + +=item * Default (Parser, String) + +This is called for any characters that don't have a registered handler. +This includes both characters that are part of markup for which no +events are generated (markup declarations) and characters that +could generate events, but for which no handler has been registered. + +Whatever the encoding in the original document, the string is returned to +the handler in UTF-8. + +=item * Unparsed (Parser, Entity, Base, Sysid, Pubid, Notation) + +This is called for a declaration of an unparsed entity. Entity is the name +of the entity. Base is the base to be used for resolving a relative URI. +Sysid is the system id. Pubid is the public id. Notation is the notation +name. Base and Pubid may be undefined. + +=item * Notation (Parser, Notation, Base, Sysid, Pubid) + +This is called for a declaration of notation. Notation is the notation name. +Base is the base to be used for resolving a relative URI. Sysid is the system +id. Pubid is the public id. Base, Sysid, and Pubid may all be undefined. + +=item * ExternEnt (Parser, Base, Sysid, Pubid) + +This is called when an external entity is referenced. Base is the base to be +used for resolving a relative URI. Sysid is the system id. Pubid is the public +id. Base, and Pubid may be undefined. + +This handler should either return a string, which represents the contents of +the external entity, or return an open filehandle that can be read to obtain +the contents of the external entity, or return undef, which indicates the +external entity couldn't be found and will generate a parse error. + +If an open filehandle is returned, it must be returned as either a glob +(*FOO) or as a reference to a glob (e.g. an instance of IO::Handle). + +=item * ExternEntFin (Parser) + +This is called after an external entity has been parsed. It allows +applications to perform cleanup on actions performed in the above +ExternEnt handler. + +=item * Entity (Parser, Name, Val, Sysid, Pubid, Ndata, IsParam) + +This is called when an entity is declared. For internal entities, the Val +parameter will contain the value and the remaining three parameters will +be undefined. For external entities, the Val parameter +will be undefined, the Sysid parameter will have the system id, the Pubid +parameter will have the public id if it was provided (it will be undefined +otherwise), the Ndata parameter will contain the notation for unparsed +entities. If this is a parameter entity declaration, then the IsParam +parameter is true. + +Note that this handler and the Unparsed handler above overlap. If both are +set, then this handler will not be called for unparsed entities. + +=item * Element (Parser, Name, Model) + +The element handler is called when an element declaration is found. Name is +the element name, and Model is the content model as an +XML::Parser::ContentModel object. See L<"XML::Parser::ContentModel Methods"> +for methods available for this class. + +=item * Attlist (Parser, Elname, Attname, Type, Default, Fixed) + +This handler is called for each attribute in an ATTLIST declaration. +So an ATTLIST declaration that has multiple attributes +will generate multiple calls to this handler. The Elname parameter is the +name of the element with which the attribute is being associated. The Attname +parameter is the name of the attribute. Type is the attribute type, given as +a string. Default is the default value, which will either be "#REQUIRED", +"#IMPLIED" or a quoted string (i.e. the returned string will begin and end +with a quote character). If Fixed is true, then this is a fixed attribute. + +=item * Doctype (Parser, Name, Sysid, Pubid, Internal) + +This handler is called for DOCTYPE declarations. Name is the document type +name. Sysid is the system id of the document type, if it was provided, +otherwise it's undefined. Pubid is the public id of the document type, +which will be undefined if no public id was given. Internal will be +true or false, indicating whether or not the doctype declaration contains +an internal subset. + +=item * DoctypeFin (Parser) + +This handler is called after parsing of the DOCTYPE declaration has finished, +including any internal or external DTD declarations. + +=item * XMLDecl (Parser, Version, Encoding, Standalone) + +This handler is called for XML declarations. Version is a string containg +the version. Encoding is either undefined or contains an encoding string. +Standalone is either undefined, or true or false. Undefined indicates +that no standalone parameter was given in the XML declaration. True or +false indicates "yes" or "no" respectively. + +=back + +=item namespace(name) + +Return the URI of the namespace that the name belongs to. If the name doesn't +belong to any namespace, an undef is returned. This is only valid on names +received through the Start or End handlers from a single document, or through +a call to the generate_ns_name method. In other words, don't use names +generated from one instance of XML::Parser::Expat with other instances. + +=item eq_name(name1, name2) + +Return true if name1 and name2 are identical (i.e. same name and from +the same namespace.) This is only meaningful if both names were obtained +through the Start or End handlers from a single document, or through +a call to the generate_ns_name method. + +=item generate_ns_name(name, namespace) + +Return a name, associated with a given namespace, good for using with the +above 2 methods. The namespace argument should be the namespace URI, not +a prefix. + +=item new_ns_prefixes + +When called from a start tag handler, returns namespace prefixes declared +with this start tag. If called elsewere (or if there were no namespace +prefixes declared), it returns an empty list. Setting of the default +namespace is indicated with '#default' as a prefix. + +=item expand_ns_prefix(prefix) + +Return the uri to which the given prefix is currently bound. Returns +undef if the prefix isn't currently bound. Use '#default' to find the +current binding of the default namespace (if any). + +=item current_ns_prefixes + +Return a list of currently bound namespace prefixes. The order of the +the prefixes in the list has no meaning. If the default namespace is +currently bound, '#default' appears in the list. + +=item recognized_string + +Returns the string from the document that was recognized in order to call +the current handler. For instance, when called from a start handler, it +will give us the the start-tag string. The string is encoded in UTF-8. +This method doesn't return a meaningful string inside declaration handlers. + +=item original_string + +Returns the verbatim string from the document that was recognized in +order to call the current handler. The string is in the original document +encoding. This method doesn't return a meaningful string inside declaration +handlers. + +=item default_current + +When called from a handler, causes the sequence of characters that generated +the corresponding event to be sent to the default handler (if one is +registered). Use of this method is deprecated in favor the recognized_string +method, which you can use without installing a default handler. This +method doesn't deliver a meaningful string to the default handler when +called from inside declaration handlers. + +=item xpcroak(message) + +Concatenate onto the given message the current line number within the +XML document plus the message implied by ErrorContext. Then croak with +the formed message. + +=item xpcarp(message) + +Concatenate onto the given message the current line number within the +XML document plus the message implied by ErrorContext. Then carp with +the formed message. + +=item current_line + +Returns the line number of the current position of the parse. + +=item current_column + +Returns the column number of the current position of the parse. + +=item current_byte + +Returns the current position of the parse. + +=item base([NEWBASE]); + +Returns the current value of the base for resolving relative URIs. If +NEWBASE is supplied, changes the base to that value. + +=item context + +Returns a list of element names that represent open elements, with the +last one being the innermost. Inside start and end tag handlers, this +will be the tag of the parent element. + +=item current_element + +Returns the name of the innermost currently opened element. Inside +start or end handlers, returns the parent of the element associated +with those tags. + +=item in_element(NAME) + +Returns true if NAME is equal to the name of the innermost currently opened +element. If namespace processing is being used and you want to check +against a name that may be in a namespace, then use the generate_ns_name +method to create the NAME argument. + +=item within_element(NAME) + +Returns the number of times the given name appears in the context list. +If namespace processing is being used and you want to check +against a name that may be in a namespace, then use the generate_ns_name +method to create the NAME argument. + +=item depth + +Returns the size of the context list. + +=item element_index + +Returns an integer that is the depth-first visit order of the current +element. This will be zero outside of the root element. For example, +this will return 1 when called from the start handler for the root element +start tag. + +=item skip_until(INDEX) + +INDEX is an integer that represents an element index. When this method +is called, all handlers are suspended until the start tag for an element +that has an index number equal to INDEX is seen. If a start handler has +been set, then this is the first tag that the start handler will see +after skip_until has been called. + + +=item position_in_context(LINES) + +Returns a string that shows the current parse position. LINES should be +an integer >= 0 that represents the number of lines on either side of the +current parse line to place into the returned string. + +=item xml_escape(TEXT [, CHAR [, CHAR ...]]) + +Returns TEXT with markup characters turned into character entities. Any +additional characters provided as arguments are also turned into character +references where found in TEXT. + +=item parse (SOURCE) + +The SOURCE parameter should either be a string containing the whole XML +document, or it should be an open IO::Handle. Only a single document +may be parsed for a given instance of XML::Parser::Expat, so this will croak +if it's been called previously for this instance. + +=item parsestring(XML_DOC_STRING) + +Parses the given string as an XML document. Only a single document may be +parsed for a given instance of XML::Parser::Expat, so this will die if either +parsestring or parsefile has been called for this instance previously. + +This method is deprecated in favor of the parse method. + +=item parsefile(FILENAME) + +Parses the XML document in the given file. Will die if parsestring or +parsefile has been called previously for this instance. + +=item is_defaulted(ATTNAME) + +NO LONGER WORKS. To find out if an attribute is defaulted please use +the specified_attr method. + +=item specified_attr + +When the start handler receives lists of attributes and values, the +non-defaulted (i.e. explicitly specified) attributes occur in the list +first. This method returns the number of specified items in the list. +So if this number is equal to the length of the list, there were no +defaulted values. Otherwise the number points to the index of the +first defaulted attribute name. + +=item finish + +Unsets all handlers (including internal ones that set context), but expat +continues parsing to the end of the document or until it finds an error. +It should finish up a lot faster than with the handlers set. + +=item release + +There are data structures used by XML::Parser::Expat that have circular +references. This means that these structures will never be garbage +collected unless these references are explicitly broken. Calling this +method breaks those references (and makes the instance unusable.) + +Normally, higher level calls handle this for you, but if you are using +XML::Parser::Expat directly, then it's your responsibility to call it. + +=back + +=head2 XML::Parser::ContentModel Methods + +The element declaration handlers are passed objects of this class as the +content model of the element declaration. They also represent content +particles, components of a content model. + +When referred to as a string, these objects are automagicly converted to a +string representation of the model (or content particle). + +=over 4 + +=item isempty + +This method returns true if the object is "EMPTY", false otherwise. + +=item isany + +This method returns true if the object is "ANY", false otherwise. + +=item ismixed + +This method returns true if the object is "(#PCDATA)" or "(#PCDATA|...)*", +false otherwise. + +=item isname + +This method returns if the object is an element name. + +=item ischoice + +This method returns true if the object is a choice of content particles. + + +=item isseq + +This method returns true if the object is a sequence of content particles. + +=item quant + +This method returns undef or a string representing the quantifier +('?', '*', '+') associated with the model or particle. + +=item children + +This method returns undef or (for mixed, choice, and sequence types) +an array of component content particles. There will always be at least +one component for choices and sequences, but for a mixed content model +of pure PCDATA, "(#PCDATA)", then an undef is returned. + +=back + +=head2 XML::Parser::ExpatNB Methods + +The class XML::Parser::ExpatNB is a subclass of XML::Parser::Expat used +for non-blocking access to the expat library. It does not support the parse, +parsestring, or parsefile methods, but it does have these additional methods: + +=over 4 + +=item parse_more(DATA) + +Feed expat more text to munch on. + +=item parse_done + +Tell expat that it's gotten the whole document. + +=back + +=head1 FUNCTIONS + +=over 4 + +=item XML::Parser::Expat::load_encoding(ENCODING) + +Load an external encoding. ENCODING is either the name of an encoding or +the name of a file. The basename is converted to lowercase and a '.enc' +extension is appended unless there's one already there. Then, unless +it's an absolute pathname (i.e. begins with '/'), the first file by that +name discovered in the @Encoding_Path path list is used. + +The encoding in the file is loaded and kept in the %Encoding_Table +table. Earlier encodings of the same name are replaced. + +This function is automaticly called by expat when it encounters an encoding +it doesn't know about. Expat shouldn't call this twice for the same +encoding name. The only reason users should use this function is to +explicitly load an encoding not contained in the @Encoding_Path list. + +=back + +=head1 AUTHORS + +Larry Wall <F<larry@wall.org>> wrote version 1.0. + +Clark Cooper <F<coopercc@netheaven.com>> picked up support, changed the API +for this version (2.x), provided documentation, and added some standard +package features. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/LWPExternEnt.pl b/Master/tlpkg/tlperl/lib/XML/Parser/LWPExternEnt.pl new file mode 100755 index 00000000000..d0c940b1ac5 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/LWPExternEnt.pl @@ -0,0 +1,71 @@ +# LWPExternEnt.pl +# +# Copyright (c) 2000 Clark Cooper +# All rights reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the same terms as Perl itself. + +package XML::Parser; + +use URI; +use URI::file; +use LWP; + +## +## Note that this external entity handler reads the entire entity into +## memory, so it will choke on huge ones. It would be really nice if +## LWP::UserAgent optionally returned us an IO::Handle. +## + +sub lwp_ext_ent_handler { + my ($xp, $base, $sys) = @_; # We don't use public id + + my $uri; + + if (defined $base) { + # Base may have been set by parsefile, which is agnostic about + # whether its a file or URI. + my $base_uri = new URI($base); + unless (defined $base_uri->scheme) { + $base_uri = URI->new_abs($base_uri, URI::file->cwd); + } + + $uri = URI->new_abs($sys, $base_uri); + } + else { + $uri = new URI($sys); + unless (defined $uri->scheme) { + $uri = URI->new_abs($uri, URI::file->cwd); + } + } + + my $ua = $xp->{_lwpagent}; + unless (defined $ua) { + $ua = $xp->{_lwpagent} = new LWP::UserAgent(); + $ua->env_proxy(); + } + + my $req = new HTTP::Request('GET', $uri); + + my $res = $ua->request($req); + if ($res->is_error) { + $xp->{ErrorMessage} .= "\n" . $res->status_line . " $uri"; + return undef; + } + + $xp->{_BaseStack} ||= []; + push(@{$xp->{_BaseStack}}, $base); + + $xp->base($uri); + + return $res->content; +} # End lwp_ext_ent_handler + +sub lwp_ext_ent_cleanup { + my ($xp) = @_; + + $xp->base(pop(@{$xp->{_BaseStack}})); +} # End lwp_ext_ent_cleanup + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Style/Debug.pm b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Debug.pm new file mode 100755 index 00000000000..89fcd8b248b --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Debug.pm @@ -0,0 +1,52 @@ +# $Id: Debug.pm,v 1.1 2003/07/27 16:07:49 matt Exp $ + +package XML::Parser::Style::Debug; +use strict; + +sub Start { + my $expat = shift; + my $tag = shift; + print STDERR "@{$expat->{Context}} \\\\ (@_)\n"; +} + +sub End { + my $expat = shift; + my $tag = shift; + print STDERR "@{$expat->{Context}} //\n"; +} + +sub Char { + my $expat = shift; + my $text = shift; + $text =~ s/([\x80-\xff])/sprintf "#x%X;", ord $1/eg; + $text =~ s/([\t\n])/sprintf "#%d;", ord $1/eg; + print STDERR "@{$expat->{Context}} || $text\n"; +} + +sub Proc { + my $expat = shift; + my $target = shift; + my $text = shift; + my @foo = @{$expat->{Context}}; + print STDERR "@foo $target($text)\n"; +} + +1; +__END__ + +=head1 NAME + +XML::Parser::Style::Debug - Debug style for XML::Parser + +=head1 SYNOPSIS + + use XML::Parser; + my $p = XML::Parser->new(Style => 'Debug'); + $p->parsefile('foo.xml'); + +=head1 DESCRIPTION + +This just prints out the document in outline form to STDERR. Nothing special is +returned by parse. + +=cut
\ No newline at end of file diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Style/Objects.pm b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Objects.pm new file mode 100755 index 00000000000..8603db05a39 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Objects.pm @@ -0,0 +1,78 @@ +# $Id: Objects.pm,v 1.1 2003/08/18 20:20:51 matt Exp $ + +package XML::Parser::Style::Objects; +use strict; + +sub Init { + my $expat = shift; + $expat->{Lists} = []; + $expat->{Curlist} = $expat->{Tree} = []; +} + +sub Start { + my $expat = shift; + my $tag = shift; + my $newlist = [ ]; + my $class = "${$expat}{Pkg}::$tag"; + my $newobj = bless { @_, Kids => $newlist }, $class; + push @{ $expat->{Lists} }, $expat->{Curlist}; + push @{ $expat->{Curlist} }, $newobj; + $expat->{Curlist} = $newlist; +} + +sub End { + my $expat = shift; + my $tag = shift; + $expat->{Curlist} = pop @{ $expat->{Lists} }; +} + +sub Char { + my $expat = shift; + my $text = shift; + my $class = "${$expat}{Pkg}::Characters"; + my $clist = $expat->{Curlist}; + my $pos = $#$clist; + + if ($pos >= 0 and ref($clist->[$pos]) eq $class) { + $clist->[$pos]->{Text} .= $text; + } else { + push @$clist, bless { Text => $text }, $class; + } +} + +sub Final { + my $expat = shift; + delete $expat->{Curlist}; + delete $expat->{Lists}; + $expat->{Tree}; +} + +1; +__END__ + +=head1 NAME + +XML::Parser::Style::Objects + +=head1 SYNOPSIS + + use XML::Parser; + my $p = XML::Parser->new(Style => 'Objects', Pkg => 'MyNode'); + my $tree = $p->parsefile('foo.xml'); + +=head1 DESCRIPTION + +This module implements XML::Parser's Objects style parser. + +This is similar to the Tree style, except that a hash object is created for +each element. The corresponding object will be in the class whose name +is created by appending "::" and the element name to the package set with +the Pkg option. Non-markup text will be in the ::Characters class. The +contents of the corresponding object will be in an anonymous array that +is the value of the Kids property for that object. + +=head1 SEE ALSO + +L<XML::Parser::Style::Tree> + +=cut
\ No newline at end of file diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Style/Stream.pm b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Stream.pm new file mode 100755 index 00000000000..1e2e3f7183d --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Stream.pm @@ -0,0 +1,184 @@ +# $Id: Stream.pm,v 1.1 2003/07/27 16:07:49 matt Exp $ + +package XML::Parser::Style::Stream; +use strict; + +# This style invented by Tim Bray <tbray@textuality.com> + +sub Init { + no strict 'refs'; + my $expat = shift; + $expat->{Text} = ''; + my $sub = $expat->{Pkg} ."::StartDocument"; + &$sub($expat) + if defined(&$sub); +} + +sub Start { + no strict 'refs'; + my $expat = shift; + my $type = shift; + + doText($expat); + $_ = "<$type"; + + %_ = @_; + while (@_) { + $_ .= ' ' . shift() . '="' . shift() . '"'; + } + $_ .= '>'; + + my $sub = $expat->{Pkg} . "::StartTag"; + if (defined(&$sub)) { + &$sub($expat, $type); + } else { + print; + } +} + +sub End { + no strict 'refs'; + my $expat = shift; + my $type = shift; + + # Set right context for Text handler + push(@{$expat->{Context}}, $type); + doText($expat); + pop(@{$expat->{Context}}); + + $_ = "</$type>"; + + my $sub = $expat->{Pkg} . "::EndTag"; + if (defined(&$sub)) { + &$sub($expat, $type); + } else { + print; + } +} + +sub Char { + my $expat = shift; + $expat->{Text} .= shift; +} + +sub Proc { + no strict 'refs'; + my $expat = shift; + my $target = shift; + my $text = shift; + + doText($expat); + + $_ = "<?$target $text?>"; + + my $sub = $expat->{Pkg} . "::PI"; + if (defined(&$sub)) { + &$sub($expat, $target, $text); + } else { + print; + } +} + +sub Final { + no strict 'refs'; + my $expat = shift; + my $sub = $expat->{Pkg} . "::EndDocument"; + &$sub($expat) + if defined(&$sub); +} + +sub doText { + no strict 'refs'; + my $expat = shift; + $_ = $expat->{Text}; + + if (length($_)) { + my $sub = $expat->{Pkg} . "::Text"; + if (defined(&$sub)) { + &$sub($expat); + } else { + print; + } + + $expat->{Text} = ''; + } +} + +1; +__END__ + +=head1 NAME + +XML::Parser::Style::Stream - Stream style for XML::Parser + +=head1 SYNOPSIS + + use XML::Parser; + my $p = XML::Parser->new(Style => 'Stream', Pkg => 'MySubs'); + $p->parsefile('foo.xml'); + + { + package MySubs; + + sub StartTag { + my ($e, $name) = @_; + # do something with start tags + } + + sub EndTag { + my ($e, $name) = @_; + # do something with end tags + } + + sub Characters { + my ($e, $data) = @_; + # do something with text nodes + } + } + +=head1 DESCRIPTION + +This style uses the Pkg option to find subs in a given package to call for each event. +If none of the subs that this +style looks for is there, then the effect of parsing with this style is +to print a canonical copy of the document without comments or declarations. +All the subs receive as their 1st parameter the Expat instance for the +document they're parsing. + +It looks for the following routines: + +=over 4 + +=item * StartDocument + +Called at the start of the parse . + +=item * StartTag + +Called for every start tag with a second parameter of the element type. The $_ +variable will contain a copy of the tag and the %_ variable will contain +attribute values supplied for that element. + +=item * EndTag + +Called for every end tag with a second parameter of the element type. The $_ +variable will contain a copy of the end tag. + +=item * Text + +Called just before start or end tags with accumulated non-markup text in +the $_ variable. + +=item * PI + +Called for processing instructions. The $_ variable will contain a copy of +the PI and the target and data are sent as 2nd and 3rd parameters +respectively. + +=item * EndDocument + +Called at conclusion of the parse. + +=back + +=cut
\ No newline at end of file diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Style/Subs.pm b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Subs.pm new file mode 100755 index 00000000000..15a21439e8e --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Subs.pm @@ -0,0 +1,58 @@ +# $Id: Subs.pm,v 1.1 2003/07/27 16:07:49 matt Exp $ + +package XML::Parser::Style::Subs; + +sub Start { + no strict 'refs'; + my $expat = shift; + my $tag = shift; + my $sub = $expat->{Pkg} . "::$tag"; + eval { &$sub($expat, $tag, @_) }; +} + +sub End { + no strict 'refs'; + my $expat = shift; + my $tag = shift; + my $sub = $expat->{Pkg} . "::${tag}_"; + eval { &$sub($expat, $tag) }; +} + +1; +__END__ + +=head1 NAME + +XML::Parser::Style::Subs + +=head1 SYNOPSIS + + use XML::Parser; + my $p = XML::Parser->new(Style => 'Subs', Pkg => 'MySubs'); + $p->parsefile('foo.xml'); + + { + package MySubs; + + sub foo { + # start of foo tag + } + + sub foo_ { + # end of foo tag + } + } + +=head1 DESCRIPTION + +Each time an element starts, a sub by that name in the package specified +by the Pkg option is called with the same parameters that the Start +handler gets called with. + +Each time an element ends, a sub with that name appended with an underscore +("_"), is called with the same parameters that the End handler gets called +with. + +Nothing special is returned by parse. + +=cut
\ No newline at end of file diff --git a/Master/tlpkg/tlperl/lib/XML/Parser/Style/Tree.pm b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Tree.pm new file mode 100755 index 00000000000..c0e69f131ce --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/Parser/Style/Tree.pm @@ -0,0 +1,90 @@ +# $Id: Tree.pm,v 1.2 2003/07/31 07:54:51 matt Exp $ + +package XML::Parser::Style::Tree; +$XML::Parser::Built_In_Styles{Tree} = 1; + +sub Init { + my $expat = shift; + $expat->{Lists} = []; + $expat->{Curlist} = $expat->{Tree} = []; +} + +sub Start { + my $expat = shift; + my $tag = shift; + my $newlist = [ { @_ } ]; + push @{ $expat->{Lists} }, $expat->{Curlist}; + push @{ $expat->{Curlist} }, $tag => $newlist; + $expat->{Curlist} = $newlist; +} + +sub End { + my $expat = shift; + my $tag = shift; + $expat->{Curlist} = pop @{ $expat->{Lists} }; +} + +sub Char { + my $expat = shift; + my $text = shift; + my $clist = $expat->{Curlist}; + my $pos = $#$clist; + + if ($pos > 0 and $clist->[$pos - 1] eq '0') { + $clist->[$pos] .= $text; + } else { + push @$clist, 0 => $text; + } +} + +sub Final { + my $expat = shift; + delete $expat->{Curlist}; + delete $expat->{Lists}; + $expat->{Tree}; +} + +1; +__END__ + +=head1 NAME + +XML::Parser::Style::Tree + +=head1 SYNOPSIS + + use XML::Parser; + my $p = XML::Parser->new(Style => 'Tree'); + my $tree = $p->parsefile('foo.xml'); + +=head1 DESCRIPTION + +This module implements XML::Parser's Tree style parser. + +When parsing a document, C<parse()> will return a parse tree for the +document. Each node in the tree +takes the form of a tag, content pair. Text nodes are represented with +a pseudo-tag of "0" and the string that is their content. For elements, +the content is an array reference. The first item in the array is a +(possibly empty) hash reference containing attributes. The remainder of +the array is a sequence of tag-content pairs representing the content +of the element. + +So for example the result of parsing: + + <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo> + +would be: + Tag Content + ================================================================== + [foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]], + bar, [ {}, 0, "Howdy", ref, [{}]], + 0, "do" + ] + ] + +The root document "foo", has 3 children: a "head" element, a "bar" +element and the text "do". After the empty attribute hash, these are +represented in it's contents by 3 tag-content pairs. + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/SAX.pm b/Master/tlpkg/tlperl/lib/XML/SAX.pm new file mode 100755 index 00000000000..2dbe8b79c21 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX.pm @@ -0,0 +1,379 @@ +# $Id: SAX.pm,v 1.31 2008-08-05 12:36:24 grant Exp $ + +package XML::SAX; + +use strict; +use vars qw($VERSION @ISA @EXPORT_OK); + +$VERSION = '0.96'; + +use Exporter (); +@ISA = ('Exporter'); + +@EXPORT_OK = qw(Namespaces Validation); + +use File::Basename qw(dirname); +use File::Spec (); +use Symbol qw(gensym); +use XML::SAX::ParserFactory (); # loaded for simplicity + +use constant PARSER_DETAILS => "ParserDetails.ini"; + +use constant Namespaces => "http://xml.org/sax/features/namespaces"; +use constant Validation => "http://xml.org/sax/features/validation"; + +my $known_parsers = undef; + +# load_parsers takes the ParserDetails.ini file out of the same directory +# that XML::SAX is in, and looks at it. Format in POD below + +=begin EXAMPLE + +[XML::SAX::PurePerl] +http://xml.org/sax/features/namespaces = 1 +http://xml.org/sax/features/validation = 0 +# a comment + +# blank lines ignored + +[XML::SAX::AnotherParser] +http://xml.org/sax/features/namespaces = 0 +http://xml.org/sax/features/validation = 1 + +=end EXAMPLE + +=cut + +sub load_parsers { + my $class = shift; + my $dir = shift; + + # reset parsers + $known_parsers = []; + + # get directory from wherever XML::SAX is installed + if (!$dir) { + $dir = $INC{'XML/SAX.pm'}; + $dir = dirname($dir); + } + + my $fh = gensym(); + if (!open($fh, File::Spec->catfile($dir, "SAX", PARSER_DETAILS))) { + XML::SAX->do_warn("could not find " . PARSER_DETAILS . " in $dir/SAX\n"); + return $class; + } + + $known_parsers = $class->_parse_ini_file($fh); + + return $class; +} + +sub _parse_ini_file { + my $class = shift; + my ($fh) = @_; + + my @config; + + my $lineno = 0; + while (defined(my $line = <$fh>)) { + $lineno++; + my $original = $line; + # strip whitespace + $line =~ s/\s*$//m; + $line =~ s/^\s*//m; + # strip comments + $line =~ s/[#;].*$//m; + # ignore blanks + next if $line =~ /^$/m; + + # heading + if ($line =~ /^\[\s*(.*)\s*\]$/m) { + push @config, { Name => $1 }; + next; + } + + # instruction + elsif ($line =~ /^(.*?)\s*?=\s*(.*)$/) { + unless(@config) { + push @config, { Name => '' }; + } + $config[-1]{Features}{$1} = $2; + } + + # not whitespace, comment, or instruction + else { + die "Invalid line in ini: $lineno\n>>> $original\n"; + } + } + + return \@config; +} + +sub parsers { + my $class = shift; + if (!$known_parsers) { + $class->load_parsers(); + } + return $known_parsers; +} + +sub remove_parser { + my $class = shift; + my ($parser_module) = @_; + + if (!$known_parsers) { + $class->load_parsers(); + } + + @$known_parsers = grep { $_->{Name} ne $parser_module } @$known_parsers; + + return $class; +} + +sub add_parser { + my $class = shift; + my ($parser_module) = @_; + + if (!$known_parsers) { + $class->load_parsers(); + } + + # first load module, then query features, then push onto known_parsers, + + my $parser_file = $parser_module; + $parser_file =~ s/::/\//g; + $parser_file .= ".pm"; + + require $parser_file; + + my @features = $parser_module->supported_features(); + + my $new = { Name => $parser_module }; + foreach my $feature (@features) { + $new->{Features}{$feature} = 1; + } + + # If exists in list already, move to end. + my $done = 0; + my $pos = undef; + for (my $i = 0; $i < @$known_parsers; $i++) { + my $p = $known_parsers->[$i]; + if ($p->{Name} eq $parser_module) { + $pos = $i; + } + } + if (defined $pos) { + splice(@$known_parsers, $pos, 1); + push @$known_parsers, $new; + $done++; + } + + # Otherwise (not in list), add at end of list. + if (!$done) { + push @$known_parsers, $new; + } + + return $class; +} + +sub save_parsers { + my $class = shift; + + # get directory from wherever XML::SAX is installed + my $dir = $INC{'XML/SAX.pm'}; + $dir = dirname($dir); + + my $file = File::Spec->catfile($dir, "SAX", PARSER_DETAILS); + chmod 0644, $file; + unlink($file); + + my $fh = gensym(); + open($fh, ">$file") || + die "Cannot write to $file: $!"; + + foreach my $p (@$known_parsers) { + print $fh "[$p->{Name}]\n"; + foreach my $key (keys %{$p->{Features}}) { + print $fh "$key = $p->{Features}{$key}\n"; + } + print $fh "\n"; + } + + print $fh "\n"; + + close $fh; + + return $class; +} + +sub do_warn { + my $class = shift; + # Don't output warnings if running under Test::Harness + warn(@_) unless $ENV{HARNESS_ACTIVE}; +} + +1; +__END__ + +=head1 NAME + +XML::SAX - Simple API for XML + +=head1 SYNOPSIS + + use XML::SAX; + + # get a list of known parsers + my $parsers = XML::SAX->parsers(); + + # add/update a parser + XML::SAX->add_parser(q(XML::SAX::PurePerl)); + + # remove parser + XML::SAX->remove_parser(q(XML::SAX::Foodelberry)); + + # save parsers + XML::SAX->save_parsers(); + +=head1 DESCRIPTION + +XML::SAX is a SAX parser access API for Perl. It includes classes +and APIs required for implementing SAX drivers, along with a factory +class for returning any SAX parser installed on the user's system. + +=head1 USING A SAX2 PARSER + +The factory class is XML::SAX::ParserFactory. Please see the +documentation of that module for how to instantiate a SAX parser: +L<XML::SAX::ParserFactory>. However if you don't want to load up +another manual page, here's a short synopsis: + + use XML::SAX::ParserFactory; + use XML::SAX::XYZHandler; + my $handler = XML::SAX::XYZHandler->new(); + my $p = XML::SAX::ParserFactory->parser(Handler => $handler); + $p->parse_uri("foo.xml"); + # or $p->parse_string("<foo/>") or $p->parse_file($fh); + +This will automatically load a SAX2 parser (defaulting to +XML::SAX::PurePerl if no others are found) and return it to you. + +In order to learn how to use SAX to parse XML, you will need to read +L<XML::SAX::Intro> and for reference, L<XML::SAX::Specification>. + +=head1 WRITING A SAX2 PARSER + +The first thing to remember in writing a SAX2 parser is to subclass +XML::SAX::Base. This will make your life infinitely easier, by providing +a number of methods automagically for you. See L<XML::SAX::Base> for more +details. + +When writing a SAX2 parser that is compatible with XML::SAX, you need +to inform XML::SAX of the presence of that driver when you install it. +In order to do that, XML::SAX contains methods for saving the fact that +the parser exists on your system to a "INI" file, which is then loaded +to determine which parsers are installed. + +The best way to do this is to follow these rules: + +=over 4 + +=item * Add XML::SAX as a prerequisite in Makefile.PL: + + WriteMakefile( + ... + PREREQ_PM => { 'XML::SAX' => 0 }, + ... + ); + +Alternatively you may wish to check for it in other ways that will +cause more than just a warning. + +=item * Add the following code snippet to your Makefile.PL: + + sub MY::install { + package MY; + my $script = shift->SUPER::install(@_); + if (ExtUtils::MakeMaker::prompt( + "Do you want to modify ParserDetails.ini?", 'Y') + =~ /^y/i) { + $script =~ s/install :: (.*)$/install :: $1 install_sax_driver/m; + $script .= <<"INSTALL"; + + install_sax_driver : + \t\@\$(PERL) -MXML::SAX -e "XML::SAX->add_parser(q(\$(NAME)))->save_parsers()" + + INSTALL + } + return $script; + } + +Note that you should check the output of this - \$(NAME) will use the name of +your distribution, which may not be exactly what you want. For example XML::LibXML +has a driver called XML::LibXML::SAX::Generator, which is used in place of +\$(NAME) in the above. + +=item * Add an XML::SAX test: + +A test file should be added to your t/ directory containing something like the +following: + + use Test; + BEGIN { plan tests => 3 } + use XML::SAX; + use XML::SAX::PurePerl::DebugHandler; + XML::SAX->add_parser(q(XML::SAX::MyDriver)); + local $XML::SAX::ParserPackage = 'XML::SAX::MyDriver'; + eval { + my $handler = XML::SAX::PurePerl::DebugHandler->new(); + ok($handler); + my $parser = XML::SAX::ParserFactory->parser(Handler => $handler); + ok($parser); + ok($parser->isa('XML::SAX::MyDriver'); + $parser->parse_string("<tag/>"); + ok($handler->{seen}{start_element}); + }; + +=back + +=head1 EXPORTS + +By default, XML::SAX exports nothing into the caller's namespace. However you +can request the symbols C<Namespaces> and C<Validation> which are the +URIs for those features, allowing an easier way to request those features +via ParserFactory: + + use XML::SAX qw(Namespaces Validation); + my $factory = XML::SAX::ParserFactory->new(); + $factory->require_feature(Namespaces); + $factory->require_feature(Validation); + my $parser = $factory->parser(); + +=head1 AUTHOR + +Current maintainer: Grant McLean, grantm@cpan.org + +Originally written by: + +Matt Sergeant, matt@sergeant.org + +Kip Hampton, khampton@totalcinema.com + +Robin Berjon, robin@knowscape.com + +=head1 LICENSE + +This is free software, you may use it and distribute it under +the same terms as Perl itself. + +=head1 SEE ALSO + +L<XML::SAX::Base> for writing SAX Filters and Parsers + +L<XML::SAX::PurePerl> for an XML parser written in 100% +pure perl. + +L<XML::SAX::Exception> for details on exception handling + +=cut + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/Base.pm b/Master/tlpkg/tlperl/lib/XML/SAX/Base.pm new file mode 100755 index 00000000000..5de3f5ce783 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/Base.pm @@ -0,0 +1,3164 @@ +package XML::SAX::Base; + +# version 0.10 - Kip Hampton <khampton@totalcinema.com> +# version 0.13 - Robin Berjon <robin@knowscape.com> +# version 0.15 - Kip Hampton <khampton@totalcinema.com> +# version 0.17 - Kip Hampton <khampton@totalcinema.com> +# version 0.19 - Kip Hampton <khampton@totalcinema.com> +# version 0.21 - Kip Hampton <khampton@totalcinema.com> +# version 0.22 - Robin Berjon <robin@knowscape.com> +# version 0.23 - Matt Sergeant <matt@sergeant.org> +# version 0.24 - Robin Berjon <robin@knowscape.com> +# version 0.25 - Kip Hampton <khampton@totalcinema.com> +# version 1.00 - Kip Hampton <khampton@totalcinema.com> +# version 1.01 - Kip Hampton <khampton@totalcinema.com> +# version 1.02 - Robin Berjon <robin@knowscape.com> +# version 1.03 - Matt Sergeant <matt@sergeant.org> +# version 1.04 - Kip Hampton <khampton@totalcinema.com> + +#-----------------------------------------------------# +# STOP!!!!! +# +# This file is generated by the 'Makefile.PL' file +# that ships with the XML::SAX distribution. +# If you need to make changes, patch that file NOT +# this one. +#-----------------------------------------------------# + +use strict; +use vars qw($VERSION); +use XML::SAX::Exception qw(); + +$VERSION = '1.04'; + +sub end_prefix_mapping { + my $self = shift; + if (defined $self->{Methods}->{'end_prefix_mapping'}) { + $self->{Methods}->{'end_prefix_mapping'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('end_prefix_mapping') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'end_prefix_mapping'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('end_prefix_mapping') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_prefix_mapping'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->end_prefix_mapping(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'end_prefix_mapping'} = sub { $handler->end_prefix_mapping(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->end_prefix_mapping(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_prefix_mapping'} = sub { $handler->end_prefix_mapping(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'end_prefix_mapping'} = sub { }; + } + } + +} + +sub internal_entity_decl { + my $self = shift; + if (defined $self->{Methods}->{'internal_entity_decl'}) { + $self->{Methods}->{'internal_entity_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DeclHandler'} and $method = $callbacks->{'DeclHandler'}->can('internal_entity_decl') ) { + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'internal_entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('internal_entity_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'internal_entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DeclHandler'} + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DeclHandler'}->internal_entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'internal_entity_decl'} = sub { $handler->internal_entity_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->internal_entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'internal_entity_decl'} = sub { $handler->internal_entity_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'internal_entity_decl'} = sub { }; + } + } + +} + +sub characters { + my $self = shift; + if (defined $self->{Methods}->{'characters'}) { + $self->{Methods}->{'characters'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('characters') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'characters'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('characters') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'characters'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('characters') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'characters'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->characters(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'characters'} = sub { $handler->characters(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->characters(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'characters'} = sub { $handler->characters(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->characters(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'characters'} = sub { $handler->characters(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'characters'} = sub { }; + } + } + +} + +sub start_element { + my $self = shift; + if (defined $self->{Methods}->{'start_element'}) { + $self->{Methods}->{'start_element'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('start_element') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'start_element'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('start_element') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'start_element'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('start_element') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_element'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->start_element(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'start_element'} = sub { $handler->start_element(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->start_element(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'start_element'} = sub { $handler->start_element(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->start_element(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_element'} = sub { $handler->start_element(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'start_element'} = sub { }; + } + } + +} + +sub external_entity_decl { + my $self = shift; + if (defined $self->{Methods}->{'external_entity_decl'}) { + $self->{Methods}->{'external_entity_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DeclHandler'} and $method = $callbacks->{'DeclHandler'}->can('external_entity_decl') ) { + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'external_entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('external_entity_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'external_entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DeclHandler'} + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DeclHandler'}->external_entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'external_entity_decl'} = sub { $handler->external_entity_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->external_entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'external_entity_decl'} = sub { $handler->external_entity_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'external_entity_decl'} = sub { }; + } + } + +} + +sub xml_decl { + my $self = shift; + if (defined $self->{Methods}->{'xml_decl'}) { + $self->{Methods}->{'xml_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DTDHandler'} and $method = $callbacks->{'DTDHandler'}->can('xml_decl') ) { + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'xml_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('xml_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'xml_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DTDHandler'} + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DTDHandler'}->xml_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'xml_decl'} = sub { $handler->xml_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->xml_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'xml_decl'} = sub { $handler->xml_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'xml_decl'} = sub { }; + } + } + +} + +sub entity_decl { + my $self = shift; + if (defined $self->{Methods}->{'entity_decl'}) { + $self->{Methods}->{'entity_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DTDHandler'} and $method = $callbacks->{'DTDHandler'}->can('entity_decl') ) { + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('entity_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DTDHandler'} + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DTDHandler'}->entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'entity_decl'} = sub { $handler->entity_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'entity_decl'} = sub { $handler->entity_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'entity_decl'} = sub { }; + } + } + +} + +sub end_dtd { + my $self = shift; + if (defined $self->{Methods}->{'end_dtd'}) { + $self->{Methods}->{'end_dtd'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'LexicalHandler'} and $method = $callbacks->{'LexicalHandler'}->can('end_dtd') ) { + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'end_dtd'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('end_dtd') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_dtd'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'LexicalHandler'} + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'LexicalHandler'}->end_dtd(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'end_dtd'} = sub { $handler->end_dtd(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->end_dtd(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_dtd'} = sub { $handler->end_dtd(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'end_dtd'} = sub { }; + } + } + +} + +sub unparsed_entity_decl { + my $self = shift; + if (defined $self->{Methods}->{'unparsed_entity_decl'}) { + $self->{Methods}->{'unparsed_entity_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DTDHandler'} and $method = $callbacks->{'DTDHandler'}->can('unparsed_entity_decl') ) { + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'unparsed_entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('unparsed_entity_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'unparsed_entity_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DTDHandler'} + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DTDHandler'}->unparsed_entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'unparsed_entity_decl'} = sub { $handler->unparsed_entity_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->unparsed_entity_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'unparsed_entity_decl'} = sub { $handler->unparsed_entity_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'unparsed_entity_decl'} = sub { }; + } + } + +} + +sub processing_instruction { + my $self = shift; + if (defined $self->{Methods}->{'processing_instruction'}) { + $self->{Methods}->{'processing_instruction'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('processing_instruction') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'processing_instruction'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('processing_instruction') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'processing_instruction'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('processing_instruction') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'processing_instruction'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->processing_instruction(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'processing_instruction'} = sub { $handler->processing_instruction(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->processing_instruction(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'processing_instruction'} = sub { $handler->processing_instruction(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->processing_instruction(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'processing_instruction'} = sub { $handler->processing_instruction(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'processing_instruction'} = sub { }; + } + } + +} + +sub attribute_decl { + my $self = shift; + if (defined $self->{Methods}->{'attribute_decl'}) { + $self->{Methods}->{'attribute_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DeclHandler'} and $method = $callbacks->{'DeclHandler'}->can('attribute_decl') ) { + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'attribute_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('attribute_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'attribute_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DeclHandler'} + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DeclHandler'}->attribute_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'attribute_decl'} = sub { $handler->attribute_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->attribute_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'attribute_decl'} = sub { $handler->attribute_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'attribute_decl'} = sub { }; + } + } + +} + +sub fatal_error { + my $self = shift; + if (defined $self->{Methods}->{'fatal_error'}) { + $self->{Methods}->{'fatal_error'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ErrorHandler'} and $method = $callbacks->{'ErrorHandler'}->can('fatal_error') ) { + my $handler = $callbacks->{'ErrorHandler'}; + $self->{Methods}->{'fatal_error'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('fatal_error') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'fatal_error'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ErrorHandler'} + and $callbacks->{'ErrorHandler'}->can('AUTOLOAD') + and $callbacks->{'ErrorHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ErrorHandler'}->fatal_error(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ErrorHandler'}; + $self->{Methods}->{'fatal_error'} = sub { $handler->fatal_error(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->fatal_error(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'fatal_error'} = sub { $handler->fatal_error(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'fatal_error'} = sub { }; + } + } + +} + +sub end_cdata { + my $self = shift; + if (defined $self->{Methods}->{'end_cdata'}) { + $self->{Methods}->{'end_cdata'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('end_cdata') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'end_cdata'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'LexicalHandler'} and $method = $callbacks->{'LexicalHandler'}->can('end_cdata') ) { + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'end_cdata'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('end_cdata') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_cdata'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->end_cdata(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'end_cdata'} = sub { $handler->end_cdata(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'LexicalHandler'} + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'LexicalHandler'}->end_cdata(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'end_cdata'} = sub { $handler->end_cdata(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->end_cdata(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_cdata'} = sub { $handler->end_cdata(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'end_cdata'} = sub { }; + } + } + +} + +sub start_entity { + my $self = shift; + if (defined $self->{Methods}->{'start_entity'}) { + $self->{Methods}->{'start_entity'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'LexicalHandler'} and $method = $callbacks->{'LexicalHandler'}->can('start_entity') ) { + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'start_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('start_entity') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'LexicalHandler'} + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'LexicalHandler'}->start_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'start_entity'} = sub { $handler->start_entity(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->start_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_entity'} = sub { $handler->start_entity(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'start_entity'} = sub { }; + } + } + +} + +sub start_prefix_mapping { + my $self = shift; + if (defined $self->{Methods}->{'start_prefix_mapping'}) { + $self->{Methods}->{'start_prefix_mapping'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('start_prefix_mapping') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'start_prefix_mapping'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('start_prefix_mapping') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_prefix_mapping'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->start_prefix_mapping(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'start_prefix_mapping'} = sub { $handler->start_prefix_mapping(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->start_prefix_mapping(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_prefix_mapping'} = sub { $handler->start_prefix_mapping(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'start_prefix_mapping'} = sub { }; + } + } + +} + +sub error { + my $self = shift; + if (defined $self->{Methods}->{'error'}) { + $self->{Methods}->{'error'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ErrorHandler'} and $method = $callbacks->{'ErrorHandler'}->can('error') ) { + my $handler = $callbacks->{'ErrorHandler'}; + $self->{Methods}->{'error'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('error') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'error'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ErrorHandler'} + and $callbacks->{'ErrorHandler'}->can('AUTOLOAD') + and $callbacks->{'ErrorHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ErrorHandler'}->error(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ErrorHandler'}; + $self->{Methods}->{'error'} = sub { $handler->error(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->error(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'error'} = sub { $handler->error(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'error'} = sub { }; + } + } + +} + +sub start_document { + my $self = shift; + if (defined $self->{Methods}->{'start_document'}) { + $self->{Methods}->{'start_document'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('start_document') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'start_document'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('start_document') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'start_document'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('start_document') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_document'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->start_document(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'start_document'} = sub { $handler->start_document(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->start_document(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'start_document'} = sub { $handler->start_document(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->start_document(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_document'} = sub { $handler->start_document(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'start_document'} = sub { }; + } + } + +} + +sub ignorable_whitespace { + my $self = shift; + if (defined $self->{Methods}->{'ignorable_whitespace'}) { + $self->{Methods}->{'ignorable_whitespace'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('ignorable_whitespace') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'ignorable_whitespace'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('ignorable_whitespace') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'ignorable_whitespace'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('ignorable_whitespace') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'ignorable_whitespace'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->ignorable_whitespace(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'ignorable_whitespace'} = sub { $handler->ignorable_whitespace(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->ignorable_whitespace(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'ignorable_whitespace'} = sub { $handler->ignorable_whitespace(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->ignorable_whitespace(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'ignorable_whitespace'} = sub { $handler->ignorable_whitespace(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'ignorable_whitespace'} = sub { }; + } + } + +} + +sub end_document { + my $self = shift; + if (defined $self->{Methods}->{'end_document'}) { + $self->{Methods}->{'end_document'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('end_document') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'end_document'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('end_document') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'end_document'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('end_document') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_document'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->end_document(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'end_document'} = sub { $handler->end_document(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->end_document(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'end_document'} = sub { $handler->end_document(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->end_document(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_document'} = sub { $handler->end_document(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'end_document'} = sub { }; + } + } + +} + +sub start_cdata { + my $self = shift; + if (defined $self->{Methods}->{'start_cdata'}) { + $self->{Methods}->{'start_cdata'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('start_cdata') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'start_cdata'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'LexicalHandler'} and $method = $callbacks->{'LexicalHandler'}->can('start_cdata') ) { + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'start_cdata'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('start_cdata') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_cdata'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->start_cdata(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'start_cdata'} = sub { $handler->start_cdata(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'LexicalHandler'} + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'LexicalHandler'}->start_cdata(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'start_cdata'} = sub { $handler->start_cdata(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->start_cdata(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_cdata'} = sub { $handler->start_cdata(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'start_cdata'} = sub { }; + } + } + +} + +sub set_document_locator { + my $self = shift; + if (defined $self->{Methods}->{'set_document_locator'}) { + $self->{Methods}->{'set_document_locator'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('set_document_locator') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'set_document_locator'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('set_document_locator') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'set_document_locator'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('set_document_locator') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'set_document_locator'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->set_document_locator(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'set_document_locator'} = sub { $handler->set_document_locator(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->set_document_locator(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'set_document_locator'} = sub { $handler->set_document_locator(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->set_document_locator(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'set_document_locator'} = sub { $handler->set_document_locator(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'set_document_locator'} = sub { }; + } + } + +} + +sub attlist_decl { + my $self = shift; + if (defined $self->{Methods}->{'attlist_decl'}) { + $self->{Methods}->{'attlist_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DTDHandler'} and $method = $callbacks->{'DTDHandler'}->can('attlist_decl') ) { + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'attlist_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('attlist_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'attlist_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DTDHandler'} + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DTDHandler'}->attlist_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'attlist_decl'} = sub { $handler->attlist_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->attlist_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'attlist_decl'} = sub { $handler->attlist_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'attlist_decl'} = sub { }; + } + } + +} + +sub start_dtd { + my $self = shift; + if (defined $self->{Methods}->{'start_dtd'}) { + $self->{Methods}->{'start_dtd'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'LexicalHandler'} and $method = $callbacks->{'LexicalHandler'}->can('start_dtd') ) { + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'start_dtd'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('start_dtd') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_dtd'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'LexicalHandler'} + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'LexicalHandler'}->start_dtd(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'start_dtd'} = sub { $handler->start_dtd(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->start_dtd(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'start_dtd'} = sub { $handler->start_dtd(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'start_dtd'} = sub { }; + } + } + +} + +sub resolve_entity { + my $self = shift; + if (defined $self->{Methods}->{'resolve_entity'}) { + $self->{Methods}->{'resolve_entity'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'EntityResolver'} and $method = $callbacks->{'EntityResolver'}->can('resolve_entity') ) { + my $handler = $callbacks->{'EntityResolver'}; + $self->{Methods}->{'resolve_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('resolve_entity') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'resolve_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'EntityResolver'} + and $callbacks->{'EntityResolver'}->can('AUTOLOAD') + and $callbacks->{'EntityResolver'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'EntityResolver'}->resolve_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'EntityResolver'}; + $self->{Methods}->{'resolve_entity'} = sub { $handler->resolve_entity(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->resolve_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'resolve_entity'} = sub { $handler->resolve_entity(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'resolve_entity'} = sub { }; + } + } + +} + +sub entity_reference { + my $self = shift; + if (defined $self->{Methods}->{'entity_reference'}) { + $self->{Methods}->{'entity_reference'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('entity_reference') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'entity_reference'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('entity_reference') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'entity_reference'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->entity_reference(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'entity_reference'} = sub { $handler->entity_reference(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->entity_reference(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'entity_reference'} = sub { $handler->entity_reference(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'entity_reference'} = sub { }; + } + } + +} + +sub element_decl { + my $self = shift; + if (defined $self->{Methods}->{'element_decl'}) { + $self->{Methods}->{'element_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DeclHandler'} and $method = $callbacks->{'DeclHandler'}->can('element_decl') ) { + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'element_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('element_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'element_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DeclHandler'} + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') + and $callbacks->{'DeclHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DeclHandler'}->element_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DeclHandler'}; + $self->{Methods}->{'element_decl'} = sub { $handler->element_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->element_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'element_decl'} = sub { $handler->element_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'element_decl'} = sub { }; + } + } + +} + +sub notation_decl { + my $self = shift; + if (defined $self->{Methods}->{'notation_decl'}) { + $self->{Methods}->{'notation_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DTDHandler'} and $method = $callbacks->{'DTDHandler'}->can('notation_decl') ) { + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'notation_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('notation_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'notation_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DTDHandler'} + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DTDHandler'}->notation_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'notation_decl'} = sub { $handler->notation_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->notation_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'notation_decl'} = sub { $handler->notation_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'notation_decl'} = sub { }; + } + } + +} + +sub skipped_entity { + my $self = shift; + if (defined $self->{Methods}->{'skipped_entity'}) { + $self->{Methods}->{'skipped_entity'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('skipped_entity') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'skipped_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('skipped_entity') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'skipped_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->skipped_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'skipped_entity'} = sub { $handler->skipped_entity(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->skipped_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'skipped_entity'} = sub { $handler->skipped_entity(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'skipped_entity'} = sub { }; + } + } + +} + +sub end_element { + my $self = shift; + if (defined $self->{Methods}->{'end_element'}) { + $self->{Methods}->{'end_element'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ContentHandler'} and $method = $callbacks->{'ContentHandler'}->can('end_element') ) { + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'end_element'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('end_element') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'end_element'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('end_element') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_element'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ContentHandler'} + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') + and $callbacks->{'ContentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ContentHandler'}->end_element(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ContentHandler'}; + $self->{Methods}->{'end_element'} = sub { $handler->end_element(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->end_element(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'end_element'} = sub { $handler->end_element(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->end_element(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_element'} = sub { $handler->end_element(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'end_element'} = sub { }; + } + } + +} + +sub doctype_decl { + my $self = shift; + if (defined $self->{Methods}->{'doctype_decl'}) { + $self->{Methods}->{'doctype_decl'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DTDHandler'} and $method = $callbacks->{'DTDHandler'}->can('doctype_decl') ) { + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'doctype_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('doctype_decl') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'doctype_decl'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DTDHandler'} + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') + and $callbacks->{'DTDHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DTDHandler'}->doctype_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DTDHandler'}; + $self->{Methods}->{'doctype_decl'} = sub { $handler->doctype_decl(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->doctype_decl(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'doctype_decl'} = sub { $handler->doctype_decl(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'doctype_decl'} = sub { }; + } + } + +} + +sub comment { + my $self = shift; + if (defined $self->{Methods}->{'comment'}) { + $self->{Methods}->{'comment'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'DocumentHandler'} and $method = $callbacks->{'DocumentHandler'}->can('comment') ) { + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'comment'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'LexicalHandler'} and $method = $callbacks->{'LexicalHandler'}->can('comment') ) { + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'comment'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('comment') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'comment'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'DocumentHandler'} + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') + and $callbacks->{'DocumentHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'DocumentHandler'}->comment(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'DocumentHandler'}; + $self->{Methods}->{'comment'} = sub { $handler->comment(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'LexicalHandler'} + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'LexicalHandler'}->comment(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'comment'} = sub { $handler->comment(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->comment(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'comment'} = sub { $handler->comment(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'comment'} = sub { }; + } + } + +} + +sub end_entity { + my $self = shift; + if (defined $self->{Methods}->{'end_entity'}) { + $self->{Methods}->{'end_entity'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'LexicalHandler'} and $method = $callbacks->{'LexicalHandler'}->can('end_entity') ) { + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'end_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('end_entity') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_entity'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'LexicalHandler'} + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') + and $callbacks->{'LexicalHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'LexicalHandler'}->end_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'LexicalHandler'}; + $self->{Methods}->{'end_entity'} = sub { $handler->end_entity(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->end_entity(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'end_entity'} = sub { $handler->end_entity(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'end_entity'} = sub { }; + } + } + +} + +sub warning { + my $self = shift; + if (defined $self->{Methods}->{'warning'}) { + $self->{Methods}->{'warning'}->(@_); + } + else { + my $method; + my $callbacks; + if (exists $self->{ParseOptions}) { + $callbacks = $self->{ParseOptions}; + } + else { + $callbacks = $self; + } + if (0) { # dummy to make elsif's below compile + } + elsif (defined $callbacks->{'ErrorHandler'} and $method = $callbacks->{'ErrorHandler'}->can('warning') ) { + my $handler = $callbacks->{'ErrorHandler'}; + $self->{Methods}->{'warning'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'Handler'} and $method = $callbacks->{'Handler'}->can('warning') ) { + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'warning'} = sub { $method->($handler, @_) }; + return $method->($handler, @_); + } + elsif (defined $callbacks->{'ErrorHandler'} + and $callbacks->{'ErrorHandler'}->can('AUTOLOAD') + and $callbacks->{'ErrorHandler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'ErrorHandler'}->warning(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'ErrorHandler'}; + $self->{Methods}->{'warning'} = sub { $handler->warning(@_) }; + } + return $res; + } + elsif (defined $callbacks->{'Handler'} + and $callbacks->{'Handler'}->can('AUTOLOAD') + and $callbacks->{'Handler'}->can('AUTOLOAD') ne (UNIVERSAL->can('AUTOLOAD') || '') + ) + { + my $res = eval { $callbacks->{'Handler'}->warning(@_) }; + if ($@) { + die $@; + } + else { + # I think there's a buggette here... + # if the first call throws an exception, we don't set it up right. + # Not fatal, but we might want to address it. + my $handler = $callbacks->{'Handler'}; + $self->{Methods}->{'warning'} = sub { $handler->warning(@_) }; + } + return $res; + } + else { + $self->{Methods}->{'warning'} = sub { }; + } + } + +} + +#-------------------------------------------------------------------# +# Class->new(%options) +#-------------------------------------------------------------------# +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $options = ($#_ == 0) ? shift : { @_ }; + + unless ( defined( $options->{Handler} ) or + defined( $options->{ContentHandler} ) or + defined( $options->{DTDHandler} ) or + defined( $options->{DocumentHandler} ) or + defined( $options->{LexicalHandler} ) or + defined( $options->{ErrorHandler} ) or + defined( $options->{DeclHandler} ) ) { + + $options->{Handler} = XML::SAX::Base::NoHandler->new; + } + + my $self = bless $options, $class; + # turn NS processing on by default + $self->set_feature('http://xml.org/sax/features/namespaces', 1); + return $self; +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# $p->parse(%options) +#-------------------------------------------------------------------# +sub parse { + my $self = shift; + my $parse_options = $self->get_options(@_); + local $self->{ParseOptions} = $parse_options; + if ($self->{Parent}) { # calling parse on a filter for some reason + return $self->{Parent}->parse($parse_options); + } + else { + my $method; + if (defined $parse_options->{Source}{CharacterStream} and $method = $self->can('_parse_characterstream')) { + warn("parse charstream???\n"); + return $method->($self, $parse_options->{Source}{CharacterStream}); + } + elsif (defined $parse_options->{Source}{ByteStream} and $method = $self->can('_parse_bytestream')) { + return $method->($self, $parse_options->{Source}{ByteStream}); + } + elsif (defined $parse_options->{Source}{String} and $method = $self->can('_parse_string')) { + return $method->($self, $parse_options->{Source}{String}); + } + elsif (defined $parse_options->{Source}{SystemId} and $method = $self->can('_parse_systemid')) { + return $method->($self, $parse_options->{Source}{SystemId}); + } + else { + die "No _parse_* routine defined on this driver (If it is a filter, remember to set the Parent property. If you call the parse() method, make sure to set a Source. You may want to call parse_uri, parse_string or parse_file instead.) [$self]"; + } + } +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# $p->parse_file(%options) +#-------------------------------------------------------------------# +sub parse_file { + my $self = shift; + my $file = shift; + return $self->parse_uri($file, @_) if ref(\$file) eq 'SCALAR'; + my $parse_options = $self->get_options(@_); + $parse_options->{Source}{ByteStream} = $file; + return $self->parse($parse_options); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# $p->parse_uri(%options) +#-------------------------------------------------------------------# +sub parse_uri { + my $self = shift; + my $file = shift; + my $parse_options = $self->get_options(@_); + $parse_options->{Source}{SystemId} = $file; + return $self->parse($parse_options); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# $p->parse_string(%options) +#-------------------------------------------------------------------# +sub parse_string { + my $self = shift; + my $string = shift; + my $parse_options = $self->get_options(@_); + $parse_options->{Source}{String} = $string; + return $self->parse($parse_options); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_options +#-------------------------------------------------------------------# +sub get_options { + my $self = shift; + + if (@_ == 1) { + return { %$self, %{$_[0]} }; + } else { + return { %$self, @_ }; + } +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_features +#-------------------------------------------------------------------# +sub get_features { + return ( + 'http://xml.org/sax/features/external-general-entities' => undef, + 'http://xml.org/sax/features/external-parameter-entities' => undef, + 'http://xml.org/sax/features/is-standalone' => undef, + 'http://xml.org/sax/features/lexical-handler' => undef, + 'http://xml.org/sax/features/parameter-entities' => undef, + 'http://xml.org/sax/features/namespaces' => 1, + 'http://xml.org/sax/features/namespace-prefixes' => 0, + 'http://xml.org/sax/features/string-interning' => undef, + 'http://xml.org/sax/features/use-attributes2' => undef, + 'http://xml.org/sax/features/use-locator2' => undef, + 'http://xml.org/sax/features/validation' => undef, + + 'http://xml.org/sax/properties/dom-node' => undef, + 'http://xml.org/sax/properties/xml-string' => undef, + ); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_feature +#-------------------------------------------------------------------# +sub get_feature { + my $self = shift; + my $feat = shift; + + # check %FEATURES to see if it's there, and return it if so + # throw XML::SAX::Exception::NotRecognized if it's not there + # throw XML::SAX::Exception::NotSupported if it's there but we + # don't support it + + my %features = $self->get_features(); + if (exists $features{$feat}) { + my %supported = map { $_ => 1 } $self->supported_features(); + if ($supported{$feat}) { + return $self->{__PACKAGE__ . "::Features"}{$feat}; + } + throw XML::SAX::Exception::NotSupported( + Message => "The feature '$feat' is not supported by " . ref($self), + Exception => undef, + ); + } + throw XML::SAX::Exception::NotRecognized( + Message => "The feature '$feat' is not recognized by " . ref($self), + Exception => undef, + ); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# set_feature +#-------------------------------------------------------------------# +sub set_feature { + my $self = shift; + my $feat = shift; + my $value = shift; + # check %FEATURES to see if it's there, and set it if so + # throw XML::SAX::Exception::NotRecognized if it's not there + # throw XML::SAX::Exception::NotSupported if it's there but we + # don't support it + + my %features = $self->get_features(); + if (exists $features{$feat}) { + my %supported = map { $_ => 1 } $self->supported_features(); + if ($supported{$feat}) { + return $self->{__PACKAGE__ . "::Features"}{$feat} = $value; + } + throw XML::SAX::Exception::NotSupported( + Message => "The feature '$feat' is not supported by " . ref($self), + Exception => undef, + ); + } + throw XML::SAX::Exception::NotRecognized( + Message => "The feature '$feat' is not recognized by " . ref($self), + Exception => undef, + ); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# get_handler and friends +#-------------------------------------------------------------------# +sub get_handler { + my $self = shift; + my $handler_type = shift; + $handler_type ||= 'Handler'; + return defined( $self->{$handler_type} ) ? $self->{$handler_type} : undef; +} + +sub get_document_handler { + my $self = shift; + return $self->get_handler('DocumentHandler', @_); +} + +sub get_content_handler { + my $self = shift; + return $self->get_handler('ContentHandler', @_); +} + +sub get_dtd_handler { + my $self = shift; + return $self->get_handler('DTDHandler', @_); +} + +sub get_lexical_handler { + my $self = shift; + return $self->get_handler('LexicalHandler', @_); +} + +sub get_decl_handler { + my $self = shift; + return $self->get_handler('DeclHandler', @_); +} + +sub get_error_handler { + my $self = shift; + return $self->get_handler('ErrorHandler', @_); +} + +sub get_entity_resolver { + my $self = shift; + return $self->get_handler('EntityResolver', @_); +} +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# set_handler and friends +#-------------------------------------------------------------------# +sub set_handler { + my $self = shift; + my ($new_handler, $handler_type) = reverse @_; + $handler_type ||= 'Handler'; + $self->{Methods} = {} if $self->{Methods}; + $self->{$handler_type} = $new_handler; + $self->{ParseOptions}->{$handler_type} = $new_handler; + return 1; +} + +sub set_document_handler { + my $self = shift; + return $self->set_handler('DocumentHandler', @_); +} + +sub set_content_handler { + my $self = shift; + return $self->set_handler('ContentHandler', @_); +} +sub set_dtd_handler { + my $self = shift; + return $self->set_handler('DTDHandler', @_); +} +sub set_lexical_handler { + my $self = shift; + return $self->set_handler('LexicalHandler', @_); +} +sub set_decl_handler { + my $self = shift; + return $self->set_handler('DeclHandler', @_); +} +sub set_error_handler { + my $self = shift; + return $self->set_handler('ErrorHandler', @_); +} +sub set_entity_resolver { + my $self = shift; + return $self->set_handler('EntityResolver', @_); +} + +#-------------------------------------------------------------------# + +#-------------------------------------------------------------------# +# supported_features +#-------------------------------------------------------------------# +sub supported_features { + my $self = shift; + # Only namespaces are required by all parsers + return ( + 'http://xml.org/sax/features/namespaces', + ); +} +#-------------------------------------------------------------------# + +sub no_op { + # this space intentionally blank +} + + +package XML::SAX::Base::NoHandler; + +# we need a fake handler that doesn't implement anything, this +# simplifies the code a lot (though given the recent changes, +# it may be better to do without) +sub new { + #warn "no handler called\n"; + return bless {}; +} + +1; + +__END__ + +=head1 NAME + +XML::SAX::Base - Base class SAX Drivers and Filters + +=head1 SYNOPSIS + + package MyFilter; + use XML::SAX::Base; + @ISA = ('XML::SAX::Base'); + +=head1 DESCRIPTION + +This module has a very simple task - to be a base class for PerlSAX +drivers and filters. It's default behaviour is to pass the input directly +to the output unchanged. It can be useful to use this module as a base class +so you don't have to, for example, implement the characters() callback. + +The main advantages that it provides are easy dispatching of events the right +way (ie it takes care for you of checking that the handler has implemented +that method, or has defined an AUTOLOAD), and the guarantee that filters +will pass along events that they aren't implementing to handlers downstream +that might nevertheless be interested in them. + +=head1 WRITING SAX DRIVERS AND FILTERS + +Writing SAX Filters is tremendously easy: all you need to do is +inherit from this module, and define the events you want to handle. A +more detailed explanation can be found at +http://www.xml.com/pub/a/2001/10/10/sax-filters.html. + +Writing Drivers is equally simple. The one thing you need to pay +attention to is B<NOT> to call events yourself (this applies to Filters +as well). For instance: + + package MyFilter; + use base qw(XML::SAX::Base); + + sub start_element { + my $self = shift; + my $data = shift; + # do something + $self->{Handler}->start_element($data); # BAD + } + +The above example works well as precisely that: an example. But it has +several faults: 1) it doesn't test to see whether the handler defines +start_element. Perhaps it doesn't want to see that event, in which +case you shouldn't throw it (otherwise it'll die). 2) it doesn't check +ContentHandler and then Handler (ie it doesn't look to see that the +user hasn't requested events on a specific handler, and if not on the +default one), 3) if it did check all that, not only would the code be +cumbersome (see this module's source to get an idea) but it would also +probably have to check for a DocumentHandler (in case this were SAX1) +and for AUTOLOADs potentially defined in all these packages. As you can +tell, that would be fairly painful. Instead of going through that, +simply remember to use code similar to the following instead: + + package MyFilter; + use base qw(XML::SAX::Base); + + sub start_element { + my $self = shift; + my $data = shift; + # do something to filter + $self->SUPER::start_element($data); # GOOD (and easy) ! + } + +This way, once you've done your job you hand the ball back to +XML::SAX::Base and it takes care of all those problems for you! + +Note that the above example doesn't apply to filters only, drivers +will benefit from the exact same feature. + +=head1 METHODS + +A number of methods are defined within this class for the purpose of +inheritance. Some probably don't need to be overridden (eg parse_file) +but some clearly should be (eg parse). Options for these methods are +described in the PerlSAX2 specification available from +http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/perl-xml/libxml-perl/doc/sax-2.0.html?rev=HEAD&content-type=text/html. + +=over 4 + +=item * parse + +The parse method is the main entry point to parsing documents. Internally +the parse method will detect what type of "thing" you are parsing, and +call the appropriate method in your implementation class. Here is the +mapping table of what is in the Source options (see the Perl SAX 2.0 +specification for the meaning of these values): + + Source Contains parse() calls + =============== ============= + CharacterStream (*) _parse_characterstream($stream, $options) + ByteStream _parse_bytestream($stream, $options) + String _parse_string($string, $options) + SystemId _parse_systemid($string, $options) + +However note that these methods may not be sensible if your driver class +is not for parsing XML. An example might be a DBI driver that generates +XML/SAX from a database table. If that is the case, you likely want to +write your own parse() method. + +Also note that the Source may contain both a PublicId entry, and an +Encoding entry. To get at these, examine $options->{Source} as passed +to your method. + +(*) A CharacterStream is a filehandle that does not need any encoding +translation done on it. This is implemented as a regular filehandle +and only works under Perl 5.7.2 or higher using PerlIO. To get a single +character, or number of characters from it, use the perl core read() +function. To get a single byte from it (or number of bytes), you can +use sysread(). The encoding of the stream should be in the Encoding +entry for the Source. + +=item * parse_file, parse_uri, parse_string + +These are all convenience variations on parse(), and in fact simply +set up the options before calling it. You probably don't need to +override these. + +=item * get_options + +This is a convenience method to get options in SAX2 style, or more +generically either as hashes or as hashrefs (it returns a hashref). +You will probably want to use this method in your own implementations +of parse() and of new(). + +=item * get_feature, set_feature + +These simply get and set features, and throw the +appropriate exceptions defined in the specification if need be. + +If your subclass defines features not defined in this one, +then you should override these methods in such a way that they check for +your features first, and then call the base class's methods +for features not defined by your class. An example would be: + + sub get_feature { + my $self = shift; + my $feat = shift; + if (exists $MY_FEATURES{$feat}) { + # handle the feature in various ways + } + else { + return $self->SUPER::get_feature($feat); + } + } + +Currently this part is unimplemented. + + +=item * set_handler + +This method takes a handler type (Handler, ContentHandler, etc.) and a +handler object as arguments, and changes the current handler for that +handler type, while taking care of resetting the internal state that +needs to be reset. This allows one to change a handler during parse +without running into problems (changing it on the parser object +directly will most likely cause trouble). + +=item * set_document_handler, set_content_handler, set_dtd_handler, set_lexical_handler, set_decl_handler, set_error_handler, set_entity_resolver + +These are just simple wrappers around the former method, and take a +handler object as their argument. Internally they simply call +set_handler with the correct arguments. + +=item * get_handler + +The inverse of set_handler, this method takes a an optional string containing a handler type (DTDHandler, +ContentHandler, etc. 'Handler' is used if no type is passed). It returns a reference to the object that implements +that that class, or undef if that handler type is not set for the current driver/filter. + +=item * get_document_handler, get_content_handler, get_dtd_handler, get_lexical_handler, get_decl_handler, +get_error_handler, get_entity_resolver + +These are just simple wrappers around the get_handler() method, and take no arguments. Internally +they simply call get_handler with the correct handler type name. + +=back + +It would be rather useless to describe all the methods that this +module implements here. They are all the methods supported in SAX1 and +SAX2. In case your memory is a little short, here is a list. The +apparent duplicates are there so that both versions of SAX can be +supported. + +=over 4 + +=item * start_document + +=item * end_document + +=item * start_element + +=item * start_document + +=item * end_document + +=item * start_element + +=item * end_element + +=item * characters + +=item * processing_instruction + +=item * ignorable_whitespace + +=item * set_document_locator + +=item * start_prefix_mapping + +=item * end_prefix_mapping + +=item * skipped_entity + +=item * start_cdata + +=item * end_cdata + +=item * comment + +=item * entity_reference + +=item * notation_decl + +=item * unparsed_entity_decl + +=item * element_decl + +=item * attlist_decl + +=item * doctype_decl + +=item * xml_decl + +=item * entity_decl + +=item * attribute_decl + +=item * internal_entity_decl + +=item * external_entity_decl + +=item * resolve_entity + +=item * start_dtd + +=item * end_dtd + +=item * start_entity + +=item * end_entity + +=item * warning + +=item * error + +=item * fatal_error + +=back + +=head1 TODO + + - more tests + - conform to the "SAX Filters" and "Java and DOM compatibility" + sections of the SAX2 document. + +=head1 AUTHOR + +Kip Hampton (khampton@totalcinema.com) did most of the work, after porting +it from XML::Filter::Base. + +Robin Berjon (robin@knowscape.com) pitched in with patches to make it +usable as a base for drivers as well as filters, along with other patches. + +Matt Sergeant (matt@sergeant.org) wrote the original XML::Filter::Base, +and patched a few things here and there, and imported it into +the XML::SAX distribution. + +=head1 SEE ALSO + +L<XML::SAX> + +=cut + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/DocumentLocator.pm b/Master/tlpkg/tlperl/lib/XML/SAX/DocumentLocator.pm new file mode 100755 index 00000000000..2d4811b12ba --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/DocumentLocator.pm @@ -0,0 +1,134 @@ +# $Id: DocumentLocator.pm,v 1.3 2005-10-14 20:31:20 matt Exp $ + +package XML::SAX::DocumentLocator; +use strict; + +sub new { + my $class = shift; + my %object; + tie %object, $class, @_; + + return bless \%object, $class; +} + +sub TIEHASH { + my $class = shift; + my ($pubmeth, $sysmeth, $linemeth, $colmeth, $encmeth, $xmlvmeth) = @_; + return bless { + pubmeth => $pubmeth, + sysmeth => $sysmeth, + linemeth => $linemeth, + colmeth => $colmeth, + encmeth => $encmeth, + xmlvmeth => $xmlvmeth, + }, $class; +} + +sub FETCH { + my ($self, $key) = @_; + my $method; + if ($key eq 'PublicId') { + $method = $self->{pubmeth}; + } + elsif ($key eq 'SystemId') { + $method = $self->{sysmeth}; + } + elsif ($key eq 'LineNumber') { + $method = $self->{linemeth}; + } + elsif ($key eq 'ColumnNumber') { + $method = $self->{colmeth}; + } + elsif ($key eq 'Encoding') { + $method = $self->{encmeth}; + } + elsif ($key eq 'XMLVersion') { + $method = $self->{xmlvmeth}; + } + if ($method) { + my $value = $method->($key); + return $value; + } + return undef; +} + +sub EXISTS { + my ($self, $key) = @_; + if ($key =~ /^(PublicId|SystemId|LineNumber|ColumnNumber|Encoding|XMLVersion)$/) { + return 1; + } + return 0; +} + +sub STORE { + my ($self, $key, $value) = @_; +} + +sub DELETE { + my ($self, $key) = @_; +} + +sub CLEAR { + my ($self) = @_; +} + +sub FIRSTKEY { + my ($self) = @_; + # assignment resets. + $self->{keys} = { + PublicId => 1, + SystemId => 1, + LineNumber => 1, + ColumnNumber => 1, + Encoding => 1, + XMLVersion => 1, + }; + return each %{$self->{keys}}; +} + +sub NEXTKEY { + my ($self, $lastkey) = @_; + return each %{$self->{keys}}; +} + +1; +__END__ + +=head1 NAME + +XML::SAX::DocumentLocator - Helper class for document locators + +=head1 SYNOPSIS + + my $locator = XML::SAX::DocumentLocator->new( + sub { $object->get_public_id }, + sub { $object->get_system_id }, + sub { $reader->current_line }, + sub { $reader->current_column }, + sub { $reader->get_encoding }, + sub { $reader->get_xml_version }, + ); + +=head1 DESCRIPTION + +This module gives you a tied hash reference that calls the +specified closures when asked for PublicId, SystemId, +LineNumber and ColumnNumber. + +It is useful for writing SAX Parsers so that you don't have +to constantly update the line numbers in a hash reference on +the object you pass to set_document_locator(). See the source +code for XML::SAX::PurePerl for a usage example. + +=head1 API + +There is only 1 method: C<new>. Simply pass it a list of +closures that when called will return the PublicId, the +SystemId, the LineNumber, the ColumnNumber, the Encoding +and the XMLVersion respectively. + +The closures are passed a single parameter, the key being +requested. But you're free to ignore that. + +=cut + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/Exception.pm b/Master/tlpkg/tlperl/lib/XML/SAX/Exception.pm new file mode 100755 index 00000000000..79910205804 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/Exception.pm @@ -0,0 +1,126 @@ +package XML::SAX::Exception; + +use strict; + +use overload '""' => "stringify", + 'fallback' => 1; + +use vars qw/$StackTrace $VERSION/; +$VERSION = '1.01'; +use Carp; + +$StackTrace = $ENV{XML_DEBUG} || 0; + +# Other exception classes: + +@XML::SAX::Exception::NotRecognized::ISA = ('XML::SAX::Exception'); +@XML::SAX::Exception::NotSupported::ISA = ('XML::SAX::Exception'); +@XML::SAX::Exception::Parse::ISA = ('XML::SAX::Exception'); + + +sub throw { + my $class = shift; + if (ref($class)) { + die $class; + } + die $class->new(@_); +} + +sub new { + my $class = shift; + my %opts = @_; + confess "Invalid options: " . join(', ', keys %opts) unless exists $opts{Message}; + + bless { ($StackTrace ? (StackTrace => stacktrace()) : ()), %opts }, + $class; +} + +sub stringify { + my $self = shift; + local $^W; + my $error; + if (exists $self->{LineNumber}) { + $error = $self->{Message} . " [Ln: " . $self->{LineNumber} . + ", Col: " . $self->{ColumnNumber} . "]"; + } + else { + $error = $self->{Message}; + } + if ($StackTrace) { + $error .= stackstring($self->{StackTrace}); + } + $error .= "\n"; + return $error; +} + +sub stacktrace { + my $i = 2; + my @fulltrace; + while (my @trace = caller($i++)) { + my %hash; + @hash{qw(Package Filename Line)} = @trace[0..2]; + push @fulltrace, \%hash; + } + return \@fulltrace; +} + +sub stackstring { + my $stacktrace = shift; + my $string = "\nFrom:\n"; + foreach my $current (@$stacktrace) { + $string .= $current->{Filename} . " Line: " . $current->{Line} . "\n"; + } + return $string; +} + +1; + +__END__ + +=head1 NAME + +XML::SAX::Exception - Exception classes for XML::SAX + +=head1 SYNOPSIS + + throw XML::SAX::Exception::NotSupported( + Message => "The foo feature is not supported", + ); + +=head1 DESCRIPTION + +This module is the base class for all SAX Exceptions, those defined in +the spec as well as those that one may create for one's own SAX errors. + +There are three subclasses included, corresponding to those of the SAX +spec: + + XML::SAX::Exception::NotSupported + XML::SAX::Exception::NotRecognized + XML::SAX::Exception::Parse + +Use them wherever you want, and as much as possible when you encounter +such errors. SAX is meant to use exceptions as much as possible to +flag problems. + +=head1 CREATING NEW EXCEPTION CLASSES + +All you need to do to create a new exception class is: + + @XML::SAX::Exception::MyException::ISA = ('XML::SAX::Exception') + +The given package doesn't need to exist, it'll behave correctly this +way. If your exception refines an existing exception class, then you +may also inherit from that instead of from the base class. + +=head1 THROWING EXCEPTIONS + +This is as simple as exemplified in the SYNOPSIS. In fact, there's +nothing more to know. All you have to do is: + + throw XML::SAX::Exception::MyException( Message => 'Something went wrong' ); + +and voila, you've thrown an exception which can be caught in an eval block. + +=cut + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/Intro.pod b/Master/tlpkg/tlperl/lib/XML/SAX/Intro.pod new file mode 100755 index 00000000000..dea71cf7103 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/Intro.pod @@ -0,0 +1,407 @@ +=head1 NAME + +XML::SAX::Intro - An Introduction to SAX Parsing with Perl + +=head1 Introduction + +XML::SAX is a new way to work with XML Parsers in Perl. In this article +we'll discuss why you should be using SAX, why you should be using +XML::SAX, and we'll see some of the finer implementation details. The +text below assumes some familiarity with callback, or push based +parsing, but if you are unfamiliar with these techniques then a good +place to start is Kip Hampton's excellent series of articles on XML.com. + +=head1 Replacing XML::Parser + +The de-facto way of parsing XML under perl is to use Larry Wall and +Clark Cooper's XML::Parser. This module is a Perl and XS wrapper around +the expat XML parser library by James Clark. It has been a hugely +successful project, but suffers from a couple of rather major flaws. +Firstly it is a proprietary API, designed before the SAX API was +conceived, which means that it is not easily replaceable by other +streaming parsers. Secondly it's callbacks are subrefs. This doesn't +sound like much of an issue, but unfortunately leads to code like: + + sub handle_start { + my ($e, $el, %attrs) = @_; + if ($el eq 'foo') { + $e->{inside_foo}++; # BAD! $e is an XML::Parser::Expat object. + } + } + +As you can see, we're using the $e object to hold our state +information, which is a bad idea because we don't own that object - we +didn't create it. It's an internal object of XML::Parser, that happens +to be a hashref. We could all too easily overwrite XML::Parser internal +state variables by using this, or Clark could change it to an array ref +(not that he would, because it would break so much code, but he could). + +The only way currently with XML::Parser to safely maintain state is to +use a closure: + + my $state = MyState->new(); + $parser->setHandlers(Start => sub { handle_start($state, @_) }); + +This closure traps the $state variable, which now gets passed as the +first parameter to your callback. Unfortunately very few people use +this technique, as it is not documented in the XML::Parser POD files. + +Another reason you might not want to use XML::Parser is because you +need some feature that it doesn't provide (such as validation), or you +might need to use a library that doesn't use expat, due to it not being +installed on your system, or due to having a restrictive ISP. Using SAX +allows you to work around these restrictions. + +=head1 Introducing SAX + +SAX stands for the Simple API for XML. And simple it really is. +Constructing a SAX parser and passing events to handlers is done as +simply as: + + use XML::SAX; + use MySAXHandler; + + my $parser = XML::SAX::ParserFactory->parser( + Handler => MySAXHandler->new + ); + + $parser->parse_uri("foo.xml"); + +The important concept to grasp here is that SAX uses a factory class +called XML::SAX::ParserFactory to create a new parser instance. The +reason for this is so that you can support other underlying +parser implementations for different feature sets. This is one thing +that XML::Parser has always sorely lacked. + +In the code above we see the parse_uri method used, but we could +have equally well +called parse_file, parse_string, or parse(). Please see XML::SAX::Base +for what these methods take as parameters, but don't be fooled into +believing parse_file takes a filename. No, it takes a file handle, a +glob, or a subclass of IO::Handle. Beware. + +SAX works very similarly to XML::Parser's default callback method, +except it has one major difference: rather than setting individual +callbacks, you create a new class in which to recieve the callbacks. +Each callback is called as a method call on an instance of that handler +class. An example will best demonstrate this: + + package MySAXHandler; + use base qw(XML::SAX::Base); + + sub start_document { + my ($self, $doc) = @_; + # process document start event + } + + sub start_element { + my ($self, $el) = @_; + # process element start event + } + +Now, when we instantiate this as above, and parse some XML with this as +the handler, the methods start_document and start_element will be +called as method calls, so this would be the equivalent of directly +calling: + + $object->start_element($el); + +Notice how this is different to XML::Parser's calling style, which +calls: + + start_element($e, $name, %attribs); + +It's the difference between function calling and method calling which +allows you to subclass SAX handlers which contributes to SAX being a +powerful solution. + +As you can see, unlike XML::Parser, we have to define a new package in +which to do our processing (there are hacks you can do to make this +uneccessary, but I'll leave figuring those out to the experts). The +biggest benefit of this is that you maintain your own state variable +($self in the above example) thus freeing you of the concerns listed +above. It is also an improvement in maintainability - you can place the +code in a separate file if you wish to, and your callback methods are +always called the same thing, rather than having to choose a suitable +name for them as you had to with XML::Parser. This is an obvious win. + +SAX parsers are also very flexible in how you pass a handler to them. +You can use a constructor parameter as we saw above, or we can pass the +handler directly in the call to one of the parse methods: + + $parser->parse(Handler => $handler, + Source => { SystemId => "foo.xml" }); + # or... + $parser->parse_file($fh, Handler => $handler); + +This flexibility allows for one parser to be used in many different +scenarios throughout your script (though one shouldn't feel pressure to +use this method, as parser construction is generally not a time +consuming process). + +=head1 Callback Parameters + +The only other thing you need to know to understand basic SAX is the +structure of the parameters passed to each of the callbacks. In +XML::Parser, all parameters are passed as multiple options to the +callbacks, so for example the Start callback would be called as +my_start($e, $name, %attributes), and the PI callback would be called +as my_processing_instruction($e, $target, $data). In SAX, every +callback is passed a hash reference, containing entries that define our +"node". The key callbacks and the structures they receive are: + +=head2 start_element + +The start_element handler is called whenever a parser sees an opening +tag. It is passed an element structure consisting of: + +=over 4 + +=item LocalName + +The name of the element minus any namespace prefix it may +have come with in the document. + +=item NamespaceURI + +The URI of the namespace associated with this element, +or the empty string for none. + +=item Attributes + +A set of attributes as described below. + +=item Name + +The name of the element as it was seen in the document (i.e. +including any prefix associated with it) + +=item Prefix + +The prefix used to qualify this element's namespace, or the +empty string if none. + +=back + +The B<Attributes> are a hash reference, keyed by what we have called +"James Clark" notation. This means that the attribute name has been +expanded to include any associated namespace URI, and put together as +{ns}name, where "ns" is the expanded namespace URI of the attribute if +and only if the attribute had a prefix, and "name" is the LocalName of +the attribute. + +The value of each entry in the attributes hash is another hash +structure consisting of: + +=over 4 + +=item LocalName + +The name of the attribute minus any namespace prefix it may have +come with in the document. + +=item NamespaceURI + +The URI of the namespace associated with this attribute. If the +attribute had no prefix, then this consists of just the empty string. + +=item Name + +The attribute's name as it appeared in the document, including any +namespace prefix. + +=item Prefix + +The prefix used to qualify this attribute's namepace, or the +empty string if none. + +=item Value + +The value of the attribute. + +=back + +So a full example, as output by Data::Dumper might be: + + .... + +=head2 end_element + +The end_element handler is called either when a parser sees a closing +tag, or after start_element has been called for an empty element (do +note however that a parser may if it is so inclined call characters +with an empty string when it sees an empty element. There is no simple +way in SAX to determine if the parser in fact saw an empty element, a +start and end element with no content.. + +The end_element handler receives exactly the same structure as +start_element, minus the Attributes entry. One must note though that it +should not be a reference to the same data as start_element receives, +so you may change the values in start_element but this will not affect +the values later seen by end_element. + +=head2 characters + +The characters callback may be called in serveral circumstances. The +most obvious one is when seeing ordinary character data in the markup. +But it is also called for text in a CDATA section, and is also called +in other situations. A SAX parser has to make no guarantees whatsoever +about how many times it may call characters for a stretch of text in an +XML document - it may call once, or it may call once for every +character in the text. In order to work around this it is often +important for the SAX developer to use a bundling technique, where text +is gathered up and processed in one of the other callbacks. This is not +always necessary, but it is a worthwhile technique to learn, which we +will cover in XML::SAX::Advanced (when I get around to writing it). + +The characters handler is called with a very simple structure - a hash +reference consisting of just one entry: + +=over 4 + +=item Data + +The text data that was received. + +=back + +=head2 comment + +The comment callback is called for comment text. Unlike with +C<characters()>, the comment callback *must* be invoked just once for an +entire comment string. It receives a single simple structure - a hash +reference containing just one entry: + +=over 4 + +=item Data + +The text of the comment. + +=back + +=head2 processing_instruction + +The processing instruction handler is called for all processing +instructions in the document. Note that these processing instructions +may appear before the document root element, or after it, or anywhere +where text and elements would normally appear within the document, +according to the XML specification. + +The handler is passed a structure containing just two entries: + +=over 4 + +=item Target + +The target of the processing instrcution + +=item Data + +The text data in the processing instruction. Can be an empty +string for a processing instruction that has no data element. +For example E<lt>?wiggle?E<gt> is a perfectly valid processing instruction. + +=back + +=head1 Tip of the iceberg + +What we have discussed above is really the tip of the SAX iceberg. And +so far it looks like there's not much of interest to SAX beyond what we +have seen with XML::Parser. But it does go much further than that, I +promise. + +People who hate Object Oriented code for the sake of it may be thinking +here that creating a new package just to parse something is a waste +when they've been parsing things just fine up to now using procedural +code. But there's reason to all this madness. And that reason is SAX +Filters. + +As you saw right at the very start, to let the parser know about our +class, we pass it an instance of our class as the Handler to the +parser. But now imagine what would happen if our class could also take +a Handler option, and simply do some processing and pass on our data +further down the line? That in a nutshell is how SAX filters work. It's +Unix pipes for the 21st century! + +There are two downsides to this. Number 1 - writing SAX filters can be +tricky. If you look into the future and read the advanced tutorial I'm +writing, you'll see that Handler can come in several shapes and sizes. +So making sure your filter does the right thing can be tricky. +Secondly, constructing complex filter chains can be difficult, and +simple thinking tells us that we only get one pass at our document, +when often we'll need more than that. + +Luckily though, those downsides have been fixed by the release of two +very cool modules. What's even better is that I didn't write either of +them! + +The first module is XML::SAX::Base. This is a VITAL SAX module that +acts as a base class for all SAX parsers and filters. It provides an +abstraction away from calling the handler methods, that makes sure your +filter or parser does the right thing, and it does it FAST. So, if you +ever need to write a SAX filter, which if you're processing XML -> XML, +or XML -> HTML, then you probably do, then you need to be writing it as +a subclass of XML::SAX::Base. Really - this is advice not to ignore +lightly. I will not go into the details of writing a SAX filter here. +Kip Hampton, the author of XML::SAX::Base has covered this nicely in +his article on XML.com here <URI>. + +To construct SAX pipelines, Barrie Slaymaker, a long time Perl hacker +whose modules you will probably have heard of or used, wrote a very +clever module called XML::SAX::Machines. This combines some really +clever SAX filter-type modules, with a construction toolkit for filters +that makes building pipelines easy. But before we see how it makes +things easy, first lets see how tricky it looks to build complex SAX +filter pipelines. + + use XML::SAX::ParserFactory; + use XML::Filter::Filter1; + use XML::Filter::Filter2; + use XML::SAX::Writer; + + my $output_string; + my $writer = XML::SAX::Writer->new(Output => \$output_string); + my $filter2 = XML::SAX::Filter2->new(Handler => $writer); + my $filter1 = XML::SAX::Filter1->new(Handler => $filter2); + my $parser = XML::SAX::ParserFactory->parser(Handler => $filter1); + + $parser->parse_uri("foo.xml"); + +This is a lot easier with XML::SAX::Machines: + + use XML::SAX::Machines qw(Pipeline); + + my $output_string; + my $parser = Pipeline( + XML::SAX::Filter1 => XML::SAX::Filter2 => \$output_string + ); + + $parser->parse_uri("foo.xml"); + +One of the main benefits of XML::SAX::Machines is that the pipelines +are constructed in natural order, rather than the reverse order we saw +with manual pipeline construction. XML::SAX::Machines takes care of all +the internals of pipe construction, providing you at the end with just +a parser you can use (and you can re-use the same parser as many times +as you need to). + +Just a final tip. If you ever get stuck and are confused about what is +being passed from one SAX filter or parser to the next, then +Devel::TraceSAX will come to your rescue. This perl debugger plugin +will allow you to dump the SAX stream of events as it goes by. Usage is +really very simple just call your perl script that uses SAX as follows: + + $ perl -d:TraceSAX <scriptname> + +And preferably pipe the output to a pager of some sort, such as more or +less. The output is extremely verbose, but should help clear some +issues up. + +=head1 AUTHOR + +Matt Sergeant, matt@sergeant.org + +$Id: Intro.pod,v 1.4 2008-08-04 10:28:01 grant Exp $ + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/ParserDetails.ini b/Master/tlpkg/tlperl/lib/XML/SAX/ParserDetails.ini new file mode 100755 index 00000000000..b2812ed6c96 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/ParserDetails.ini @@ -0,0 +1,10 @@ +[XML::SAX::PurePerl] +http://xml.org/sax/features/namespaces = 1 + +[XML::LibXML::SAX::Parser] +http://xml.org/sax/features/namespaces = 1 + +[XML::LibXML::SAX] +http://xml.org/sax/features/namespaces = 1 + + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/ParserFactory.pm b/Master/tlpkg/tlperl/lib/XML/SAX/ParserFactory.pm new file mode 100755 index 00000000000..f4325b41797 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/ParserFactory.pm @@ -0,0 +1,230 @@ +# $Id: ParserFactory.pm,v 1.14 2008-08-04 04:51:29 grant Exp $ + +package XML::SAX::ParserFactory; + +use strict; +use vars qw($VERSION); + +$VERSION = '1.01'; + +use Symbol qw(gensym); +use XML::SAX; +use XML::SAX::Exception; + +sub new { + my $class = shift; + my %params = @_; # TODO : Fix this in spec. + my $self = bless \%params, $class; + $self->{KnownParsers} = XML::SAX->parsers(); + return $self; +} + +sub parser { + my $self = shift; + my @parser_params = @_; + if (!ref($self)) { + $self = $self->new(); + } + + my $parser_class = $self->_parser_class(); + + my $version = ''; + if ($parser_class =~ s/\s*\(([\d\.]+)\)\s*$//) { + $version = " $1"; + } + + if (!$parser_class->can('new')) { + eval "require $parser_class $version;"; + die $@ if $@; + } + + return $parser_class->new(@parser_params); +} + +sub require_feature { + my $self = shift; + my ($feature) = @_; + $self->{RequiredFeatures}{$feature}++; + return $self; +} + +sub _parser_class { + my $self = shift; + + # First try ParserPackage + if ($XML::SAX::ParserPackage) { + return $XML::SAX::ParserPackage; + } + + # Now check if required/preferred is there + if ($self->{RequiredFeatures}) { + my %required = %{$self->{RequiredFeatures}}; + # note - we never go onto the next try (ParserDetails.ini), + # because if we can't provide the requested feature + # we need to throw an exception. + PARSER: + foreach my $parser (reverse @{$self->{KnownParsers}}) { + foreach my $feature (keys %required) { + if (!exists $parser->{Features}{$feature}) { + next PARSER; + } + } + # got here - all features must exist! + return $parser->{Name}; + } + # TODO : should this be NotSupported() ? + throw XML::SAX::Exception ( + Message => "Unable to provide required features", + ); + } + + # Next try SAX.ini + for my $dir (@INC) { + my $fh = gensym(); + if (open($fh, "$dir/SAX.ini")) { + my $param_list = XML::SAX->_parse_ini_file($fh); + my $params = $param_list->[0]->{Features}; + if ($params->{ParserPackage}) { + return $params->{ParserPackage}; + } + else { + # we have required features (or nothing?) + PARSER: + foreach my $parser (reverse @{$self->{KnownParsers}}) { + foreach my $feature (keys %$params) { + if (!exists $parser->{Features}{$feature}) { + next PARSER; + } + } + return $parser->{Name}; + } + XML::SAX->do_warn("Unable to provide SAX.ini required features. Using fallback\n"); + } + last; # stop after first INI found + } + } + + if (@{$self->{KnownParsers}}) { + return $self->{KnownParsers}[-1]{Name}; + } + else { + return "XML::SAX::PurePerl"; # backup plan! + } +} + +1; +__END__ + +=head1 NAME + +XML::SAX::ParserFactory - Obtain a SAX parser + +=head1 SYNOPSIS + + use XML::SAX::ParserFactory; + use XML::SAX::XYZHandler; + my $handler = XML::SAX::XYZHandler->new(); + my $p = XML::SAX::ParserFactory->parser(Handler => $handler); + $p->parse_uri("foo.xml"); + # or $p->parse_string("<foo/>") or $p->parse_file($fh); + +=head1 DESCRIPTION + +XML::SAX::ParserFactory is a factory class for providing an application +with a Perl SAX2 XML parser. It is akin to DBI - a front end for other +parser classes. Each new SAX2 parser installed will register itself +with XML::SAX, and then it will become available to all applications +that use XML::SAX::ParserFactory to obtain a SAX parser. + +Unlike DBI however, XML/SAX parsers almost all work alike (especially +if they subclass XML::SAX::Base, as they should), so rather than +specifying the parser you want in the call to C<parser()>, XML::SAX +has several ways to automatically choose which parser to use: + +=over 4 + +=item * $XML::SAX::ParserPackage + +If this package variable is set, then this package is C<require()>d +and an instance of this package is returned by calling the C<new()> +class method in that package. If it cannot be loaded or there is +an error, an exception will be thrown. The variable can also contain +a version number: + + $XML::SAX::ParserPackage = "XML::SAX::Expat (0.72)"; + +And the number will be treated as a minimum version number. + +=item * Required features + +It is possible to require features from the parsers. For example, you +may wish for a parser that supports validation via a DTD. To do that, +use the following code: + + use XML::SAX::ParserFactory; + my $factory = XML::SAX::ParserFactory->new(); + $factory->require_feature('http://xml.org/sax/features/validation'); + my $parser = $factory->parser(...); + +Alternatively, specify the required features in the call to the +ParserFactory constructor: + + my $factory = XML::SAX::ParserFactory->new( + RequiredFeatures => { + 'http://xml.org/sax/features/validation' => 1, + } + ); + +If the features you have asked for are unavailable (for example the +user might not have a validating parser installed), then an +exception will be thrown. + +The list of known parsers is searched in reverse order, so it will +always return the last installed parser that supports all of your +requested features (Note: this is subject to change if someone +comes up with a better way of making this work). + +=item * SAX.ini + +ParserFactory will search @INC for a file called SAX.ini, which +is in a simple format: + + # a comment looks like this, + ; or like this, and are stripped anywhere in the file + key = value # SAX.in contains key/value pairs. + +All whitespace is non-significant. + +This file can contain either a line: + + ParserPackage = MyParserModule (1.02) + +Where MyParserModule is the module to load and use for the parser, +and the number in brackets is a minimum version to load. + +Or you can list required features: + + http://xml.org/sax/features/validation = 1 + +And each feature with a true value will be required. + +=item * Fallback + +If none of the above works, the last parser installed on the user's +system will be used. The XML::SAX package ships with a pure perl +XML parser, XML::SAX::PurePerl, so that there will always be a +fallback parser. + +=back + +=head1 AUTHOR + +Matt Sergeant, matt@sergeant.org + +=head1 LICENSE + +This is free software, you may use it and distribute it under the same +terms as Perl itself. + +=cut + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl.pm new file mode 100755 index 00000000000..40e71485f20 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl.pm @@ -0,0 +1,751 @@ +# $Id: PurePerl.pm,v 1.28 2008-08-05 12:36:51 grant Exp $ + +package XML::SAX::PurePerl; + +use strict; +use vars qw/$VERSION/; + +$VERSION = '0.96'; + +use XML::SAX::PurePerl::Productions qw($NameChar $SingleChar); +use XML::SAX::PurePerl::Reader; +use XML::SAX::PurePerl::EncodingDetect (); +use XML::SAX::Exception; +use XML::SAX::PurePerl::DocType (); +use XML::SAX::PurePerl::DTDDecls (); +use XML::SAX::PurePerl::XMLDecl (); +use XML::SAX::DocumentLocator (); +use XML::SAX::Base (); +use XML::SAX qw(Namespaces); +use XML::NamespaceSupport (); +use IO::File; + +if ($] < 5.006) { + require XML::SAX::PurePerl::NoUnicodeExt; +} +else { + require XML::SAX::PurePerl::UnicodeExt; +} + +use vars qw(@ISA); +@ISA = ('XML::SAX::Base'); + +my %int_ents = ( + amp => '&', + lt => '<', + gt => '>', + quot => '"', + apos => "'", + ); + +my $xmlns_ns = "http://www.w3.org/2000/xmlns/"; +my $xml_ns = "http://www.w3.org/XML/1998/namespace"; + +use Carp; +sub _parse_characterstream { + my $self = shift; + my ($fh) = @_; + confess("CharacterStream is not yet correctly implemented"); + my $reader = XML::SAX::PurePerl::Reader::Stream->new($fh); + return $self->_parse($reader); +} + +sub _parse_bytestream { + my $self = shift; + my ($fh) = @_; + my $reader = XML::SAX::PurePerl::Reader::Stream->new($fh); + return $self->_parse($reader); +} + +sub _parse_string { + my $self = shift; + my ($str) = @_; + my $reader = XML::SAX::PurePerl::Reader::String->new($str); + return $self->_parse($reader); +} + +sub _parse_systemid { + my $self = shift; + my ($uri) = @_; + my $reader = XML::SAX::PurePerl::Reader::URI->new($uri); + return $self->_parse($reader); +} + +sub _parse { + my ($self, $reader) = @_; + + $reader->public_id($self->{ParseOptions}{Source}{PublicId}); + $reader->system_id($self->{ParseOptions}{Source}{SystemId}); + + $self->{NSHelper} = XML::NamespaceSupport->new({xmlns => 1}); + + $self->set_document_locator( + XML::SAX::DocumentLocator->new( + sub { $reader->public_id }, + sub { $reader->system_id }, + sub { $reader->line }, + sub { $reader->column }, + sub { $reader->get_encoding }, + sub { $reader->get_xml_version }, + ), + ); + + $self->start_document({}); + + if (defined $self->{ParseOptions}{Source}{Encoding}) { + $reader->set_encoding($self->{ParseOptions}{Source}{Encoding}); + } + else { + $self->encoding_detect($reader); + } + + # parse a document + $self->document($reader); + + return $self->end_document({}); +} + +sub parser_error { + my $self = shift; + my ($error, $reader) = @_; + +# warn("parser error: $error from ", $reader->line, " : ", $reader->column, "\n"); + my $exception = XML::SAX::Exception::Parse->new( + Message => $error, + ColumnNumber => $reader->column, + LineNumber => $reader->line, + PublicId => $reader->public_id, + SystemId => $reader->system_id, + ); + + $self->fatal_error($exception); + $exception->throw; +} + +sub document { + my ($self, $reader) = @_; + + # document ::= prolog element Misc* + + $self->prolog($reader); + $self->element($reader) || + $self->parser_error("Document requires an element", $reader); + + while(length($reader->data)) { + $self->Misc($reader) || + $self->parser_error("Only Comments, PIs and whitespace allowed at end of document", $reader); + } +} + +sub prolog { + my ($self, $reader) = @_; + + $self->XMLDecl($reader); + + # consume all misc bits + 1 while($self->Misc($reader)); + + if ($self->doctypedecl($reader)) { + while (length($reader->data)) { + $self->Misc($reader) || last; + } + } +} + +sub element { + my ($self, $reader) = @_; + + return 0 unless $reader->match('<'); + + my $name = $self->Name($reader) || $self->parser_error("Invalid element name", $reader); + + my %attribs; + + while( my ($k, $v) = $self->Attribute($reader) ) { + $attribs{$k} = $v; + } + + my $have_namespaces = $self->get_feature(Namespaces); + + # Namespace processing + $self->{NSHelper}->push_context; + my @new_ns; +# my %attrs = @attribs; +# while (my ($k,$v) = each %attrs) { + if ($have_namespaces) { + while ( my ($k, $v) = each %attribs ) { + if ($k =~ m/^xmlns(:(.*))?$/) { + my $prefix = $2 || ''; + $self->{NSHelper}->declare_prefix($prefix, $v); + my $ns = + { + Prefix => $prefix, + NamespaceURI => $v, + }; + push @new_ns, $ns; + $self->SUPER::start_prefix_mapping($ns); + } + } + } + + # Create element object and fire event + my %attrib_hash; + while (my ($name, $value) = each %attribs ) { + # TODO normalise value here + my ($ns, $prefix, $lname); + if ($have_namespaces) { + ($ns, $prefix, $lname) = $self->{NSHelper}->process_attribute_name($name); + } + $ns ||= ''; $prefix ||= ''; $lname ||= ''; + $attrib_hash{"{$ns}$lname"} = { + Name => $name, + LocalName => $lname, + Prefix => $prefix, + NamespaceURI => $ns, + Value => $value, + }; + } + + %attribs = (); # lose the memory since we recurse deep + + my ($ns, $prefix, $lname); + if ($self->get_feature(Namespaces)) { + ($ns, $prefix, $lname) = $self->{NSHelper}->process_element_name($name); + } + else { + $lname = $name; + } + $ns ||= ''; $prefix ||= ''; $lname ||= ''; + + # Process remainder of start_element + $self->skip_whitespace($reader); + my $have_content; + my $data = $reader->data(2); + if ($data =~ /^\/>/) { + $reader->move_along(2); + } + else { + $data =~ /^>/ or $self->parser_error("No close element tag", $reader); + $reader->move_along(1); + $have_content++; + } + + my $el = + { + Name => $name, + LocalName => $lname, + Prefix => $prefix, + NamespaceURI => $ns, + Attributes => \%attrib_hash, + }; + $self->start_element($el); + + # warn("($name\n"); + + if ($have_content) { + $self->content($reader); + + my $data = $reader->data(2); + $data =~ /^<\// or $self->parser_error("No close tag marker", $reader); + $reader->move_along(2); + my $end_name = $self->Name($reader); + $end_name eq $name || $self->parser_error("End tag mismatch ($end_name != $name)", $reader); + $self->skip_whitespace($reader); + $reader->match('>') or $self->parser_error("No close '>' on end tag", $reader); + } + + my %end_el = %$el; + delete $end_el{Attributes}; + $self->end_element(\%end_el); + + for my $ns (@new_ns) { + $self->end_prefix_mapping($ns); + } + $self->{NSHelper}->pop_context; + + return 1; +} + +sub content { + my ($self, $reader) = @_; + + while (1) { + $self->CharData($reader); + + my $data = $reader->data(2); + + if ($data =~ /^<\//) { + return 1; + } + elsif ($data =~ /^&/) { + $self->Reference($reader) or $self->parser_error("bare & not allowed in content", $reader); + next; + } + elsif ($data =~ /^<!/) { + ($self->CDSect($reader) + or + $self->Comment($reader)) + and next; + } + elsif ($data =~ /^<\?/) { + $self->PI($reader) and next; + } + elsif ($data =~ /^</) { + $self->element($reader) and next; + } + last; + } + + return 1; +} + +sub CDSect { + my ($self, $reader) = @_; + + my $data = $reader->data(9); + return 0 unless $data =~ /^<!\[CDATA\[/; + $reader->move_along(9); + + $self->start_cdata({}); + + $data = $reader->data; + while (1) { + $self->parser_error("EOF looking for CDATA section end", $reader) + unless length($data); + + if ($data =~ /^(.*?)\]\]>/s) { + my $chars = $1; + $reader->move_along(length($chars) + 3); + $self->characters({Data => $chars}); + last; + } + else { + $self->characters({Data => $data}); + $reader->move_along(length($data)); + $data = $reader->data; + } + } + $self->end_cdata({}); + return 1; +} + +sub CharData { + my ($self, $reader) = @_; + + my $data = $reader->data; + + while (1) { + return unless length($data); + + if ($data =~ /^([^<&]*)[<&]/s) { + my $chars = $1; + $self->parser_error("String ']]>' not allowed in character data", $reader) + if $chars =~ /\]\]>/; + $reader->move_along(length($chars)); + $self->characters({Data => $chars}) if length($chars); + last; + } + else { + $self->characters({Data => $data}); + $reader->move_along(length($data)); + $data = $reader->data; + } + } +} + +sub Misc { + my ($self, $reader) = @_; + if ($self->Comment($reader)) { + return 1; + } + elsif ($self->PI($reader)) { + return 1; + } + elsif ($self->skip_whitespace($reader)) { + return 1; + } + + return 0; +} + +sub Reference { + my ($self, $reader) = @_; + + return 0 unless $reader->match('&'); + + my $data = $reader->data; + + # Fetch more data if we have an incomplete numeric reference + if ($data =~ /^(#\d*|#x[0-9a-fA-F]*)$/) { + $data = $reader->data(length($data) + 6); + } + + if ($data =~ /^#x([0-9a-fA-F]+);/) { + my $ref = $1; + $reader->move_along(length($ref) + 3); + my $char = chr_ref(hex($ref)); + $self->parser_error("Character reference &#$ref; refers to an illegal XML character ($char)", $reader) + unless $char =~ /$SingleChar/o; + $self->characters({ Data => $char }); + return 1; + } + elsif ($data =~ /^#([0-9]+);/) { + my $ref = $1; + $reader->move_along(length($ref) + 2); + my $char = chr_ref($ref); + $self->parser_error("Character reference &#$ref; refers to an illegal XML character ($char)", $reader) + unless $char =~ /$SingleChar/o; + $self->characters({ Data => $char }); + return 1; + } + else { + # EntityRef + my $name = $self->Name($reader) + || $self->parser_error("Invalid name in entity", $reader); + $reader->match(';') or $self->parser_error("No semi-colon found after entity name", $reader); + + # warn("got entity: \&$name;\n"); + + # expand it + if ($self->_is_entity($name)) { + + if ($self->_is_external($name)) { + my $value = $self->_get_entity($name); + my $ent_reader = XML::SAX::PurePerl::Reader::URI->new($value); + $self->encoding_detect($ent_reader); + $self->extParsedEnt($ent_reader); + } + else { + my $value = $self->_stringify_entity($name); + my $ent_reader = XML::SAX::PurePerl::Reader::String->new($value); + $self->content($ent_reader); + } + return 1; + } + elsif ($name =~ /^(?:amp|gt|lt|quot|apos)$/) { + $self->characters({ Data => $int_ents{$name} }); + return 1; + } + else { + $self->parser_error("Undeclared entity", $reader); + } + } +} + +sub AttReference { + my ($self, $name, $reader) = @_; + if ($name =~ /^#x([0-9a-fA-F]+)$/) { + my $chr = chr_ref(hex($1)); + $chr =~ /$SingleChar/o or $self->parser_error("Character reference '&$name;' refers to an illegal XML character", $reader); + return $chr; + } + elsif ($name =~ /^#([0-9]+)$/) { + my $chr = chr_ref($1); + $chr =~ /$SingleChar/o or $self->parser_error("Character reference '&$name;' refers to an illegal XML character", $reader); + return $chr; + } + else { + if ($self->_is_entity($name)) { + if ($self->_is_external($name)) { + $self->parser_error("No external entity references allowed in attribute values", $reader); + } + else { + my $value = $self->_stringify_entity($name); + return $value; + } + } + elsif ($name =~ /^(?:amp|lt|gt|quot|apos)$/) { + return $int_ents{$name}; + } + else { + $self->parser_error("Undeclared entity '$name'", $reader); + } + } +} + +sub extParsedEnt { + my ($self, $reader) = @_; + + $self->TextDecl($reader); + $self->content($reader); +} + +sub _is_external { + my ($self, $name) = @_; +# TODO: Fix this to use $reader to store the entities perhaps. + if ($self->{ParseOptions}{external_entities}{$name}) { + return 1; + } + return ; +} + +sub _is_entity { + my ($self, $name) = @_; +# TODO: ditto above + if (exists $self->{ParseOptions}{entities}{$name}) { + return 1; + } + return 0; +} + +sub _stringify_entity { + my ($self, $name) = @_; +# TODO: ditto above + if (exists $self->{ParseOptions}{expanded_entity}{$name}) { + return $self->{ParseOptions}{expanded_entity}{$name}; + } + # expand + my $reader = XML::SAX::PurePerl::Reader::URI->new($self->{ParseOptions}{entities}{$name}); + my $ent = ''; + while(1) { + my $data = $reader->data; + $ent .= $data; + $reader->move_along(length($data)) or last; + } + return $self->{ParseOptions}{expanded_entity}{$name} = $ent; +} + +sub _get_entity { + my ($self, $name) = @_; +# TODO: ditto above + return $self->{ParseOptions}{entities}{$name}; +} + +sub skip_whitespace { + my ($self, $reader) = @_; + + my $data = $reader->data; + + my $found = 0; + while ($data =~ s/^([\x20\x0A\x0D\x09]*)//) { + last unless length($1); + $found++; + $reader->move_along(length($1)); + $data = $reader->data; + } + + return $found; +} + +sub Attribute { + my ($self, $reader) = @_; + + $self->skip_whitespace($reader) || return; + + my $data = $reader->data(2); + return if $data =~ /^\/?>/; + + if (my $name = $self->Name($reader)) { + $self->skip_whitespace($reader); + $reader->match('=') or $self->parser_error("No '=' in Attribute", $reader); + $self->skip_whitespace($reader); + my $value = $self->AttValue($reader); + + if (!$self->cdata_attrib($name)) { + $value =~ s/^\x20*//; # discard leading spaces + $value =~ s/\x20*$//; # discard trailing spaces + $value =~ s/ {1,}/ /g; # all >1 space to single space + } + + return $name, $value; + } + + return; +} + +sub cdata_attrib { + # TODO implement this! + return 1; +} + +sub AttValue { + my ($self, $reader) = @_; + + my $quote = $self->quote($reader); + + my $value = ''; + + while (1) { + my $data = $reader->data; + $self->parser_error("EOF found while looking for the end of attribute value", $reader) + unless length($data); + if ($data =~ /^([^$quote]*)$quote/) { + $reader->move_along(length($1) + 1); + $value .= $1; + last; + } + else { + $value .= $data; + $reader->move_along(length($data)); + } + } + + if ($value =~ /</) { + $self->parser_error("< character not allowed in attribute values", $reader); + } + + $value =~ s/[\x09\x0A\x0D]/\x20/g; + $value =~ s/&(#(x[0-9a-fA-F]+)|#([0-9]+)|\w+);/$self->AttReference($1, $reader)/geo; + + return $value; +} + +sub Comment { + my ($self, $reader) = @_; + + my $data = $reader->data(4); + if ($data =~ /^<!--/) { + $reader->move_along(4); + my $comment_str = ''; + while (1) { + my $data = $reader->data; + $self->parser_error("End of data seen while looking for close comment marker", $reader) + unless length($data); + if ($data =~ /^(.*?)-->/s) { + $comment_str .= $1; + $self->parser_error("Invalid comment (dash)", $reader) if $comment_str =~ /-$/; + $reader->move_along(length($1) + 3); + last; + } + else { + $comment_str .= $data; + $reader->move_along(length($data)); + } + } + + $self->comment({ Data => $comment_str }); + + return 1; + } + return 0; +} + +sub PI { + my ($self, $reader) = @_; + + my $data = $reader->data(2); + + if ($data =~ /^<\?/) { + $reader->move_along(2); + my ($target); + $target = $self->Name($reader) || + $self->parser_error("PI has no target", $reader); + + my $pi_data = ''; + if ($self->skip_whitespace($reader)) { + while (1) { + my $data = $reader->data; + $self->parser_error("End of data seen while looking for close PI marker", $reader) + unless length($data); + if ($data =~ /^(.*?)\?>/s) { + $pi_data .= $1; + $reader->move_along(length($1) + 2); + last; + } + else { + $pi_data .= $data; + $reader->move_along(length($data)); + } + } + } + else { + my $data = $reader->data(2); + $data =~ /^\?>/ or $self->parser_error("PI closing sequence not found", $reader); + $reader->move_along(2); + } + + $self->processing_instruction({ Target => $target, Data => $pi_data }); + + return 1; + } + return 0; +} + +sub Name { + my ($self, $reader) = @_; + + my $name = ''; + while(1) { + my $data = $reader->data; + return unless length($data); + $data =~ /^([^\s>\/&\?;=<\)\(\[\],\%\#\!\*\|]*)/ or return; + $name .= $1; + my $len = length($1); + $reader->move_along($len); + last if ($len != length($data)); + } + + return unless length($name); + + $name =~ /$NameChar/o or $self->parser_error("Name <$name> does not match NameChar production", $reader); + + return $name; +} + +sub quote { + my ($self, $reader) = @_; + + my $data = $reader->data; + + $data =~ /^(['"])/ or $self->parser_error("Invalid quote token", $reader); + $reader->move_along(1); + return $1; +} + +1; +__END__ + +=head1 NAME + +XML::SAX::PurePerl - Pure Perl XML Parser with SAX2 interface + +=head1 SYNOPSIS + + use XML::Handler::Foo; + use XML::SAX::PurePerl; + my $handler = XML::Handler::Foo->new(); + my $parser = XML::SAX::PurePerl->new(Handler => $handler); + $parser->parse_uri("myfile.xml"); + +=head1 DESCRIPTION + +This module implements an XML parser in pure perl. It is written around the +upcoming perl 5.8's unicode support and support for multiple document +encodings (using the PerlIO layer), however it has been ported to work with +ASCII/UTF8 documents under lower perl versions. + +The SAX2 API is described in detail at http://sourceforge.net/projects/perl-xml/, in +the CVS archive, under libxml-perl/docs. Hopefully those documents will be in a +better location soon. + +Please refer to the SAX2 documentation for how to use this module - it is merely a +front end to SAX2, and implements nothing that is not in that spec (or at least tries +not to - please email me if you find errors in this implementation). + +=head1 BUGS + +XML::SAX::PurePerl is B<slow>. Very slow. I suggest you use something else +in fact. However it is great as a fallback parser for XML::SAX, where the +user might not be able to install an XS based parser or C library. + +Currently lots, probably. At the moment the weakest area is parsing DOCTYPE declarations, +though the code is in place to start doing this. Also parsing parameter entity +references is causing me much confusion, since it's not exactly what I would call +trivial, or well documented in the XML grammar. XML documents with internal subsets +are likely to fail. + +I am however trying to work towards full conformance using the Oasis test suite. + +=head1 AUTHOR + +Matt Sergeant, matt@sergeant.org. Copyright 2001. + +Please report all bugs to the Perl-XML mailing list at perl-xml@listserv.activestate.com. + +=head1 LICENSE + +This is free software. You may use it or redistribute it under the same terms as +Perl 5.7.2 itself. + +=cut + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DTDDecls.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DTDDecls.pm new file mode 100755 index 00000000000..9e496b47f4c --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DTDDecls.pm @@ -0,0 +1,603 @@ +# $Id: DTDDecls.pm,v 1.9 2008-08-05 12:37:13 grant Exp $ + +package XML::SAX::PurePerl; + +use strict; +use XML::SAX::PurePerl::Productions qw($SingleChar); + +sub elementdecl { + my ($self, $reader) = @_; + + my $data = $reader->data(9); + return 0 unless $data =~ /^<!ELEMENT/; + $reader->move_along(9); + + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after ELEMENT declaration", $reader); + + my $name = $self->Name($reader); + + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after ELEMENT's name", $reader); + + $self->contentspec($reader, $name); + + $self->skip_whitespace($reader); + + $reader->match('>') or $self->parser_error("Closing angle bracket not found on ELEMENT declaration", $reader); + + return 1; +} + +sub contentspec { + my ($self, $reader, $name) = @_; + + my $data = $reader->data(5); + + my $model; + if ($data =~ /^EMPTY/) { + $reader->move_along(5); + $model = 'EMPTY'; + } + elsif ($data =~ /^ANY/) { + $reader->move_along(3); + $model = 'ANY'; + } + else { + $model = $self->Mixed_or_children($reader); + } + + if ($model) { + # call SAX callback now. + $self->element_decl({Name => $name, Model => $model}); + return 1; + } + + $self->parser_error("contentspec not found in ELEMENT declaration", $reader); +} + +sub Mixed_or_children { + my ($self, $reader) = @_; + + my $data = $reader->data(8); + $data =~ /^\(/ or return; # $self->parser_error("No opening bracket in Mixed or children", $reader); + + if ($data =~ /^\(\s*\#PCDATA/) { + $reader->match('('); + $self->skip_whitespace($reader); + $reader->move_along(7); + my $model = $self->Mixed($reader); + return $model; + } + + # not matched - must be Children + return $self->children($reader); +} + +# Mixed ::= ( '(' S* PCDATA ( S* '|' S* QName )* S* ')' '*' ) +# | ( '(' S* PCDATA S* ')' ) +sub Mixed { + my ($self, $reader) = @_; + + # Mixed_or_children already matched '(' S* '#PCDATA' + + my $model = '(#PCDATA'; + + $self->skip_whitespace($reader); + + my %seen; + + while (1) { + last unless $reader->match('|'); + $self->skip_whitespace($reader); + + my $name = $self->Name($reader) || + $self->parser_error("No 'Name' after Mixed content '|'", $reader); + + if ($seen{$name}) { + $self->parser_error("Element '$name' has already appeared in this group", $reader); + } + $seen{$name}++; + + $model .= "|$name"; + + $self->skip_whitespace($reader); + } + + $reader->match(')') || $self->parser_error("no closing bracket on mixed content", $reader); + + $model .= ")"; + + if ($reader->match('*')) { + $model .= "*"; + } + + return $model; +} + +# [[47]] Children ::= ChoiceOrSeq Cardinality? +# [[48]] Cp ::= ( QName | ChoiceOrSeq ) Cardinality? +# ChoiceOrSeq ::= '(' S* Cp ( Choice | Seq )? S* ')' +# [[49]] Choice ::= ( S* '|' S* Cp )+ +# [[50]] Seq ::= ( S* ',' S* Cp )+ +# // Children ::= (Choice | Seq) Cardinality? +# // Cp ::= ( QName | Choice | Seq) Cardinality? +# // Choice ::= '(' S* Cp ( S* '|' S* Cp )+ S* ')' +# // Seq ::= '(' S* Cp ( S* ',' S* Cp )* S* ')' +# [[51]] Mixed ::= ( '(' S* PCDATA ( S* '|' S* QName )* S* ')' MixedCardinality ) +# | ( '(' S* PCDATA S* ')' ) +# Cardinality ::= '?' | '+' | '*' +# MixedCardinality ::= '*' +sub children { + my ($self, $reader) = @_; + + return $self->ChoiceOrSeq($reader) . $self->Cardinality($reader); +} + +sub ChoiceOrSeq { + my ($self, $reader) = @_; + + $reader->match('(') or $self->parser_error("choice/seq contains no opening bracket", $reader); + + my $model = '('; + + $self->skip_whitespace($reader); + + $model .= $self->Cp($reader); + + if (my $choice = $self->Choice($reader)) { + $model .= $choice; + } + else { + $model .= $self->Seq($reader); + } + + $self->skip_whitespace($reader); + + $reader->match(')') or $self->parser_error("choice/seq contains no closing bracket", $reader); + + $model .= ')'; + + return $model; +} + +sub Cardinality { + my ($self, $reader) = @_; + # cardinality is always optional + my $data = $reader->data; + if ($data =~ /^([\?\+\*])/) { + $reader->move_along(1); + return $1; + } + return ''; +} + +sub Cp { + my ($self, $reader) = @_; + + my $model; + my $name = eval + { + if (my $name = $self->Name($reader)) { + return $name . $self->Cardinality($reader); + } + }; + return $name if defined $name; + return $self->ChoiceOrSeq($reader) . $self->Cardinality($reader); +} + +sub Choice { + my ($self, $reader) = @_; + + my $model = ''; + $self->skip_whitespace($reader); + + while ($reader->match('|')) { + $self->skip_whitespace($reader); + $model .= '|'; + $model .= $self->Cp($reader); + $self->skip_whitespace($reader); + } + + return $model; +} + +sub Seq { + my ($self, $reader) = @_; + + my $model = ''; + $self->skip_whitespace($reader); + + while ($reader->match(',')) { + $self->skip_whitespace($reader); + my $cp = $self->Cp($reader); + if ($cp) { + $model .= ','; + $model .= $cp; + } + $self->skip_whitespace($reader); + } + + return $model; +} + +sub AttlistDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(9); + if ($data =~ /^<!ATTLIST/) { + # It's an attlist + + $reader->move_along(9); + + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after ATTLIST declaration", $reader); + my $name = $self->Name($reader); + + $self->AttDefList($reader, $name); + + $self->skip_whitespace($reader); + + $reader->match('>') or $self->parser_error("Closing angle bracket not found on ATTLIST declaration", $reader); + + return 1; + } + + return 0; +} + +sub AttDefList { + my ($self, $reader, $name) = @_; + + 1 while $self->AttDef($reader, $name); +} + +sub AttDef { + my ($self, $reader, $el_name) = @_; + + $self->skip_whitespace($reader) || return 0; + my $att_name = $self->Name($reader) || return 0; + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after Name in attribute definition", $reader); + my $att_type = $self->AttType($reader); + + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after AttType in attribute definition", $reader); + my ($mode, $value) = $self->DefaultDecl($reader); + + # fire SAX event here! + $self->attribute_decl({ + eName => $el_name, + aName => $att_name, + Type => $att_type, + Mode => $mode, + Value => $value, + }); + return 1; +} + +sub AttType { + my ($self, $reader) = @_; + + return $self->StringType($reader) || + $self->TokenizedType($reader) || + $self->EnumeratedType($reader) || + $self->parser_error("Can't match AttType", $reader); +} + +sub StringType { + my ($self, $reader) = @_; + + my $data = $reader->data(5); + return unless $data =~ /^CDATA/; + $reader->move_along(5); + return 'CDATA'; +} + +sub TokenizedType { + my ($self, $reader) = @_; + + my $data = $reader->data(8); + if ($data =~ /^(IDREFS?|ID|ENTITIES|ENTITY|NMTOKENS?)/) { + $reader->move_along(length($1)); + return $1; + } + return; +} + +sub EnumeratedType { + my ($self, $reader) = @_; + return $self->NotationType($reader) || $self->Enumeration($reader); +} + +sub NotationType { + my ($self, $reader) = @_; + + my $data = $reader->data(8); + return unless $data =~ /^NOTATION/; + $reader->move_along(8); + + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after NOTATION", $reader); + $reader->match('(') or $self->parser_error("No opening bracket in notation section", $reader); + + $self->skip_whitespace($reader); + my $model = 'NOTATION ('; + my $name = $self->Name($reader) || + $self->parser_error("No name in notation section", $reader); + $model .= $name; + $self->skip_whitespace($reader); + $data = $reader->data; + while ($data =~ /^\|/) { + $reader->move_along(1); + $model .= '|'; + $self->skip_whitespace($reader); + my $name = $self->Name($reader) || + $self->parser_error("No name in notation section", $reader); + $model .= $name; + $self->skip_whitespace($reader); + $data = $reader->data; + } + $data =~ /^\)/ or $self->parser_error("No closing bracket in notation section", $reader); + $reader->move_along(1); + + $model .= ')'; + + return $model; +} + +sub Enumeration { + my ($self, $reader) = @_; + + return unless $reader->match('('); + + $self->skip_whitespace($reader); + my $model = '('; + my $nmtoken = $self->Nmtoken($reader) || + $self->parser_error("No Nmtoken in enumerated declaration", $reader); + $model .= $nmtoken; + $self->skip_whitespace($reader); + my $data = $reader->data; + while ($data =~ /^\|/) { + $model .= '|'; + $reader->move_along(1); + $self->skip_whitespace($reader); + my $nmtoken = $self->Nmtoken($reader) || + $self->parser_error("No Nmtoken in enumerated declaration", $reader); + $model .= $nmtoken; + $self->skip_whitespace($reader); + $data = $reader->data; + } + $data =~ /^\)/ or $self->parser_error("No closing bracket in enumerated declaration", $reader); + $reader->move_along(1); + + $model .= ')'; + + return $model; +} + +sub Nmtoken { + my ($self, $reader) = @_; + return $self->Name($reader); +} + +sub DefaultDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(9); + if ($data =~ /^(\#REQUIRED|\#IMPLIED)/) { + $reader->move_along(length($1)); + return $1; + } + my $model = ''; + if ($data =~ /^\#FIXED/) { + $reader->move_along(6); + $self->skip_whitespace($reader) || $self->parser_error( + "no whitespace after FIXED specifier", $reader); + my $value = $self->AttValue($reader); + return "#FIXED", $value; + } + my $value = $self->AttValue($reader); + return undef, $value; +} + +sub EntityDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(8); + return 0 unless $data =~ /^<!ENTITY/; + $reader->move_along(8); + + $self->skip_whitespace($reader) || $self->parser_error( + "No whitespace after ENTITY declaration", $reader); + + $self->PEDecl($reader) || $self->GEDecl($reader); + + $self->skip_whitespace($reader); + + $reader->match('>') or $self->parser_error("No closing '>' in entity definition", $reader); + + return 1; +} + +sub GEDecl { + my ($self, $reader) = @_; + + my $name = $self->Name($reader) || $self->parser_error("No entity name given", $reader); + $self->skip_whitespace($reader) || $self->parser_error("No whitespace after entity name", $reader); + + # TODO: ExternalID calls lexhandler method. Wrong place for it. + my $value; + if ($value = $self->ExternalID($reader)) { + $value .= $self->NDataDecl($reader); + } + else { + $value = $self->EntityValue($reader); + } + + if ($self->{ParseOptions}{entities}{$name}) { + warn("entity $name already exists\n"); + } else { + $self->{ParseOptions}{entities}{$name} = 1; + $self->{ParseOptions}{expanded_entity}{$name} = $value; # ??? + } + # do callback? + return 1; +} + +sub PEDecl { + my ($self, $reader) = @_; + + return 0 unless $reader->match('%'); + + $self->skip_whitespace($reader) || $self->parser_error("No whitespace after parameter entity marker", $reader); + my $name = $self->Name($reader) || $self->parser_error("No parameter entity name given", $reader); + $self->skip_whitespace($reader) || $self->parser_error("No whitespace after parameter entity name", $reader); + my $value = $self->ExternalID($reader) || + $self->EntityValue($reader) || + $self->parser_error("PE is not a value or an external resource", $reader); + # do callback? + return 1; +} + +my $quotre = qr/[^%&\"]/; +my $aposre = qr/[^%&\']/; + +sub EntityValue { + my ($self, $reader) = @_; + + my $data = $reader->data; + my $quote = '"'; + my $re = $quotre; + if ($data !~ /^"/) { + $data =~ /^'/ or $self->parser_error("Not a quote character", $reader); + $quote = "'"; + $re = $aposre; + } + $reader->move_along(1); + + my $value = ''; + + while (1) { + my $data = $reader->data; + + $self->parser_error("EOF found while reading entity value", $reader) + unless length($data); + + if ($data =~ /^($re+)/) { + my $match = $1; + $value .= $match; + $reader->move_along(length($match)); + } + elsif ($reader->match('&')) { + # if it's a char ref, expand now: + if ($reader->match('#')) { + my $char; + my $ref = ''; + if ($reader->match('x')) { + my $data = $reader->data; + while (1) { + $self->parser_error("EOF looking for reference end", $reader) + unless length($data); + if ($data !~ /^([0-9a-fA-F]*)/) { + last; + } + $ref .= $1; + $reader->move_along(length($1)); + if (length($1) == length($data)) { + $data = $reader->data; + } + else { + last; + } + } + $char = chr_ref(hex($ref)); + $ref = "x$ref"; + } + else { + my $data = $reader->data; + while (1) { + $self->parser_error("EOF looking for reference end", $reader) + unless length($data); + if ($data !~ /^([0-9]*)/) { + last; + } + $ref .= $1; + $reader->move_along(length($1)); + if (length($1) == length($data)) { + $data = $reader->data; + } + else { + last; + } + } + $char = chr($ref); + } + $reader->match(';') || + $self->parser_error("No semi-colon found after character reference", $reader); + if ($char !~ $SingleChar) { # match a single character + $self->parser_error("Character reference '&#$ref;' refers to an illegal XML character ($char)", $reader); + } + $value .= $char; + } + else { + # entity refs in entities get expanded later, so don't parse now. + $value .= '&'; + } + } + elsif ($reader->match('%')) { + $value .= $self->PEReference($reader); + } + elsif ($reader->match($quote)) { + # end of attrib + last; + } + else { + $self->parser_error("Invalid character in attribute value: " . substr($reader->data, 0, 1), $reader); + } + } + + return $value; +} + +sub NDataDecl { + my ($self, $reader) = @_; + $self->skip_whitespace($reader) || return ''; + my $data = $reader->data(5); + return '' unless $data =~ /^NDATA/; + $reader->move_along(5); + $self->skip_whitespace($reader) || $self->parser_error("No whitespace after NDATA declaration", $reader); + my $name = $self->Name($reader) || $self->parser_error("NDATA declaration lacks a proper Name", $reader); + return " NDATA $name"; +} + +sub NotationDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(10); + return 0 unless $data =~ /^<!NOTATION/; + $reader->move_along(10); + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after NOTATION declaration", $reader); + $data = $reader->data; + my $value = ''; + while(1) { + $self->parser_error("EOF found while looking for end of NotationDecl", $reader) + unless length($data); + + if ($data =~ /^([^>]*)>/) { + $value .= $1; + $reader->move_along(length($1) + 1); + $self->notation_decl({Name => "FIXME", SystemId => "FIXME", PublicId => "FIXME" }); + last; + } + else { + $value .= $data; + $reader->move_along(length($data)); + $data = $reader->data; + } + } + return 1; +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DebugHandler.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DebugHandler.pm new file mode 100755 index 00000000000..1afcec28547 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DebugHandler.pm @@ -0,0 +1,95 @@ +# $Id: DebugHandler.pm,v 1.3 2001-11-24 17:47:53 matt Exp $ + +package XML::SAX::PurePerl::DebugHandler; + +use strict; + +sub new { + my $class = shift; + my %opts = @_; + return bless \%opts, $class; +} + +# DocumentHandler + +sub set_document_locator { + my $self = shift; + print "set_document_locator\n" if $ENV{DEBUG_XML}; + $self->{seen}{set_document_locator}++; +} + +sub start_document { + my $self = shift; + print "start_document\n" if $ENV{DEBUG_XML}; + $self->{seen}{start_document}++; +} + +sub end_document { + my $self = shift; + print "end_document\n" if $ENV{DEBUG_XML}; + $self->{seen}{end_document}++; +} + +sub start_element { + my $self = shift; + print "start_element\n" if $ENV{DEBUG_XML}; + $self->{seen}{start_element}++; +} + +sub end_element { + my $self = shift; + print "end_element\n" if $ENV{DEBUG_XML}; + $self->{seen}{end_element}++; +} + +sub characters { + my $self = shift; + print "characters\n" if $ENV{DEBUG_XML}; +# warn "Char: ", $_[0]->{Data}, "\n"; + $self->{seen}{characters}++; +} + +sub processing_instruction { + my $self = shift; + print "processing_instruction\n" if $ENV{DEBUG_XML}; + $self->{seen}{processing_instruction}++; +} + +sub ignorable_whitespace { + my $self = shift; + print "ignorable_whitespace\n" if $ENV{DEBUG_XML}; + $self->{seen}{ignorable_whitespace}++; +} + +# LexHandler + +sub comment { + my $self = shift; + print "comment\n" if $ENV{DEBUG_XML}; + $self->{seen}{comment}++; +} + +# DTDHandler + +sub notation_decl { + my $self = shift; + print "notation_decl\n" if $ENV{DEBUG_XML}; + $self->{seen}{notation_decl}++; +} + +sub unparsed_entity_decl { + my $self = shift; + print "unparsed_entity_decl\n" if $ENV{DEBUG_XML}; + $self->{seen}{entity_decl}++; +} + +# EntityResolver + +sub resolve_entity { + my $self = shift; + print "resolve_entity\n" if $ENV{DEBUG_XML}; + $self->{seen}{resolve_entity}++; + return ''; +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DocType.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DocType.pm new file mode 100755 index 00000000000..7ec7c9e38bb --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/DocType.pm @@ -0,0 +1,180 @@ +# $Id: DocType.pm,v 1.3 2003-07-30 13:39:22 matt Exp $ + +package XML::SAX::PurePerl; + +use strict; +use XML::SAX::PurePerl::Productions qw($PubidChar); + +sub doctypedecl { + my ($self, $reader) = @_; + + my $data = $reader->data(9); + if ($data =~ /^<!DOCTYPE/) { + $reader->move_along(9); + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after doctype declaration", $reader); + + my $root_name = $self->Name($reader) || + $self->parser_error("Doctype declaration has no root element name", $reader); + + if ($self->skip_whitespace($reader)) { + # might be externalid... + my %dtd = $self->ExternalID($reader); + # TODO: Call SAX event + } + + $self->skip_whitespace($reader); + + $self->InternalSubset($reader); + + $reader->match('>') or $self->parser_error("Doctype not closed", $reader); + + return 1; + } + + return 0; +} + +sub ExternalID { + my ($self, $reader) = @_; + + my $data = $reader->data(6); + + if ($data =~ /^SYSTEM/) { + $reader->move_along(6); + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after SYSTEM identifier", $reader); + return (SYSTEM => $self->SystemLiteral($reader)); + } + elsif ($data =~ /^PUBLIC/) { + $reader->move_along(6); + $self->skip_whitespace($reader) || + $self->parser_error("No whitespace after PUBLIC identifier", $reader); + + my $quote = $self->quote($reader) || + $self->parser_error("Not a quote character in PUBLIC identifier", $reader); + + my $data = $reader->data; + my $pubid = ''; + while(1) { + $self->parser_error("EOF while looking for end of PUBLIC identifiier", $reader) + unless length($data); + + if ($data =~ /^([^$quote]*)$quote/) { + $pubid .= $1; + $reader->move_along(length($1) + 1); + last; + } + else { + $pubid .= $data; + $reader->move_along(length($data)); + $data = $reader->data; + } + } + + if ($pubid !~ /^($PubidChar)+$/) { + $self->parser_error("Invalid characters in PUBLIC identifier", $reader); + } + + $self->skip_whitespace($reader) || + $self->parser_error("Not whitespace after PUBLIC ID in DOCTYPE", $reader); + + return (PUBLIC => $pubid, + SYSTEM => $self->SystemLiteral($reader)); + } + else { + return; + } + + return 1; +} + +sub SystemLiteral { + my ($self, $reader) = @_; + + my $quote = $self->quote($reader); + + my $data = $reader->data; + my $systemid = ''; + while (1) { + $self->parser_error("EOF found while looking for end of Sytem Literal", $reader) + unless length($data); + if ($data =~ /^([^$quote]*)$quote/) { + $systemid .= $1; + $reader->move_along(length($1) + 1); + return $systemid; + } + else { + $systemid .= $data; + $reader->move_along(length($data)); + $data = $reader->data; + } + } +} + +sub InternalSubset { + my ($self, $reader) = @_; + + return 0 unless $reader->match('['); + + 1 while $self->IntSubsetDecl($reader); + + $reader->match(']') or $self->parser_error("No close bracket on internal subset (found: " . $reader->data, $reader); + $self->skip_whitespace($reader); + return 1; +} + +sub IntSubsetDecl { + my ($self, $reader) = @_; + + return $self->DeclSep($reader) || $self->markupdecl($reader); +} + +sub DeclSep { + my ($self, $reader) = @_; + + if ($self->skip_whitespace($reader)) { + return 1; + } + + if ($self->PEReference($reader)) { + return 1; + } + +# if ($self->ParsedExtSubset($reader)) { +# return 1; +# } + + return 0; +} + +sub PEReference { + my ($self, $reader) = @_; + + return 0 unless $reader->match('%'); + + my $peref = $self->Name($reader) || + $self->parser_error("PEReference did not find a Name", $reader); + # TODO - load/parse the peref + + $reader->match(';') or $self->parser_error("Invalid token in PEReference", $reader); + return 1; +} + +sub markupdecl { + my ($self, $reader) = @_; + + if ($self->elementdecl($reader) || + $self->AttlistDecl($reader) || + $self->EntityDecl($reader) || + $self->NotationDecl($reader) || + $self->PI($reader) || + $self->Comment($reader)) + { + return 1; + } + + return 0; +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/EncodingDetect.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/EncodingDetect.pm new file mode 100755 index 00000000000..6f1c8eadcbd --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/EncodingDetect.pm @@ -0,0 +1,105 @@ +# $Id: EncodingDetect.pm,v 1.6 2007-02-07 09:33:50 grant Exp $ + +package XML::SAX::PurePerl; # NB, not ::EncodingDetect! + +use strict; + +sub encoding_detect { + my ($parser, $reader) = @_; + + my $error = "Invalid byte sequence at start of file"; + + my $data = $reader->data; + if ($data =~ /^\x00\x00\xFE\xFF/) { + # BO-UCS4-be + $reader->move_along(4); + $reader->set_encoding('UCS-4BE'); + return; + } + elsif ($data =~ /^\x00\x00\xFF\xFE/) { + # BO-UCS-4-2143 + $reader->move_along(4); + $reader->set_encoding('UCS-4-2143'); + return; + } + elsif ($data =~ /^\x00\x00\x00\x3C/) { + $reader->set_encoding('UCS-4BE'); + return; + } + elsif ($data =~ /^\x00\x00\x3C\x00/) { + $reader->set_encoding('UCS-4-2143'); + return; + } + elsif ($data =~ /^\x00\x3C\x00\x00/) { + $reader->set_encoding('UCS-4-3412'); + return; + } + elsif ($data =~ /^\x00\x3C\x00\x3F/) { + $reader->set_encoding('UTF-16BE'); + return; + } + elsif ($data =~ /^\xFF\xFE\x00\x00/) { + # BO-UCS-4LE + $reader->move_along(4); + $reader->set_encoding('UCS-4LE'); + return; + } + elsif ($data =~ /^\xFF\xFE/) { + $reader->move_along(2); + $reader->set_encoding('UTF-16LE'); + return; + } + elsif ($data =~ /^\xFE\xFF\x00\x00/) { + $reader->move_along(4); + $reader->set_encoding('UCS-4-3412'); + return; + } + elsif ($data =~ /^\xFE\xFF/) { + $reader->move_along(2); + $reader->set_encoding('UTF-16BE'); + return; + } + elsif ($data =~ /^\xEF\xBB\xBF/) { # UTF-8 BOM + $reader->move_along(3); + $reader->set_encoding('UTF-8'); + return; + } + elsif ($data =~ /^\x3C\x00\x00\x00/) { + $reader->set_encoding('UCS-4LE'); + return; + } + elsif ($data =~ /^\x3C\x00\x3F\x00/) { + $reader->set_encoding('UTF-16LE'); + return; + } + elsif ($data =~ /^\x3C\x3F\x78\x6D/) { + # $reader->set_encoding('UTF-8'); + return; + } + elsif ($data =~ /^\x3C\x3F\x78/) { + # $reader->set_encoding('UTF-8'); + return; + } + elsif ($data =~ /^\x3C\x3F/) { + # $reader->set_encoding('UTF-8'); + return; + } + elsif ($data =~ /^\x3C/) { + # $reader->set_encoding('UTF-8'); + return; + } + elsif ($data =~ /^[\x20\x09\x0A\x0D]+\x3C[^\x3F]/) { + # $reader->set_encoding('UTF-8'); + return; + } + elsif ($data =~ /^\x4C\x6F\xA7\x94/) { + $reader->set_encoding('EBCDIC'); + return; + } + + warn("Unable to recognise encoding of this document"); + return; +} + +1; + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Exception.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Exception.pm new file mode 100755 index 00000000000..6a0d1b6b524 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Exception.pm @@ -0,0 +1,67 @@ +# $Id: Exception.pm,v 1.2 2001-11-14 11:07:25 matt Exp $ + +package XML::SAX::PurePerl::Exception; + +use strict; + +use overload '""' => "stringify"; + +use vars qw/$StackTrace/; + +$StackTrace = $ENV{XML_DEBUG} || 0; + +sub throw { + my $class = shift; + die $class->new(@_); +} + +sub new { + my $class = shift; + my %opts = @_; + die "Invalid options" unless exists $opts{Message}; + + if ($opts{reader}) { + return bless { Message => $opts{Message}, + Exception => undef, # not sure what this is for!!! + ColumnNumber => $opts{reader}->column, + LineNumber => $opts{reader}->line, + PublicId => $opts{reader}->public_id, + SystemId => $opts{reader}->system_id, + $StackTrace ? (StackTrace => stacktrace()) : (), + }, $class; + } + return bless { Message => $opts{Message}, + Exception => undef, # not sure what this is for!!! + }, $class; +} + +sub stringify { + my $self = shift; + local $^W; + return $self->{Message} . " [Ln: " . $self->{LineNumber} . + ", Col: " . $self->{ColumnNumber} . "]" . + ($StackTrace ? stackstring($self->{StackTrace}) : "") . "\n"; +} + +sub stacktrace { + my $i = 2; + my @fulltrace; + while (my @trace = caller($i++)) { + my %hash; + @hash{qw(Package Filename Line)} = @trace[0..2]; + push @fulltrace, \%hash; + } + return \@fulltrace; +} + +sub stackstring { + my $stacktrace = shift; + my $string = "\nFrom:\n"; + foreach my $current (@$stacktrace) { + $string .= $current->{Filename} . " Line: " . $current->{Line} . "\n"; + } + return $string; +} + +1; + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/NoUnicodeExt.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/NoUnicodeExt.pm new file mode 100755 index 00000000000..334e52bee76 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/NoUnicodeExt.pm @@ -0,0 +1,28 @@ +# $Id: NoUnicodeExt.pm,v 1.1 2002-01-30 17:35:21 matt Exp $ + +package XML::SAX::PurePerl; +use strict; + +sub chr_ref { + my $n = shift; + if ($n < 0x80) { + return chr ($n); + } + elsif ($n < 0x800) { + return pack ("CC", (($n >> 6) | 0xc0), (($n & 0x3f) | 0x80)); + } + elsif ($n < 0x10000) { + return pack ("CCC", (($n >> 12) | 0xe0), ((($n >> 6) & 0x3f) | 0x80), + (($n & 0x3f) | 0x80)); + } + elsif ($n < 0x110000) + { + return pack ("CCCC", (($n >> 18) | 0xf0), ((($n >> 12) & 0x3f) | 0x80), + ((($n >> 6) & 0x3f) | 0x80), (($n & 0x3f) | 0x80)); + } + else { + return undef; + } +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Productions.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Productions.pm new file mode 100755 index 00000000000..3060960b79f --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Productions.pm @@ -0,0 +1,147 @@ +# $Id: Productions.pm,v 1.13 2008-08-05 12:37:13 grant Exp $ + +package XML::SAX::PurePerl::Productions; + +use Exporter; +@ISA = ('Exporter'); +@EXPORT_OK = qw($S $Char $VersionNum $BaseChar $Ideographic + $Extender $Digit $CombiningChar $EncNameStart $EncNameEnd $NameChar $CharMinusDash + $PubidChar $Any $SingleChar); + +### WARNING!!! All productions here must *only* match a *single* character!!! ### + +BEGIN { +$S = qr/[\x20\x09\x0D\x0A]/; + +$CharMinusDash = qr/[^-]/x; + +$Any = qr/ . /xms; + +$VersionNum = qr/ [a-zA-Z0-9_.:-]+ /x; + +$EncNameStart = qr/ [A-Za-z] /x; +$EncNameEnd = qr/ [A-Za-z0-9\._-] /x; + +$PubidChar = qr/ [\x20\x0D\x0Aa-zA-Z0-9'()\+,.\/:=\?;!*\#@\$_\%-] /x; + +if ($] < 5.006) { + eval <<' PERL'; + $Char = qr/^ [\x09\x0A\x0D\x20-\x7F]|([\xC0-\xFD][\x80-\xBF]+) $/x; + + $SingleChar = qr/^$Char$/; + + $BaseChar = qr/ [\x41-\x5A\x61-\x7A]|([\xC0-\xFD][\x80-\xBF]+) /x; + + $Extender = qr/ \xB7 /x; + + $Digit = qr/ [\x30-\x39] /x; + + # can't do this one without unicode + # $CombiningChar = qr/^$/msx; + + $NameChar = qr/^ (?: $BaseChar | $Digit | [._:-] | $Extender )+ $/x; + PERL + die $@ if $@; +} +else { + eval <<' PERL'; + + use utf8; # for 5.6 + + $Char = qr/^ [\x09\x0A\x0D\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}] $/x; + + $SingleChar = qr/^$Char$/; + + $BaseChar = qr/ +[\x{0041}-\x{005A}\x{0061}-\x{007A}\x{00C0}-\x{00D6}\x{00D8}-\x{00F6}] | +[\x{00F8}-\x{00FF}\x{0100}-\x{0131}\x{0134}-\x{013E}\x{0141}-\x{0148}] | +[\x{014A}-\x{017E}\x{0180}-\x{01C3}\x{01CD}-\x{01F0}\x{01F4}-\x{01F5}] | +[\x{01FA}-\x{0217}\x{0250}-\x{02A8}\x{02BB}-\x{02C1}\x{0386}\x{0388}-\x{038A}] | +[\x{038C}\x{038E}-\x{03A1}\x{03A3}-\x{03CE}\x{03D0}-\x{03D6}\x{03DA}] | +[\x{03DC}\x{03DE}\x{03E0}\x{03E2}-\x{03F3}\x{0401}-\x{040C}\x{040E}-\x{044F}] | +[\x{0451}-\x{045C}\x{045E}-\x{0481}\x{0490}-\x{04C4}\x{04C7}-\x{04C8}] | +[\x{04CB}-\x{04CC}\x{04D0}-\x{04EB}\x{04EE}-\x{04F5}\x{04F8}-\x{04F9}] | +[\x{0531}-\x{0556}\x{0559}\x{0561}-\x{0586}\x{05D0}-\x{05EA}\x{05F0}-\x{05F2}] | +[\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0671}-\x{06B7}\x{06BA}-\x{06BE}] | +[\x{06C0}-\x{06CE}\x{06D0}-\x{06D3}\x{06D5}\x{06E5}-\x{06E6}\x{0905}-\x{0939}] | +[\x{093D}\x{0958}-\x{0961}\x{0985}-\x{098C}\x{098F}-\x{0990}] | +[\x{0993}-\x{09A8}\x{09AA}-\x{09B0}\x{09B2}\x{09B6}-\x{09B9}\x{09DC}-\x{09DD}] | +[\x{09DF}-\x{09E1}\x{09F0}-\x{09F1}\x{0A05}-\x{0A0A}\x{0A0F}-\x{0A10}] | +[\x{0A13}-\x{0A28}\x{0A2A}-\x{0A30}\x{0A32}-\x{0A33}\x{0A35}-\x{0A36}] | +[\x{0A38}-\x{0A39}\x{0A59}-\x{0A5C}\x{0A5E}\x{0A72}-\x{0A74}\x{0A85}-\x{0A8B}] | +[\x{0A8D}\x{0A8F}-\x{0A91}\x{0A93}-\x{0AA8}\x{0AAA}-\x{0AB0}] | +[\x{0AB2}-\x{0AB3}\x{0AB5}-\x{0AB9}\x{0ABD}\x{0AE0}\x{0B05}-\x{0B0C}] | +[\x{0B0F}-\x{0B10}\x{0B13}-\x{0B28}\x{0B2A}-\x{0B30}\x{0B32}-\x{0B33}] | +[\x{0B36}-\x{0B39}\x{0B3D}\x{0B5C}-\x{0B5D}\x{0B5F}-\x{0B61}\x{0B85}-\x{0B8A}] | +[\x{0B8E}-\x{0B90}\x{0B92}-\x{0B95}\x{0B99}-\x{0B9A}\x{0B9C}] | +[\x{0B9E}-\x{0B9F}\x{0BA3}-\x{0BA4}\x{0BA8}-\x{0BAA}\x{0BAE}-\x{0BB5}] | +[\x{0BB7}-\x{0BB9}\x{0C05}-\x{0C0C}\x{0C0E}-\x{0C10}\x{0C12}-\x{0C28}] | +[\x{0C2A}-\x{0C33}\x{0C35}-\x{0C39}\x{0C60}-\x{0C61}\x{0C85}-\x{0C8C}] | +[\x{0C8E}-\x{0C90}\x{0C92}-\x{0CA8}\x{0CAA}-\x{0CB3}\x{0CB5}-\x{0CB9}\x{0CDE}] | +[\x{0CE0}-\x{0CE1}\x{0D05}-\x{0D0C}\x{0D0E}-\x{0D10}\x{0D12}-\x{0D28}] | +[\x{0D2A}-\x{0D39}\x{0D60}-\x{0D61}\x{0E01}-\x{0E2E}\x{0E30}\x{0E32}-\x{0E33}] | +[\x{0E40}-\x{0E45}\x{0E81}-\x{0E82}\x{0E84}\x{0E87}-\x{0E88}\x{0E8A}] | +[\x{0E8D}\x{0E94}-\x{0E97}\x{0E99}-\x{0E9F}\x{0EA1}-\x{0EA3}\x{0EA5}\x{0EA7}] | +[\x{0EAA}-\x{0EAB}\x{0EAD}-\x{0EAE}\x{0EB0}\x{0EB2}-\x{0EB3}\x{0EBD}] | +[\x{0EC0}-\x{0EC4}\x{0F40}-\x{0F47}\x{0F49}-\x{0F69}\x{10A0}-\x{10C5}] | +[\x{10D0}-\x{10F6}\x{1100}\x{1102}-\x{1103}\x{1105}-\x{1107}\x{1109}] | +[\x{110B}-\x{110C}\x{110E}-\x{1112}\x{113C}\x{113E}\x{1140}\x{114C}\x{114E}] | +[\x{1150}\x{1154}-\x{1155}\x{1159}\x{115F}-\x{1161}\x{1163}\x{1165}] | +[\x{1167}\x{1169}\x{116D}-\x{116E}\x{1172}-\x{1173}\x{1175}\x{119E}\x{11A8}] | +[\x{11AB}\x{11AE}-\x{11AF}\x{11B7}-\x{11B8}\x{11BA}\x{11BC}-\x{11C2}] | +[\x{11EB}\x{11F0}\x{11F9}\x{1E00}-\x{1E9B}\x{1EA0}-\x{1EF9}\x{1F00}-\x{1F15}] | +[\x{1F18}-\x{1F1D}\x{1F20}-\x{1F45}\x{1F48}-\x{1F4D}\x{1F50}-\x{1F57}] | +[\x{1F59}\x{1F5B}\x{1F5D}\x{1F5F}-\x{1F7D}\x{1F80}-\x{1FB4}\x{1FB6}-\x{1FBC}] | +[\x{1FBE}\x{1FC2}-\x{1FC4}\x{1FC6}-\x{1FCC}\x{1FD0}-\x{1FD3}] | +[\x{1FD6}-\x{1FDB}\x{1FE0}-\x{1FEC}\x{1FF2}-\x{1FF4}\x{1FF6}-\x{1FFC}] | +[\x{2126}\x{212A}-\x{212B}\x{212E}\x{2180}-\x{2182}\x{3041}-\x{3094}] | +[\x{30A1}-\x{30FA}\x{3105}-\x{312C}\x{AC00}-\x{D7A3}] + /x; + + $Extender = qr/ +[\x{00B7}\x{02D0}\x{02D1}\x{0387}\x{0640}\x{0E46}\x{0EC6}\x{3005}\x{3031}-\x{3035}\x{309D}-\x{309E}\x{30FC}-\x{30FE}] +/x; + + $Digit = qr/ +[\x{0030}-\x{0039}\x{0660}-\x{0669}\x{06F0}-\x{06F9}\x{0966}-\x{096F}] | +[\x{09E6}-\x{09EF}\x{0A66}-\x{0A6F}\x{0AE6}-\x{0AEF}\x{0B66}-\x{0B6F}] | +[\x{0BE7}-\x{0BEF}\x{0C66}-\x{0C6F}\x{0CE6}-\x{0CEF}\x{0D66}-\x{0D6F}] | +[\x{0E50}-\x{0E59}\x{0ED0}-\x{0ED9}\x{0F20}-\x{0F29}] +/x; + + $CombiningChar = qr/ +[\x{0300}-\x{0345}\x{0360}-\x{0361}\x{0483}-\x{0486}\x{0591}-\x{05A1}] | +[\x{05A3}-\x{05B9}\x{05BB}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}] | +[\x{064B}-\x{0652}\x{0670}\x{06D6}-\x{06DC}\x{06DD}-\x{06DF}\x{06E0}-\x{06E4}] | +[\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{0901}-\x{0903}\x{093C}] | +[\x{093E}-\x{094C}\x{094D}\x{0951}-\x{0954}\x{0962}-\x{0963}\x{0981}-\x{0983}] | +[\x{09BC}\x{09BE}\x{09BF}\x{09C0}-\x{09C4}\x{09C7}-\x{09C8}] | +[\x{09CB}-\x{09CD}\x{09D7}\x{09E2}-\x{09E3}\x{0A02}\x{0A3C}\x{0A3E}\x{0A3F}] | +[\x{0A40}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A70}-\x{0A71}] | +[\x{0A81}-\x{0A83}\x{0ABC}\x{0ABE}-\x{0AC5}\x{0AC7}-\x{0AC9}\x{0ACB}-\x{0ACD}] | +[\x{0B01}-\x{0B03}\x{0B3C}\x{0B3E}-\x{0B43}\x{0B47}-\x{0B48}] | +[\x{0B4B}-\x{0B4D}\x{0B56}-\x{0B57}\x{0B82}-\x{0B83}\x{0BBE}-\x{0BC2}] | +[\x{0BC6}-\x{0BC8}\x{0BCA}-\x{0BCD}\x{0BD7}\x{0C01}-\x{0C03}\x{0C3E}-\x{0C44}] | +[\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C82}-\x{0C83}] | +[\x{0CBE}-\x{0CC4}\x{0CC6}-\x{0CC8}\x{0CCA}-\x{0CCD}\x{0CD5}-\x{0CD6}] | +[\x{0D02}-\x{0D03}\x{0D3E}-\x{0D43}\x{0D46}-\x{0D48}\x{0D4A}-\x{0D4D}\x{0D57}] | +[\x{0E31}\x{0E34}-\x{0E3A}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}] | +[\x{0EBB}-\x{0EBC}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}] | +[\x{0F3E}\x{0F3F}\x{0F71}-\x{0F84}\x{0F86}-\x{0F8B}\x{0F90}-\x{0F95}] | +[\x{0F97}\x{0F99}-\x{0FAD}\x{0FB1}-\x{0FB7}\x{0FB9}\x{20D0}-\x{20DC}\x{20E1}] | +[\x{302A}-\x{302F}\x{3099}\x{309A}] +/x; + + $Ideographic = qr/ +[\x{4E00}-\x{9FA5}\x{3007}\x{3021}-\x{3029}] +/x; + + $NameChar = qr/^ (?: $BaseChar | $Ideographic | $Digit | [._:-] | $CombiningChar | $Extender )+ $/x; + PERL + + die $@ if $@; +} + +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader.pm new file mode 100755 index 00000000000..d901e7d2f50 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader.pm @@ -0,0 +1,136 @@ +# $Id: Reader.pm,v 1.13 2008-08-05 12:37:13 grant Exp $ + +package XML::SAX::PurePerl::Reader; + +use strict; +use XML::SAX::PurePerl::Reader::URI; +use Exporter (); + +use vars qw(@ISA @EXPORT_OK); +@ISA = qw(Exporter); +@EXPORT_OK = qw( + EOF + BUFFER + LINE + COLUMN + ENCODING + XML_VERSION +); + +use constant EOF => 0; +use constant BUFFER => 1; +use constant LINE => 2; +use constant COLUMN => 3; +use constant ENCODING => 4; +use constant SYSTEM_ID => 5; +use constant PUBLIC_ID => 6; +use constant XML_VERSION => 7; + +require XML::SAX::PurePerl::Reader::Stream; +require XML::SAX::PurePerl::Reader::String; + +if ($] >= 5.007002) { + require XML::SAX::PurePerl::Reader::UnicodeExt; +} +else { + require XML::SAX::PurePerl::Reader::NoUnicodeExt; +} + +sub new { + my $class = shift; + my $thing = shift; + + # try to figure if this $thing is a handle of some sort + if (ref($thing) && UNIVERSAL::isa($thing, 'IO::Handle')) { + return XML::SAX::PurePerl::Reader::Stream->new($thing)->init; + } + my $ioref; + if (tied($thing)) { + my $class = ref($thing); + no strict 'refs'; + $ioref = $thing if defined &{"${class}::TIEHANDLE"}; + } + else { + eval { + $ioref = *{$thing}{IO}; + }; + undef $@; + } + if ($ioref) { + return XML::SAX::PurePerl::Reader::Stream->new($thing)->init; + } + + if ($thing =~ /</) { + # assume it's a string + return XML::SAX::PurePerl::Reader::String->new($thing)->init; + } + + # assume it is a uri + return XML::SAX::PurePerl::Reader::URI->new($thing)->init; +} + +sub init { + my $self = shift; + $self->[LINE] = 1; + $self->[COLUMN] = 1; + $self->read_more; + return $self; +} + +sub data { + my ($self, $min_length) = (@_, 1); + if (length($self->[BUFFER]) < $min_length) { + $self->read_more; + } + return $self->[BUFFER]; +} + +sub match { + my ($self, $char) = @_; + my $data = $self->data; + if (substr($data, 0, 1) eq $char) { + $self->move_along(1); + return 1; + } + return 0; +} + +sub public_id { + my $self = shift; + @_ and $self->[PUBLIC_ID] = shift; + $self->[PUBLIC_ID]; +} + +sub system_id { + my $self = shift; + @_ and $self->[SYSTEM_ID] = shift; + $self->[SYSTEM_ID]; +} + +sub line { + shift->[LINE]; +} + +sub column { + shift->[COLUMN]; +} + +sub get_encoding { + my $self = shift; + return $self->[ENCODING]; +} + +sub get_xml_version { + my $self = shift; + return $self->[XML_VERSION]; +} + +1; + +__END__ + +=head1 NAME + +XML::Parser::PurePerl::Reader - Abstract Reader factory class + +=cut diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/NoUnicodeExt.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/NoUnicodeExt.pm new file mode 100755 index 00000000000..d551710d0d3 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/NoUnicodeExt.pm @@ -0,0 +1,25 @@ +# $Id: NoUnicodeExt.pm,v 1.3 2003-07-30 13:39:23 matt Exp $ + +package XML::SAX::PurePerl::Reader; +use strict; + +sub set_raw_stream { + # no-op +} + +sub switch_encoding_stream { + my ($fh, $encoding) = @_; + throw XML::SAX::Exception::Parse ( + Message => "Only ASCII encoding allowed without perl 5.7.2 or higher. You tried: $encoding", + ) if $encoding !~ /(ASCII|UTF\-?8)/i; +} + +sub switch_encoding_string { + my (undef, $encoding) = @_; + throw XML::SAX::Exception::Parse ( + Message => "Only ASCII encoding allowed without perl 5.7.2 or higher. You tried: $encoding", + ) if $encoding !~ /(ASCII|UTF\-?8)/i; +} + +1; + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/Stream.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/Stream.pm new file mode 100755 index 00000000000..794aac4d4d1 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/Stream.pm @@ -0,0 +1,84 @@ +# $Id: Stream.pm,v 1.7 2005-10-14 20:31:20 matt Exp $ + +package XML::SAX::PurePerl::Reader::Stream; + +use strict; +use vars qw(@ISA); + +use XML::SAX::PurePerl::Reader qw( + EOF + BUFFER + LINE + COLUMN + ENCODING + XML_VERSION +); +use XML::SAX::Exception; + +@ISA = ('XML::SAX::PurePerl::Reader'); + +# subclassed by adding 1 to last element +use constant FH => 8; +use constant BUFFER_SIZE => 4096; + +sub new { + my $class = shift; + my $ioref = shift; + XML::SAX::PurePerl::Reader::set_raw_stream($ioref); + my @parts; + @parts[FH, LINE, COLUMN, BUFFER, EOF, XML_VERSION] = + ($ioref, 1, 0, '', 0, '1.0'); + return bless \@parts, $class; +} + +sub read_more { + my $self = shift; + my $buf; + my $bytesread = read($self->[FH], $buf, BUFFER_SIZE); + if ($bytesread) { + $self->[BUFFER] .= $buf; + return 1; + } + elsif (defined($bytesread)) { + $self->[EOF]++; + return 0; + } + else { + throw XML::SAX::Exception::Parse( + Message => "Error reading from filehandle: $!", + ); + } +} + +sub move_along { + my $self = shift; + my $discarded = substr($self->[BUFFER], 0, $_[0], ''); + + # Wish I could skip this lot - tells us where we are in the file + my $lines = $discarded =~ tr/\n//; + $self->[LINE] += $lines; + if ($lines) { + $discarded =~ /\n([^\n]*)$/; + $self->[COLUMN] = length($1); + } + else { + $self->[COLUMN] += $_[0]; + } +} + +sub set_encoding { + my $self = shift; + my ($encoding) = @_; + # warn("set encoding to: $encoding\n"); + XML::SAX::PurePerl::Reader::switch_encoding_stream($self->[FH], $encoding); + XML::SAX::PurePerl::Reader::switch_encoding_string($self->[BUFFER], $encoding); + $self->[ENCODING] = $encoding; +} + +sub bytepos { + my $self = shift; + tell($self->[FH]); +} + +1; + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/String.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/String.pm new file mode 100755 index 00000000000..62b5d0bfb0f --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/String.pm @@ -0,0 +1,78 @@ +# $Id: String.pm,v 1.6 2008-08-04 03:35:44 grant Exp $ + +package XML::SAX::PurePerl::Reader::String; + +use strict; +use vars qw(@ISA); + +use XML::SAX::PurePerl::Reader qw( + LINE + COLUMN + BUFFER + ENCODING + EOF +); + +@ISA = ('XML::SAX::PurePerl::Reader'); + +use constant DISCARDED => 8; +use constant STRING => 9; +use constant USED => 10; +use constant CHUNK_SIZE => 2048; + +sub new { + my $class = shift; + my $string = shift; + my @parts; + @parts[BUFFER, EOF, LINE, COLUMN, DISCARDED, STRING, USED] = + ('', 0, 1, 0, 0, $string, 0); + return bless \@parts, $class; +} + +sub read_more () { + my $self = shift; + if ($self->[USED] >= length($self->[STRING])) { + $self->[EOF]++; + return 0; + } + my $bytes = CHUNK_SIZE; + if ($bytes > (length($self->[STRING]) - $self->[USED])) { + $bytes = (length($self->[STRING]) - $self->[USED]); + } + $self->[BUFFER] .= substr($self->[STRING], $self->[USED], $bytes); + $self->[USED] += $bytes; + return 1; + } + + +sub move_along { + my($self, $bytes) = @_; + my $discarded = substr($self->[BUFFER], 0, $bytes, ''); + $self->[DISCARDED] += length($discarded); + + # Wish I could skip this lot - tells us where we are in the file + my $lines = $discarded =~ tr/\n//; + $self->[LINE] += $lines; + if ($lines) { + $discarded =~ /\n([^\n]*)$/; + $self->[COLUMN] = length($1); + } + else { + $self->[COLUMN] += $_[0]; + } +} + +sub set_encoding { + my $self = shift; + my ($encoding) = @_; + + XML::SAX::PurePerl::Reader::switch_encoding_string($self->[BUFFER], $encoding, "utf-8"); + $self->[ENCODING] = $encoding; +} + +sub bytepos { + my $self = shift; + $self->[DISCARDED]; +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/URI.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/URI.pm new file mode 100755 index 00000000000..20c92d6c627 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/URI.pm @@ -0,0 +1,57 @@ +# $Id: URI.pm,v 1.1 2001-11-11 18:41:51 matt Exp $ + +package XML::SAX::PurePerl::Reader::URI; + +use strict; + +use XML::SAX::PurePerl::Reader; +use File::Temp qw(tempfile); +use Symbol; + +## NOTE: This is *not* a subclass of Reader. It just returns Stream or String +## Reader objects depending on what it's capabilities are. + +sub new { + my $class = shift; + my $uri = shift; + # request the URI + if (-e $uri && -f _) { + my $fh = gensym; + open($fh, $uri) || die "Cannot open file $uri : $!"; + return XML::SAX::PurePerl::Reader::Stream->new($fh); + } + elsif ($uri =~ /^file:(.*)$/ && -e $1 && -f _) { + my $file = $1; + my $fh = gensym; + open($fh, $file) || die "Cannot open file $file : $!"; + return XML::SAX::PurePerl::Reader::Stream->new($fh); + } + else { + # request URI, return String reader + require LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->agent("Perl/XML/SAX/PurePerl/1.0 " . $ua->agent); + + my $req = HTTP::Request->new(GET => $uri); + + my $fh = tempfile(); + + my $callback = sub { + my ($data, $response, $protocol) = @_; + print $fh $data; + }; + + my $res = $ua->request($req, $callback, 4096); + + if ($res->is_success) { + seek($fh, 0, 0); + return XML::SAX::PurePerl::Reader::Stream->new($fh); + } + else { + die "LWP Request Failed"; + } + } +} + + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/UnicodeExt.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/UnicodeExt.pm new file mode 100755 index 00000000000..07510683712 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/Reader/UnicodeExt.pm @@ -0,0 +1,23 @@ +# $Id: UnicodeExt.pm,v 1.5 2008-08-04 10:04:54 grant Exp $ + +package XML::SAX::PurePerl::Reader; +use strict; + +use Encode (); + +sub set_raw_stream { + my ($fh) = @_; + binmode($fh, ":bytes"); +} + +sub switch_encoding_stream { + my ($fh, $encoding) = @_; + binmode($fh, ":encoding($encoding)"); +} + +sub switch_encoding_string { + $_[0] = Encode::decode($_[1], $_[0]); +} + +1; + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/UnicodeExt.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/UnicodeExt.pm new file mode 100755 index 00000000000..cbfe4e83f49 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/UnicodeExt.pm @@ -0,0 +1,22 @@ +# $Id: UnicodeExt.pm,v 1.1 2002-01-30 17:35:21 matt Exp $ + +package XML::SAX::PurePerl; +use strict; + +no warnings 'utf8'; + +sub chr_ref { + return chr(shift); +} + +if ($] >= 5.007002) { + require Encode; + + Encode::define_alias( "UTF-16" => "UCS-2" ); + Encode::define_alias( "UTF-16BE" => "UCS-2" ); + Encode::define_alias( "UTF-16LE" => "ucs-2le" ); + Encode::define_alias( "UTF16LE" => "ucs-2le" ); +} + +1; + diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/XMLDecl.pm b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/XMLDecl.pm new file mode 100755 index 00000000000..4672c20a757 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/PurePerl/XMLDecl.pm @@ -0,0 +1,129 @@ +# $Id: XMLDecl.pm,v 1.3 2003-07-30 13:39:22 matt Exp $ + +package XML::SAX::PurePerl; + +use strict; +use XML::SAX::PurePerl::Productions qw($S $VersionNum $EncNameStart $EncNameEnd); + +sub XMLDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(5); + # warn("Looking for xmldecl in: $data"); + if ($data =~ /^<\?xml$S/o) { + $reader->move_along(5); + $self->skip_whitespace($reader); + + # get version attribute + $self->VersionInfo($reader) || + $self->parser_error("XML Declaration lacks required version attribute, or version attribute does not match XML specification", $reader); + + if (!$self->skip_whitespace($reader)) { + my $data = $reader->data(2); + $data =~ /^\?>/ or $self->parser_error("Syntax error", $reader); + $reader->move_along(2); + return; + } + + if ($self->EncodingDecl($reader)) { + if (!$self->skip_whitespace($reader)) { + my $data = $reader->data(2); + $data =~ /^\?>/ or $self->parser_error("Syntax error", $reader); + $reader->move_along(2); + return; + } + } + + $self->SDDecl($reader); + + $self->skip_whitespace($reader); + + my $data = $reader->data(2); + $data =~ /^\?>/ or $self->parser_error("Syntax error", $reader); + $reader->move_along(2); + } + else { + # warn("first 5 bytes: ", join(',', unpack("CCCCC", $data)), "\n"); + # no xml decl + if (!$reader->get_encoding) { + $reader->set_encoding("UTF-8"); + } + } +} + +sub VersionInfo { + my ($self, $reader) = @_; + + my $data = $reader->data(11); + + # warn("Looking for version in $data"); + + $data =~ /^(version$S*=$S*(["'])($VersionNum)\2)/o or return 0; + $reader->move_along(length($1)); + my $vernum = $3; + + if ($vernum ne "1.0") { + $self->parser_error("Only XML version 1.0 supported. Saw: '$vernum'", $reader); + } + + return 1; +} + +sub SDDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(15); + + $data =~ /^(standalone$S*=$S*(["'])(yes|no)\2)/o or return 0; + $reader->move_along(length($1)); + my $yesno = $3; + + if ($yesno eq 'yes') { + $self->{standalone} = 1; + } + else { + $self->{standalone} = 0; + } + + return 1; +} + +sub EncodingDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(12); + + $data =~ /^(encoding$S*=$S*(["'])($EncNameStart$EncNameEnd*)\2)/o or return 0; + $reader->move_along(length($1)); + my $encoding = $3; + + $reader->set_encoding($encoding); + + return 1; +} + +sub TextDecl { + my ($self, $reader) = @_; + + my $data = $reader->data(6); + $data =~ /^<\?xml$S+/ or return; + $reader->move_along(5); + $self->skip_whitespace($reader); + + if ($self->VersionInfo($reader)) { + $self->skip_whitespace($reader) || + $self->parser_error("Lack of whitespace after version attribute in text declaration", $reader); + } + + $self->EncodingDecl($reader) || + $self->parser_error("Encoding declaration missing from external entity text declaration", $reader); + + $self->skip_whitespace($reader); + + $data = $reader->data(2); + $data =~ /^\?>/ or $self->parser_error("Syntax error", $reader); + + return 1; +} + +1; diff --git a/Master/tlpkg/tlperl/lib/XML/SAX/placeholder.pl b/Master/tlpkg/tlperl/lib/XML/SAX/placeholder.pl new file mode 100755 index 00000000000..6db59025607 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/SAX/placeholder.pl @@ -0,0 +1 @@ +# ignore me diff --git a/Master/tlpkg/tlperl/lib/XML/benchmark.pl b/Master/tlpkg/tlperl/lib/XML/benchmark.pl new file mode 100755 index 00000000000..0435116055c --- /dev/null +++ b/Master/tlpkg/tlperl/lib/XML/benchmark.pl @@ -0,0 +1,268 @@ +use Benchmark; +use Getopt::Long; +use File::Basename; +use XML::XPath; +use strict; + +$|++; + +my @default_drivers = qw( + LibXSLT + Sablotron + ); + +use vars qw( + $component $iter $ms $kb_in $kb_out $kb_sec $result $ref_size + ); + +my @getopt_args = ( + 'c=s', # config file + 'n=i', # number of benchmark times + 'd=s@', # drivers + 't', # only 1 iteration per test + 'v', # verbose + 'h', # help + 'x', # XSLTMark emulation + ); + +my %options; + +Getopt::Long::config("bundling"); + +unless (GetOptions(\%options, @getopt_args)) { + usage(); +} + +usage() if $options{h}; + +$options{c} ||= 'testcases/default.conf'; + +my $basedir = dirname($options{c}); + +$options{d} ||= [@default_drivers]; + +$options{n} ||= 1; + +# load drivers +for my $driver (@{$options{d}}) { + warn "Loading $driver Driver\n" if $options{v}; + require "Driver/$driver.pm"; +} + +# load config +my @config; +open(CONFIG, $options{c}) || die "Can't open config file '$options{c}' : $!"; +my $current = {}; +while(my $line = <CONFIG>) { + if ($line =~ /^\s*$/m && %$current) { + push @config, $current; + $current = {}; + } + + # ignore comments and full line comments + $line =~ s/#.*$//; + next unless $line =~ /\S/; + + if ($line =~ /^\s*\[(.*)\]\s*$/) { + $current->{component} = $1; + } + elsif ($line =~ /^(.*?)\s*=\s*(.*)$/) { + $current->{$1} = $2; + } +} + +for my $driver (@{$options{d}}) { + my $pkg = "Driver::${driver}"; + + $pkg->can('init')->(verbose => $options{v}); + + $pkg->can('chdir')->($basedir); + + print "Testing: $driver\n\n"; + + print_header(); + + my %totals; + + COMPONENT: + for my $cmp (@config) { + warn "Running test: $cmp->{component}\n" if $options{v}; + for (1..$options{n}) { + $component = $cmp->{component}; + $iter = $ms = $kb_in = $kb_out = $kb_sec = $ref_size = 0; + + if ($cmp->{skipdriver} =~ /\b\Q$driver\E\b/) { + $result = 'SKIPPED'; + print_output() unless $cmp->{written}; + $cmp->{written}++; + next COMPONENT; + } + + eval { + $pkg->can('load_stylesheet')->($cmp->{stylesheet}); + $pkg->can('load_input')->($cmp->{input}); + + $iter = $cmp->{iterations}; + $iter = 1 if $options{t}; + + + my $bench = timeit($iter, sub { + $pkg->can('run_transform')->($cmp->{output}); + }); + + my $str = timestr($bench, 'all', '5.4f'); + + if ($str =~ /\((\d+\.\d+)/) { + $ms = $1; + $ms *= 1000; + } + + $kb_in = (stat($cmp->{input}))[7]; + + if ($options{x}) { + $kb_in /= 1000; + } + else { + $kb_in += (stat($cmp->{stylesheet}))[7]; + $kb_in /= 1024; + } + + $kb_in *= $iter; + + $kb_out = (stat($cmp->{output}))[7]; + $kb_out /= 1024; + $kb_out *= $iter; + + die "failed - no output\n" unless $kb_out > 0; + + $kb_sec = ($kb_in + $kb_out) / + ( $ms / 500 ); + + if ($cmp->{reference}) { + $ref_size = (stat($cmp->{reference}))[7]; + $ref_size /= 1024; + + open(REFERENCE, $cmp->{reference}) || die "Can't open reference '$cmp->{reference}' : $!"; + open(NEW, $cmp->{output}) || die "Can't open transform output '$cmp->{output}' : $!"; + local $/; + my $ref = <REFERENCE>; + my $new = <NEW>; + close REFERENCE; + close NEW; + $new =~ s/\A<\?xml.*?\?>\s*//; + $new =~ s/\A<!DOCTYPE.*?>\s*//; + + if (!length($new)) { + die "output length failed\n"; + } + if ($new eq $ref) { + $result = 'OK'; + } + else { + $result = 'CHECK OUTPUT'; + eval { + my $rpp = XML::XPath->new(xml => $ref); + my $ppp = XML::XPath::XMLParser->new(xml => $new); + my $npp; + eval { + $npp = $ppp->parse; + }; + if ($@) { + $npp = $ppp->parse("<norm>$new</norm>"); + } + my @rnodes = $rpp->findnodes('//*'); + my @nnodes = $npp->findnodes('//*'); +# warn "ref nodes: ", scalar(@rnodes), "\n"; +# warn "new nodes: ", scalar(@nnodes), "\n"; + if (@rnodes == @nnodes) { + $result = 'COUNT OK'; + } + }; + if ($@) { + warn $@ if $options{v}; + } + } + } + else { + $result = 'NO REFERENCE'; + } + }; + if ($@) { + warn "$component failed: $@" if $options{v}; + $result = 'ERROR'; + } + + if (($result =~ /OK/) || ($result eq 'NO REFERENCE')) { + $totals{iter} += $iter; + $totals{ms} += $ms; + $totals{kb_in} += $kb_in; + $totals{kb_out} += $kb_out; + } + + print_output() unless $cmp->{written}; + $cmp->{written}++; + } # $options{n} loop + + delete $cmp->{written}; + } # each component + + $pkg->can('shutdown')->(); + + $component = 'total'; + $iter = $totals{iter}; + $ms = $totals{ms}; + $kb_in = $totals{kb_in}; + $kb_out = $totals{kb_out}; + $kb_sec = ($kb_in + $kb_out) / + ( $ms / 500 ); + $ref_size = 0; + $result = ''; + print_output(); +} + +sub usage { + print <<EOT; +usage: $0 [options] + + options: + + -c <file> load configuration from <file> + defaults to testcases/default.conf + + -n <num> run each test case <num> times. Default = 1. + + -t only one iteration per test case (note this + is different to -n 1) + + -d <Driver> test <Driver>. Use multiple -d options to test + more than one driver. Defaults are set in this + script (the \@default_drivers variable). + + -x XSLTMark emulation. Infuriatingly XSLTMark thinks + there are 1000 bytes in a Kilobyte. Someone please + tell them some basic computer science... + + Without this option, this benchmark also includes + the size of the stylesheet in the KB In figure. + + -v be verbose. + +Copyright 2001 AxKit.com Ltd. This is free software, you may use it and +distribute it under either the GNU GPL Version 2, or under the Perl +Artistic License. + +EOT + exit(0); +} + +sub print_header { + print STDOUT <<'EOF'; +Test Component Iter ms KB In KB Out KB/s Result +========================================================================== +EOF +} + +sub print_output { + printf STDOUT "%-15.15s %5.0d %5.0d %7.0f %7.0f %9.2f %-15.15s\n", + $component, $iter, $ms, $kb_in, $kb_out, $kb_sec, $result; +} |