This little CGI script uses XML::LibXML and
XML::LibXSLT to transform a node (fetched in
XML display mode
via LWP::Simple) from XML to HTML. This script is
not necessarily meant to replace the
print display mode,
but instead as an example of how to use XSLT with Perl to
transform XML to HTML.
The HTML::Entities module is used in the final step
to decode the entities in the node content. More work could
be done here like linking PM shortcuts
([id://], [cpan://], etc.), but
since we already have a functioning print mode for nodes,
why bother? :) This is simply here as a reference for
further exploration. (it doesn't even work well on this type
of node - Code Catecombs).
The XSL stylesheet
is included in the DATA section, feel free to cut
and paste it into it's own file.
UPDATE: added a default node per PodMaster's request.
#!/usr/bin/perl -T
use strict;
use warnings;
use CGI qw(:standard);
use LWP::Simple qw(get);
use HTML::Entities;
use XML::LibXML;
use XML::LibXSLT;
print header, start_html,
start_form,
textfield('node_id'), submit('ID'),
end_form, end_html,
;
my $id = param('node_id');
print hr, node2html($id);
sub node2html {
my $id = shift || 181206;
return qq(bad id "$id"\n) unless $id =~ /^\d+$/;
my $xml = get "http://perlmonks.org/index.pl?node_id=$id&displayty
+pe=xml";
my $xslt = do {local $/; <DATA>};
my $xml_parser = XML::LibXML->new();
my $xslt_parser = XML::LibXSLT->new();
my $doc = $xml_parser->parse_string($xml);
my $style = $xml_parser->parse_string($xslt);
my $stylesheet = $xslt_parser->parse_stylesheet($style);
my $results = $stylesheet->transform($doc);
return decode_entities($stylesheet->output_string($results));
}
__DATA__
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node">
<xsl:value-of select="./@title"/>
(<xsl:value-of select="./@id"/>)<br/>
by <xsl:value-of select="./author"/>
<hr/>
<blockquote>
<xsl:value-of select="./data/field"/>
</blockquote>
</xsl:template>
</xsl:stylesheet>
one little thing: you might consider inverting the logic in your pattern match. i think it helps readability and maintainability a bit.
## turn (unless id contains one or more digits only)
return qq(bad id "$id"\n) unless $id =~ /^\d+$/;
## into (if id contains non-digits)
return qq(bad id "$id"\n) if $id =~ /\D/;