XML::RSS::Parser::Util - utility methods for working with
package XML::RSS::Parser::Util;
use strict;
use Exporter;
@XML::RSS::Parser::Util::ISA = qw( Exporter );
use vars qw( @EXPORT_OK );
@EXPORT_OK = qw( as_xml encode_xml );
use XML::Elemental::Util qw( process_name );
# This has its limitations, but should suffice
sub as_xml {
my($node,$dec,$encoding) = @_;
$encoding ||= 'utf-8';
my $xml = $dec ? qq(<?xml version="1.0" encoding="$encoding"?>\n) : '';
my $dumper;
$dumper = sub {
my $node = shift;
return encode_xml($node->data)
if (ref($node) eq 'XML::RSS::Parser::Characters');
# it must be an element then.
my ($name, $ns) = process_name($node->name);
my $prefix = $XML::RSS::Parser::xpath_ns{$ns}; # missing namespace???
$name = "$prefix:$name" if ($prefix && $prefix ne '#default');
my $xml = "<$name";
my $a = $node->attributes;
my $children = $node->contents;
foreach (keys %$a) {
my ($aname, $ans) = process_name($_);
if ($ans ne $ns) {
my $aprefix =
$XML::RSS::Parser::xpath_ns{$ans}; # missing namespace???
$aname = "$aprefix:$aname"
if ($aprefix && $aprefix ne '#default');
}
$xml .= " $aname=\"" . encode_xml($a->{$_}, 1) . "\"";
}
if ($children) {
$xml .= '>';
map { $xml .= $dumper->($_) } @$children;
$xml .= "</$name>";
} else {
$xml .= '/>';
}
$xml;
};
$xml .= $dumper->($node);
$xml;
}
my %Map = (
'&' => '&',
'"' => '"',
'<' => '<',
'>' => '>',
'\'' => '''
);
my $RE = join '|', keys %Map;
sub encode_xml {
my ($str, $nocdata) = @_;
return unless defined($str);
if (
!$nocdata
&& $str =~ m/
<[^>]+> ## HTML markup
| ## or
&(?:(?!(\#([0-9]+)|\#x([0-9a-fA-F]+))).*?);
## something that looks like an HTML entity.
/x
) {
## If ]]> exists in the string, encode the > to >.
$str =~ s/]]>/]]>/g;
$str = '<![CDATA[' . $str . ']]>';
} else {
$str =~ s!($RE)!$Map{$1}!g;
}
$str;
}
1;
__END__