7 package XML::TemplateSAX::Handler;
8 use base qw(XML::SAX::Base);
15 obj => $options{'Content'},
17 Handler => $options{'Handler'}
24 my ($self, $data) = @_;
25 my $obj = $self->{'obj'};
28 my $id = $data->{'Attributes'}->{'{http://template.sesse.net/}id'};
29 $id = $id->{'Value'} if (defined($id));
31 # within a replacement; just ignore everything
32 return if (!defined($obj));
34 # within a cloning; slurp it up
35 if (ref($obj) eq 'XML::TemplateSAX::Buffer') {
36 $obj->start_element($data);
40 # substitution: see if this element matches anything. if so,
41 # descend down into the tree.
42 if (ref($obj) eq 'HASH') {
44 for my $key (keys %$obj) {
45 if ($key =~ /^#(.*)$/) {
46 if (defined($id) && $id eq $1) {
47 $match = $obj->{$key};
51 if ($data->{'LocalName'} eq $key) {
52 $match = $obj->{$key};
58 if (defined($match)) {
59 $self->SUPER::start_element($data);
61 # FIXME: we should match on something better than the name. But what?
62 push @{$self->{'stack'}}, [ $data->{'Name'}, $obj ];
65 # This is sort of ugly. We special-case replacement by outputting
66 # the string immediately, and then just ignoring the rest of the
67 # events until we get to the right end tag. It's not 100% technically
68 # correct for the case where you replace an entire document by a
69 # string, but that's nonsensical anyway.
72 $self->SUPER::characters({ Data => $match });
73 $self->{'obj'} = undef;
78 # Sort of the same, for cloning. Cloning works by gobbling up all the all the
79 # input until the end element, and put it into a buffer. when we get to the end
80 # element, spew it all out again as many times as we need, onto ourselves so we
81 # get filtering etc. right.
83 # We let the buffer object keep the actual array, so we can fetch it out later.
85 if (ref($match) eq 'ARRAY') {
86 $self->{'obj'} = XML::TemplateSAX::Buffer->new($match);
90 $self->{'obj'} = $match;
96 $self->SUPER::start_element($data);
100 my ($self, $data) = @_;
102 return if (!defined($self->{'obj'}));
104 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
105 $self->{'obj'}->characters($data);
109 $self->SUPER::characters($data);
113 my ($self, $data) = @_;
115 return if (!defined($self->{'obj'}));
117 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
118 $self->{'obj'}->comment($data);
122 $self->SUPER::comment($data);
125 sub processing_instruction {
126 my ($self, $data) = @_;
128 return if (!defined($self->{'obj'}));
130 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
131 $self->{'obj'}->processing_instruction($data);
135 $self->SUPER::processing_instruction($data);
139 my ($self, $data) = @_;
141 my $stack = $self->{'stack'};
142 if (scalar @$stack > 0) {
143 my $top = $stack->[scalar @$stack - 1];
145 if ($data->{'Name'} eq $top->[0]) {
146 my $obj = $self->{'obj'};
148 # did we just finish a clone operation?
149 if (ref($obj) eq 'XML::TemplateSAX::Buffer') {
150 for my $instance (@{$obj->{'ptr'}}) {
151 $self->{'obj'} = $instance;
156 $self->SUPER::end_element($data);
157 $self->{'obj'} = $top->[1];
163 return if (!defined($self->{'obj'}));
165 if (ref($self->{'obj'}) eq 'XML::TemplateSAX::Buffer') {
166 $self->{'obj'}->end_element($data);
170 $self->SUPER::end_element($data);