#
# Copyright (C) 1998, 1999 Ken MacLeod
# XML::Grove::AsCanonXML is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# $Id: AsCanonXML.pm,v 1.6 1999/08/17 18:36:20 kmacleod Exp $
#
use strict;
package XML::Grove::AsCanonXML;
use vars qw{%char_entities};
use Data::Grove::Visitor;
%char_entities = (
"\x09" => ' ',
"\x0a" => '
',
"\x0d" => '
',
'&' => '&',
'<' => '<',
'>' => '>',
'"' => '"',
);
sub new {
my $class = shift;
my $self = ($#_ == 0) ? { %{ (shift) } } : { @_ };
return bless $self, $class;
}
sub as_canon_xml {
my $self = shift; my $object = shift; my $fh = shift;
if (defined $fh) {
return ();
} else {
return join('', $object->accept($self, $fh));
}
}
sub visit_document {
my $self = shift; my $document = shift;
return $document->children_accept($self, @_);
}
sub visit_element {
my $self = shift; my $element = shift; my $fh = shift;
my @return;
push @return, $self->_print($fh, '<' . $element->{Name});
my $key;
my $attrs = $element->{Attributes};
foreach $key (sort keys %$attrs) {
push @return, $self->_print($fh,
" $key=\"" . $self->_escape($attrs->{$key}) . '"');
}
push @return, $self->_print($fh, '>');
push @return, $element->children_accept($self, $fh, @_);
push @return, $self->_print($fh, '' . $element->{Name} . '>');
return @return;
}
sub visit_entity {
# entities don't occur in text
return ();
}
sub visit_pi {
my $self = shift; my $pi = shift; my $fh = shift;
return $self->_print($fh, '' . $pi->{Target} . ' ' . $pi->{Data} . '?>');
}
sub visit_comment {
my $self = shift; my $comment = shift; my $fh = shift;
if ($self->{Comments}) {
return $self->_print($fh, '');
} else {
return ();
}
}
sub visit_characters {
my $self = shift; my $characters = shift; my $fh = shift;
return ($self->_print($fh, $self->_escape($characters->{Data})));
}
sub _print {
my $self = shift; my $fh = shift; my $string = shift;
if (defined $fh) {
$fh->print($string);
return ();
} else {
return ($string);
}
}
sub _escape {
my $self = shift; my $string = shift;
$string =~ s/([\x09\x0a\x0d&<>"])/$char_entities{$1}/ge;
return $string;
}
package XML::Grove;
sub as_canon_xml {
my $xml_object = shift;
return XML::Grove::AsCanonXML->new(@_)->as_canon_xml($xml_object);
}
1;
__END__
=head1 NAME
XML::Grove::AsCanonXML - output XML objects in canonical XML
=head1 SYNOPSIS
use XML::Grove::AsCanonXML;
# Using as_canon_xml method on XML::Grove objects:
$string = $xml_object->as_canon_xml( OPTIONS );
# Using an XML::Grove::AsCanonXML instance:
$writer = XML::Grove::AsCanonXML->new( OPTIONS );
$string = $writer->as_canon_xml($xml_object);
$writer->as_canon_xml($xml_object, $file_handle);
=head1 DESCRIPTION
C