#! /usr/bin/perl

#
# SAX version of XML::Template. Advantages over DOM: Doesn't have to load
# the entire thing into memory, and you can chain filters. Disadvantages:
# Slightly kludgier interface, and you won't get a DOM tree out.
#
# Differences from the DOM version:
# 
# - There is no process(). Instead, it works as a SAX filter, so you put it
#   in the stream, usually between a parser and a writer (ie.
#   parser -> XML::TemplateSAX::Handler -> writer). process_file works as
#   before, but it returns a _string_, not a DOM tree.
# - You can no longer insert a DOM tree, naturally. Instead, you can set up
#   an XML::TemplateSAX::Buffer, let it gobble up your data, and send it
#   in the way you'd insert a DOM tree. process_file_to_buffer does this
#   transparently for you, returning a buffer you can give in.
#

use strict;
use warnings;
use XML::SAX::Expat;
use XML::SAX::Writer;
use XML::TemplateSAX::Buffer;
use XML::TemplateSAX::Cleaner;
use XML::TemplateSAX::Handler;

package XML::TemplateSAX;

sub process_file {
	my ($filename, $obj, $clean) = @_;
	$clean = 1 unless (defined($clean));

	my ($writer, $cleaner, $filter, $parser);
	my $str = '';

	$writer = XML::SAX::Writer->new(Output => \$str);

	if ($clean) {
		$cleaner = XML::TemplateSAX::Cleaner->new(Handler => $writer, Content => $obj);
		$filter = XML::TemplateSAX::Handler->new(Handler => $cleaner, Content => $obj);
	} else {
		$filter = XML::TemplateSAX::Handler->new(Handler => $writer, Content => $obj);
	}

	# FIXME: hardcoding expat = not good?
	$parser = XML::SAX::Expat->new(Handler => $filter);
	$parser->parse_file($filename);

	return $str;
}

sub process_file_to_buffer {
	my ($filename, $obj, $clean) = @_;
	$clean = 1 unless (defined($clean));

	my ($buffer, $cleaner, $filter, $parser);

	$buffer = XML::TemplateSAX::Buffer->new;

	if ($clean) {
		$cleaner = XML::TemplateSAX::Cleaner->new(Handler => $buffer, Content => $obj);
		$filter = XML::TemplateSAX::Handler->new(Handler => $cleaner, Content => $obj);
	} else {
		$filter = XML::TemplateSAX::Handler->new(Handler => $buffer, Content => $obj);
	}

	# FIXME: hardcoding expat = not good?
	$parser = XML::SAX::Expat->new(Handler => $filter);
	$parser->parse_file($filename);

	return $buffer;
}

sub alternate {
	my ($tag, $array, @elems) = @_;

	my $i = 0;
	my $num = scalar @elems;

	for my $ref (@$array) {
		if (defined($ref)) {
			$ref->{$tag} = $elems[$i++ % $num];
		}
	}

	return $array;
}

1;
