Skip Menu |

This queue is for tickets about the XML-Twig CPAN distribution.

Report information
The Basics
Id: 110924
Status: open
Priority: 0/
Queue: XML-Twig

People
Owner: Nobody in particular
Requestors: brianjamespugh [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in:
  • 3.48
  • 3.49



Subject: Support for !NOTATION elements
XML::Twig is currently lacking in support for manipulating !NOTATION elements found in the DTD/Doctype section. I'm submitting a patch that is just a cut/paste/update of the current !ENTITY support to handle !NOTATION. This patch is lacking tests and various parsing style updates, but works in basic cases. This patch was tested with 3.48, but I have applied to 3.49 and it went in clean.
Subject: XML-Twig-3.48-Notation.patch
diff -uNr XML-Twig-3.48/Twig.pm XML-Twig-3.48-Notation/Twig.pm --- XML-Twig-3.48/Twig.pm 2014-03-30 04:54:15.000000000 -0400 +++ XML-Twig-3.48-Notation/Twig.pm 2016-01-05 14:16:11.924926200 -0500 @@ -117,7 +117,7 @@ my %DEFAULT_URI2NS= map { $DEFAULT_NS{$_} => $_ } keys %DEFAULT_NS; # constants -my( $PCDATA, $CDATA, $PI, $COMMENT, $ENT, $ELT, $TEXT, $ASIS, $EMPTY, $BUFSIZE); +my( $PCDATA, $CDATA, $PI, $COMMENT, $ENT, $NOTATION, $ELT, $TEXT, $ASIS, $EMPTY, $BUFSIZE); # used when an HTML doc only has a PUBLIC declaration, to generate the SYSTEM one # this should really be done by HTML::TreeBuilder, but as of HTML::TreeBuilder 4.2 it isn't @@ -173,17 +173,20 @@ import XML::Twig::Elt; import XML::Twig::Entity; import XML::Twig::Entity_list; +import XML::Twig::Notation; +import XML::Twig::Notation_list; # used to store the gi's # should be set for each twig really, at least when there are several # the init ensures that special gi's are always the same # constants: element types -$PCDATA = '#PCDATA'; -$CDATA = '#CDATA'; -$PI = '#PI'; -$COMMENT = '#COMMENT'; -$ENT = '#ENT'; +$PCDATA = '#PCDATA'; +$CDATA = '#CDATA'; +$PI = '#PI'; +$COMMENT = '#COMMENT'; +$ENT = '#ENT'; +$NOTATION = '#NOTATION'; # element classes $ELT = '#ELT'; @@ -237,6 +240,7 @@ End => \&_twig_end, Char => \&_twig_char, Entity => \&_twig_entity, + Notation => \&_twig_notation, XMLDecl => \&_twig_xmldecl, Doctype => \&_twig_doctype, Element => \&_twig_element, @@ -731,7 +735,8 @@ # XML::Parser level $self->setHandlers( Init => \&_twig_init, Final => \&_twig_final); - $self->{twig_entity_list}= XML::Twig::Entity_list->new; + $self->{twig_entity_list} = XML::Twig::Entity_list->new; + $self->{twig_notation_list} = XML::Twig::Notation_list->new; $self->{twig_id}= $ID; $self->{twig_stored_spaces}=''; @@ -2829,6 +2834,19 @@ return; } +sub _twig_notation + { + # warn " in _twig_notation...\n"; + my( $p, $name, $base, $sysid, $pubid ) = @_; + my $t = $p->{twig}; + + my $notation = XML::Twig::Notation->new( $name, $base, $sysid, $pubid ); + my $notation_list = $t->notation_list(); + if( $notation_list ) { $notation_list->add( $notation ); } + + return; + } + sub _twig_extern_ent { # warn " in _twig_extern_ent...I (", $_[0]->original_string, ")\n"; # DEBUG handler @@ -3157,6 +3175,25 @@ return $t->entity_list->ent( $entity_name); } +# return the notation_list object +sub notation_list + { my $t= shift; + return $t->{twig_notation_list}; + } + +# return the list of notation names +sub notation_names + { my $t= shift; + return $t->notation_list->notation_names; + } + +# return the notation object +sub notation + { my $t= shift; + my $notation_name= shift; + return $t->notation_list->notation( $notation_name); + } + sub print_prolog { my $t= shift; @@ -3195,15 +3232,18 @@ { my $internal=$doctype->{internal}; # awful hack, but at least it works a little better that what was there before if( $internal) - { # remove entity declarations (they will be re-generated from the updated entity list) + { # remove entity and notation declarations (they will be re-generated from the updated lists) $internal=~ s{<! \s* ENTITY \s+ $REG_TAG_NAME \s+ ( ("[^"]*"|'[^']*') \s* | SYSTEM [^>]*) >\s*}{}xg; + $internal=~ s{<! \s* NOTATION .*? >\s*}{}xg; $internal=~ s{^\n}{}; } - $internal .= $t->entity_list->text ||'' if( $t->entity_list); + $internal .= $t->entity_list->text ||'' if( $t->entity_list); + $internal .= $t->notation_list->text ||'' if( $t->notation_list); + if( $internal) { $doctype_text .= "[\n$internal]>\n"; } } - elsif( !$t->{'twig_dtd'} && keys %{$t->entity_list}) - { $doctype_text .= "<!DOCTYPE " . $t->root->gi . " [\n" . $t->entity_list->text . "\n]>";;} + elsif( !$t->{'twig_dtd'} && ( keys %{$t->entity_list} || keys %{$t->notation_list} )) + { $doctype_text .= "<!DOCTYPE " . $t->root->gi . " [\n" . $t->entity_list->text . $t->notation_list->text . "\n]>";;} else { $doctype_text= $t->{twig_dtd}; $doctype_text .= $t->dtd_text; @@ -4837,6 +4877,161 @@ 1; ###################################################################### +package XML::Twig::Notation_list; +###################################################################### + +*isa= *UNIVERSAL::isa; + +sub new + { my $class = shift; + my $self={ notations => {}, updated => 0}; + + bless $self, $class; + return $self; + + } + +sub add_new_notation + { my $notation_list= shift; + my $notation= XML::Twig::Notation->new( @_); + $notation_list->add( $notation); + return $notation_list; + } + +sub _add_list + { my( $notation_list, $to_add)= @_; + my $notations_to_add= $to_add->{notations}; + return $notation_list unless( $notations_to_add && %$notations_to_add); + @{$notation_list->{notations}}{keys %$notations_to_add}= values %$notations_to_add; + $notation_list->{updated}=1; + return $notation_list; + } + +sub add + { my( $notation_list, $notation)= @_; + $notation_list->{notations}->{$notation->{name}}= $notation; + $notation_list->{updated}=1; + return $notation_list; + } + +sub notation + { my( $notation_list, $notation_name)= @_; + return $notation_list->{notations}->{$notation_name}; + } + +# can be called with an notationity or with an notationity name +sub delete + { my $notation_list= shift; + if( isa( ref $_[0], 'XML::Twig::Notation')) + { # the second arg is an notationity + my $notation= shift; + delete $notation_list->{notations}->{$notation->{name}}; + } + else + { # the second arg was not notationity, must be a string then + my $name= shift; + delete $notation_list->{notations}->{$name}; + } + $notation_list->{updated}=1; + return $notation_list; + } + +sub print + { my ($notation_list, $fh)= @_; + my $old_select= defined $fh ? select $fh : undef; + + foreach my $notation_name ( sort keys %{$notation_list->{notations}}) + { my $notation= $notation_list->{notations}->{$notation_name}; + # we have to test what the notationity is or un-defined notations can creep in + if( isa( $notation, 'XML::Twig::Notation')) { $notation->print(); } + } + select $old_select if( defined $old_select); + return $notation_list; + } + +sub text + { my ($notation_list)= @_; + return join "\n", map { $notation_list->{notations}->{$_}->text} sort keys %{$notation_list->{notations}}; + } + +# return the list of notationity names +sub notationity_names + { my $notation_list= shift; + return (sort keys %{$notation_list->{notations}}) ; + } + + +sub list + { my ($notation_list)= @_; + return map { $notation_list->{notations}->{$_} } sort keys %{$notation_list->{notations}}; + } + +1; + +###################################################################### +package XML::Twig::Notation; +###################################################################### + +#*isa= *UNIVERSAL::isa; + +sub new + { my( $class, $name, $base, $sysid, $pubid)= @_; + $class= ref( $class) || $class; + + my $self={}; + + $self->{name} = $name; + $self->{base} = $base if( defined $base ); + $self->{sysid} = $sysid if( defined $sysid); + $self->{pubid} = $pubid if( defined $pubid); + + bless $self, $class; + return $self; + } + + +sub name { return $_[0]->{name}; } +sub base { return $_[0]->{base}; } +sub sysid { return $_[0]->{sysid}; } +sub pubid { return $_[0]->{pubid}; } + + +sub print + { my ($notation, $fh)= @_; + my $text= $notation->text; + if( $fh) { print $fh $text . "\n"; } + else { print $text . "\n"; } + } + +sub sprint + { my ($notation)= @_; + return $notation->text; + } + +sub text + { my ($notation)= @_; + #warn "text called: '", $notation->_dump, "'\n"; + return '' if( !$notation->{name}); + my @tokens; + push @tokens, '<!NOTATION'; + push @tokens, $notation->{name}; + push @tokens, ( 'PUBLIC', _quoted_val( $notation->{pubid} ) ) if $notation->{pubid}; + push @tokens, ( 'SYSTEM', _quoted_val( $notation->{sysid} ) ) if $notation->{sysid}; + + return join( ' ', @tokens) . '>'; + } + +sub _quoted_val + { my $q= $_[0]=~ m{"} ? q{'} : q{"}; + return qq{$q$_[0]$q}; + } + +sub _dump + { my( $notation)= @_; return join( " - ", map { "$_ => '$notation->{$_}'" } grep { defined $notation->{$_} } sort keys %$notation); } + +1; + +###################################################################### package XML::Twig::Elt; ###################################################################### @@ -11189,6 +11384,18 @@ Return the entity +=item notation_list + +Return the notation list of a twig + +=item notation_names + +Return the list of all defined notations + +=item notation ($notation_name) + +Return the notation + =item change_gi ($old_gi, $new_gi) Performs a (very fast) global change. All elements C<$old_gi> are now @@ -13621,6 +13828,72 @@ =back +=head2 XML::Twig::Notation_list + +=over 4 + +=item new + +Create an notation list. + +=item add ($notation) + +Add an notation to an notation list. + +=item add_new_notation ($name, $base, $sysid, $pubid) + +Create a new notation and add it to the notation list + +=item delete ($notation or $tag). + +Delete an notation (defined by its name or by the Notation object) +from the list. + +=item print ($optional_filehandle) + +Print the notation list. + +=item list + +Return the list as an array + +=back + + +=head2 XML::Twig::Notation + +=over 4 + +=item new ($name, $base, $sysid, $pubid) + +Same argumnotations as the Notation handler for XML::Parser. + +=item print ($optional_filehandle) + +Print an notation declaration. + +=item name + +Return the name of the notation + +=item base + +Return the base to be used for resolving a relative URI + +=item sysid + +Return the system id for the notation + +=item pubid + +Return the public id for the notation + + +=item text + +Return the notation declaration text. + +=back =head1 EXAMPLES
Subject: Re: [rt.cpan.org #110924] Support for !NOTATION elements
Date: Tue, 5 Jan 2016 15:01:56 -0500
To: bug-XML-Twig [...] rt.cpan.org
From: Michel Rodriguez <xmltwig [...] gmail.com>
Thanks, I'll try to have a look at it this week. I think the "notationity_names" method would be better call "notation_names" though. -- mirod On Tue, Jan 5, 2016 at 2:41 PM, brianjamespugh@gmail.com via RT < bug-XML-Twig@rt.cpan.org> wrote: Show quoted text
> Tue Jan 05 14:41:06 2016: Request 110924 was acted upon. > Transaction: Ticket created by brianjamespugh@gmail.com > Queue: XML-Twig > Subject: Support for !NOTATION elements > Broken in: (no value) > Severity: Normal > Owner: Nobody > Requestors: brianjamespugh@gmail.com > Status: new > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=110924 > > > > XML::Twig is currently lacking in support for manipulating !NOTATION > elements found in the DTD/Doctype section. > > I'm submitting a patch that is just a cut/paste/update of the current > !ENTITY support to handle !NOTATION. This patch is lacking tests and > various parsing style updates, but works in basic cases. > > This patch was tested with 3.48, but I have applied to 3.49 and it went in > clean. >