6 package XML::TemplateSAX::Handler;
7 use base qw(XML::SAX::Base);
14 obj => $options{'Content'},
16 Handler => $options{'Handler'}
23 my ($self, $data) = @_;
24 my $obj = $self->{'obj'};
27 my $id = $data->{'Attributes'}->{'{http://template.sesse.net/}id'};
28 $id = $id->{'Value'} if (defined($id));
30 # within a replacement; just ignore everything
31 return if (!defined($obj));
33 # within a cloning; slurp it up
34 if (ref($obj) eq 'XML::TemplateSAX::Buffer') {
35 $obj->start_element($data);
39 # substitution: see if this element matches anything. if so,
40 # descend down into the tree.
41 if (ref($obj) eq 'HASH') {
43 for my $key (keys %$obj) {
44 if ($key =~ /^#(.*)$/) {
45 if (defined($id) && $id eq $1) {
46 $match = $obj->{$key};
50 if ($data->{'LocalName'} eq $key) {
51 $match = $obj->{$key};
57 if (defined($match)) {
58 $self->SUPER::start_element($data);
60 push @{$self->{'stack'}}, [ $data->{'Name'}, $obj ];
63 # This is sort of ugly. We special-case replacement by outputting
64 # the string immediately, and then just ignoring the rest of the
65 # events until we get to the right end tag. It's not 100% technically
66 # correct for the case where you replace an entire document by a
67 # string, but that's nonsensical anyway.
70 $self->SUPER::characters({ Data => $match });
71 $self->{'obj'} = undef;
76 # Sort of the same, for cloning. Cloning works by gobbling up all the all the
77 # input until the end element, and put it into a buffer. when we get to the end
78 # element, spew it all out again as many times as we need, onto ourselves so we
79 # get filtering etc. right.
81 # We let the buffer object keep the actual array, so we can fetch it out later.
83 if (ref($match) eq 'ARRAY') {
84 $self->{'obj'} = XML::TemplateSAX::Buffer->new($match);
88 $self->{'obj'} = $match;
94 $self->SUPER::start_element($data);
98 my ($self, $data) = @_;
100 return if (!defined($self->{'obj'}));
102 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
103 $self->{'obj'}->characters($data);
107 $self->SUPER::characters($data);
111 my ($self, $data) = @_;
113 return if (!defined($self->{'obj'}));
115 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
116 $self->{'obj'}->comment($data);
120 $self->SUPER::comment($data);
123 sub processing_instruction {
124 my ($self, $data) = @_;
126 return if (!defined($self->{'obj'}));
128 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
129 $self->{'obj'}->processing_instruction($data);
133 $self->SUPER::processing_instruction($data);
137 my ($self, $data) = @_;
139 my $stack = $self->{'stack'};
140 if (scalar @$stack > 0) {
141 my $top = $stack->[scalar @$stack - 1];
143 if ($data->{'Name'} eq $top->[0]) {
144 my $obj = $self->{'obj'};
146 # did we just finish a clone operation?
147 if (ref($obj) eq 'XML::TemplateSAX::Buffer') {
148 for my $instance (@{$obj->{'ptr'}}) {
149 $self->{'obj'} = $instance;
154 $self->SUPER::end_element($data);
155 $self->{'obj'} = $top->[1];
161 return if (!defined($self->{'obj'}));
163 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
164 $self->{'obj'}->end_element($data);
168 $self->SUPER::end_element($data);