package MT::Plugin::LibXSLT; # mt-xslt.pl - A Plugin for XSL Transformation via XML::LibXSLT # Author: klm # License: same as Perl use strict; use MT; use MT::Template::Context; our $VERSION = 0.1; our ($Parser, $Processor, %Cache); eval { require MT::Plugin }; MT->add_plugin(MT::Plugin->new({ name => __PACKAGE__ . " v$VERSION", description => "A Plugin for XSL Transformation via XML::LibXSLT", })) unless $@; MT::Template::Context->add_container_tag(Transform => \&Transform); sub Transform { my ($ctx, $args, $cond) = @_; init(); my $builder = $ctx->stash('builder'); my $tokens = $ctx->stash('tokens'); my $dir = $ctx->stash('blog')->site_path; my $text = $builder->build($ctx, $tokens); $text =~ s/^\s+//s; $text =~ s/\s+$//s; my $xml = $Parser->parse_string($text); my @cmds = map { m[^/] ? $_ : "$dir/$_" } map { $args->{$_} } sort { $a cmp $b } grep { /^_\d+$/ } keys %$args; my $xsl; foreach my $cmd (@cmds) { my @arg; push @arg, $1 while $cmd =~ /(\'[^\']+\'|\S+)/g; my $file = shift @arg; $xsl = get_stylesheet($file); $xml = $xsl->transform($xml, @arg); } return $xsl->output_string($xml); } sub init { require XML::LibXML; require XML::LibXSLT; $Parser ||= XML::LibXML->new or die; $Processor ||= XML::LibXSLT->new or die; } sub get_stylesheet { my $file = shift; my $mtime = (stat $file)[9]; $Cache{$file} and $Cache{$file}->[0] == $mtime and return $Cache{$file}->[1]; # hit my $style_doc = $Parser->parse_file($file) or die "XML parse error: $file"; my $stylesheet = $Processor->parse_stylesheet($style_doc) or die "XSL syntax error: $file"; $Cache{$file} = [ $mtime, $stylesheet ]; return $stylesheet; } 1;