use LWP::Simple; use XML::DTDParser; my $dtdfile = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"; # or any other, like xhtml1-frameset.dtd my $dtd = get($dtdfile); $dtd =~ s/.*=== Imported Names =+-->//s; # avoid 'die' in XML::DTDParser $DTD = ParseDTD $dtd; my $elems = [ map {uc($_) } keys %$DTD ]; my %s; my $attrs = [ grep { s/-/_/g; ! $s{$_}++ } map { keys %{$DTD->{$_}->{'attributes'}} } keys %$DTD ]; define_vocabulary($elems,$attrs); #### # it's just Perl, so we can mix in other code for (2..5) { p { text "Plus paragraph number $_." } } #### sub render_via_xml_writer { my $doc = shift; my $writer = XML::Writer->new(@_); # extra args go to ->new() # my $render_fn; # $render_fn = sub { sub render_fn { my $frag = shift; my ($elem, $attrs, $children) = @$frag; $writer->startTag( $elem, map {@$_} @$attrs ); for (@$children) { # ref() ? $render_fn->($_) : $writer->characters($_); ref() ? render_fn($_) : $writer->characters($_); } $writer->endTag($elem); }; # $render_fn->($doc); render_fn($doc); $writer->end(); }