<!--
=head1 NAME

xsl.wmk - apply an XSL stylesheet to XML data, using Sablotron

=head1 LOADING

  < use plugin="xsl" />

=head1 HTML / XML TAGS

  < xsl xmlname="name_of_content.xml"
  	xslname="name_of_xslt.xsl"
	[ xslparam="value" ... ] />

=head1 DESCRIPTION

This WebMake Perl library provides the C<xsl> WebMake tag, allowing you to
apply the named XSL stylesheet to the named XML data, rendering the output in
place of the tag.

The named items should be defined as WebMake content or template items of
format C<text/xml>, in order to use dependency information correctly.

XSL parameters may be passed in using attributes.

Note that the Perl module C<XML::Sablotron> is required.

=head1 REQUIRED MODULES

C<XML::Sablotron>

=head1 SEE ALSO

C<XML::Sablotron>
B<http://www.gingerall.com/>
B<http://www.w3.org/TR/1999/REC-xslt-19991116>
B<http://www.w3.org/TR/1999/REC-xpath-19991116>
B<http://www.w3.org/TR/1998/REC-xml-19980210>

=head1 AUTHOR

Justin Mason <jm@jmason.org>

=cut

-->

<{perl

  use XML::Sablotron;

  $self->define_empty_preformat_tag ("xsl",
  	\&HTML::WebMake::PerlLib::XSLTag::handle_xsl_tag,
	qw(xmlname xslname));

  # TODO: define another tag for embedded XSL? e.g.
  #
  # <xslhere xmlname="foo"> ...xsl data... </xslhere>
  #
  # hmm. see if it turns out to be handy. (I would imagine
  # keeping XSLs out of content would be cleaner.)

  package HTML::WebMake::PerlLib::XSLTag;

  sub handle_xsl_tag {
    my ($tagname, $attrs, $text, $self) = @_;

    my $template = $attrs->{xsl};
    my $data = $attrs->{xml};

    $template = HTML::WebMake::PerlLib::XSLTag::get_content_xml
    			($self, $attrs->{xslname});
    $data = HTML::WebMake::PerlLib::XSLTag::get_content_xml
    			($self, $attrs->{xmlname});

    if (!defined $template || !defined $data) {
      warn "<xsl> tag requires valid 'xmlname' and 'xslname' attributes.\n";
      return '';
    }

    my $sab = XML::Sablotron->new();

    my $situa = XML::Sablotron::Situation->new();
    $sab->addArg ($situa, "xsl", $template);
    $sab->addArg ($situa, "xml", $data);

    foreach my $attr (%{$attrs}) {
      next if (!defined $attr || !defined $attrs->{$attr});
      next if ($attr =~ /^(?:xslname|xmlname|xsl|xml)$/i);
      $sab->addParam ($situa, $attr, $attrs->{$attr});
    }

    $sab->process ($situa, "arg:/xsl", "arg:/xml", "arg:/out");

    my $ret = $sab->getResultArg ("out");
    if (!defined $ret) {
      warn "<xsl>: an error occurred processing ".
      		"\"$attrs->{xmlname}\" with \"$attrs->{xslname}\"\n";
      return '';

    } else {
      return $ret;
    }
  }

  sub get_content_xml {
    my ($self, $name) = @_;

    return undef unless (defined $name);

    my $main = $self->get_webmake_main_object();
    my $obj = $self->get_content_object ($name);

    if (!defined $obj) {
      warn "<xsl> tag: no such template item: \$\{$name\}\n";
      return undef;
    }

    $main->add_content_dependency ($obj);
    return $obj->get_text_as('text/xml');
  }

  '';

}>
