]> git.sesse.net Git - xml-template/commitdiff
Make perl-sax/simple almost work.
authorsgunderson@bigfoot.com <>
Thu, 1 Mar 2007 01:58:49 +0000 (02:58 +0100)
committersgunderson@bigfoot.com <>
Thu, 1 Mar 2007 01:58:49 +0000 (02:58 +0100)
perl-sax/XML/TemplateSAX.pm

index fce9ae21a155125cee64b894894c1e26ea80f1a0..d2eb7a5bc1ead16e97b04f909f5a97b34826909c 100644 (file)
@@ -17,6 +17,7 @@
 
 use XML::SAX::Expat;
 use XML::SAX::Writer;
+use Data::Dumper;
 
 package XML::TemplateSAX::Handler;
 use base qw(XML::SAX::Base);
@@ -27,6 +28,7 @@ sub new {
 
        my $self = {
                obj => $options{'Content'},
+               stack => [],
                Handler => $options{'Handler'}
        };
        bless($self, $class);
@@ -35,10 +37,80 @@ sub new {
 
 sub start_element {
        my ($self, $data) = @_;
+       my $obj = $self->{'obj'};
 
+       # within a replacement; just ignore everything  
+       return if (!defined($obj));
+
+       # substitution: see if this element matches anything. if so,
+       # descend down into the tree.
+       if (ref($obj) eq 'HASH') {
+               my $match = undef;
+               for my $key (keys %$obj) {
+                       if ($key =~ /^#(.*)$/) {
+                               if ($data->{'NamespaceURI'} eq 'http://template.sesse.net/' && $data->{'LocalName'} eq $1) {
+                                       $match = $obj->{$key};
+                                       last;
+                               }
+                       } else {
+                               if ($data->{'LocalName'} eq $key) {
+                                       $match = $obj->{$key};
+                                       last;
+                               }
+                       }
+               }
+
+               if (defined($match)) {
+                       $self->SUPER::start_element($data);
+
+                       push @{$self->{'stack'}}, [ $data->{'Name'}, $obj ];
+                       
+                       #
+                       # This is sort of ugly. We special-case replacement by outputting
+                       # the string immediately, and then just ignoring the rest of the
+                       # events until we get to the right end tag. It's not 100% technically
+                       # correct for the case where you replace an entire document by a
+                       # string, but that's nonsensical anyway.
+                       #
+                       if (!ref($match)) {
+                               $self->SUPER::characters({ Data => $match });
+                               $match = undef;
+                       }
+
+                       $self->{'obj'} = $match;
+                       return;
+               }
+       }
+       
        $self->SUPER::start_element($data);
 }
 
+sub characters {
+       my ($self, $data) = @_;
+       return if (!defined($self->{'obj'}));
+       $self->SUPER::characters($data);
+}
+
+sub end_element {
+       my ($self, $data) = @_;
+
+       my $stack = $self->{'stack'};
+       if (scalar @$stack > 0) {
+               my $top = $stack->[$#stack];
+               
+               if ($data->{'Name'} eq $top->[0]) {
+                       $self->SUPER::end_element($data);
+                       $self->{'obj'} = $top->[1];
+                       pop @$stack;
+                       return;
+               }
+       }
+       
+       return if (!defined($self->{'obj'}));
+
+       $self->SUPER::end_element($data);
+}
+
 package XML::TemplateSAX;
 
 sub process_file {