こんな感じかなぁ。

#! /usr/bin/perl
use strict;
use warnings;

my $file = shift @ARGV;

use XML::SAX::ParserFactory;
my $handler = new MyHandler;
my $parser = XML::SAX::ParserFactory->parser( Handler => $handler );
$parser->parse_uri( $file );


package MyHandler;
sub new {
	my $invocant = shift;
	my $class = ref($invocant) || $invocant;
	my $self = { @_ };
	return bless( $self, $class );
}

my $buf;
my @indent;
sub start_element {
	my $self = shift;
	my $element = shift;
	my $str = "<" . $element->{Name};
	for( keys %{ $element->{Attributes} } ){
		$str .= " ";
		$str .= $element->{Attributes}->{$_}->{Name} . '="';
		$str .= $element->{Attributes}->{$_}->{Value} . '"';
	}
	$str .= ">";

	print "\n" if @indent and not $buf;
	print join( "", @indent ), $str;
	push @indent, "\t";
}

sub end_element {
	my $self = shift;
	my $element = shift;

	pop @indent;
	if( $buf ){
		print $buf;
		$buf = '';
	}else{
		print "\n", join( "", @indent );
	}

	print "</", $element->{Name}, ">";
}

sub characters {
	my $self = shift;
	my $characters = shift;

	my $str = $characters->{Data};
	$str =~ s/^\s+$//;
	$str =~ s/&/&amp;/g;
	$str =~ s/</&lt;/g;
	$str =~ s/>/&gt;/g;
	$buf .= $str;
}

*1

*1:おわっつ!! &と<をそのまま出してた…orz。