package Data::DumpXML; use strict; use vars qw(@EXPORT_OK $VERSION); require Exporter; *import = \&Exporter::import; @EXPORT_OK=qw(dump_xml dump); $VERSION = "1.01"; # $Date: 2000/09/19 09:58:26 $ use vars qw($INDENT); # configuration $INDENT = " " unless defined $INDENT; use overload (); use vars qw(%seen %ref $count); #use HTTP::Date qw(time2iso); sub dump_xml { local %seen; local %ref; local $count = 0; my $out = qq(\n); $out .= qq(\n); #$out .= qq(); $out .= ""; $out .= format_list(map _dump($_), @_); $out .= "\n"; $count = 0; $out =~ s/\01/$ref{++$count} ? qq( id="r$ref{$count}") : ""/ge; print STDERR $out unless defined wantarray; $out; } *dump = \&dump_xml; sub _dump { my $rval = \$_[0]; shift; my $deref = shift; $rval = $$rval if $deref; my($class, $type, $id); if (overload::StrVal($rval) =~ /^(?:([^=]+)=)?([A-Z]+)\(0x([^\)]+)\)$/) { $class = $1; $type = $2; $id = $3; } else { return qq(); } if (my $seq = $seen{$id}) { my $ref_no = $ref{$seq} || ($ref{$seq} = keys(%ref) + 1); return qq(); } $seen{$id} = ++$count; $class = $class ? " class=" . quote($class) : ""; $id = "\1"; # magic that is removed or expanded to ' id="r1"' in the end. if ($type eq "SCALAR" || $type eq "REF") { return "" unless defined $$rval; return "" . format_list(_dump($$rval, 1)) . "" if ref $$rval; my($str, $enc) = esc($$rval); return "$str"; } elsif ($type eq "ARRAY") { return "" unless @$rval; return "" . format_list(map _dump($_), @$rval) . ""; } elsif ($type eq "HASH") { my $out = "\n"; for my $key (sort keys %$rval) { my $val = \$rval->{$key}; $val = _dump($$val); if ($INDENT) { $val =~ s/^/$INDENT$INDENT/gm; $out .= $INDENT; } my($str, $enc) = esc($key); $out .= "$str\n$val\n"; } $out .= ""; return $out; } elsif ($type eq "GLOB") { return ""; } elsif ($type eq "CODE") { return ""; } else { #warn "Can't handle $type data"; return ""; } die "Assert"; } sub format_list { my @elem = @_; if ($INDENT) { for (@elem) { s/^/$INDENT/gm; } } return "\n" . join("\n", @elem); } # put a string value in double quotes sub quote { local($_) = shift; s/&/&/g; s/\"/"/g; s/ ]> As an example of the XML documents producted; the following call: $a = bless [1,2], "Foo"; $a->[2] = \$a; $b = $a; dump_xml($a, $b); will produce: 1 2 If dump_xml() is called in void context, then the dump will be printed on STDERR instead of being returned. For compatibility with C there is also an alias for dump_xml() simply called dump(). You can set the variable $Data::DumpXML::INDENT to control indenting before calling dump_xml(). To suppress indenting set it as "". The C is a class that can restore datastructures dumped by dump_xml(). =head1 BUGS Class names with 8-bit characters will be dumped as Latin-1, but converted to UTF-8 when restored by the Data::DumpXML::Parser. The content of globs and subroutines are not dumped. They are restored as the strings; "** glob **" and "** code **". LVALUE and IO objects are not dumped at all. They will simply disappear from the restored data structure. =head1 SEE ALSO L, L, L, L =head1 AUTHORS The C module is written by Gisle Aas , based on C. The C module was written by Gisle Aas, based on C by Gurusamy Sarathy . Copyright 1998-2000 Gisle Aas. Copyright 1996-1998 Gurusamy Sarathy. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut