Revision: 20 Author: matt Date: 2006-07-31 21:07:03 +0000 (Mon, 31 Jul 2006)
Log Message: ----------- Support for TAL (aka Petal) Modified Paths: -------------- trunk/etc/axkit.conf trunk/lib/AxKit2/Processor.pm Added Paths: ----------- trunk/demo/tal/ trunk/demo/tal/index.xml trunk/demo/tal/tal.html trunk/demo/xsp/ trunk/demo/xsp/test.xsp trunk/lib/AxKit2/Transformer/TAL.pm trunk/plugins/demo/ trunk/plugins/demo/serve_tal Removed Paths: ------------- trunk/demo/test.xsp Added: trunk/demo/tal/index.xml =================================================================== --- trunk/demo/tal/index.xml 2006-07-29 02:34:31 UTC (rev 19) +++ trunk/demo/tal/index.xml 2006-07-31 21:07:03 UTC (rev 20) @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<demo> + <title>This is the title</title> + <users> + <user> + <first>Larry</first> + <last>Wall</last> + </user> + <user> + <first>Audrey</first> + <last>Tang</last> + </user> + <user> + <first>chromatic</first> + </user> + <user> + <first>Matt</first> + <last>Sergeant</last> + </user> + </users> +</demo> \ No newline at end of file Added: trunk/demo/tal/tal.html =================================================================== --- trunk/demo/tal/tal.html 2006-07-29 02:34:31 UTC (rev 19) +++ trunk/demo/tal/tal.html 2006-07-31 21:07:03 UTC (rev 20) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<html + xmlns:tal="http://xml.zope.org/namespaces/tal"> + <head> + <title tal:content="/demo/title">TITLE</title> + </head> + <body> + <h1>Petal Demo</h1> + <ul> + <li tal:repeat="u /demo/users/user"> + <span tal:replace="$u/last">last</span>, <span tal:replace="$u/first">first</span> + </li> + </ul> + </body> +</html> \ No newline at end of file Deleted: trunk/demo/test.xsp =================================================================== --- trunk/demo/test.xsp 2006-07-29 02:34:31 UTC (rev 19) +++ trunk/demo/test.xsp 2006-07-31 21:07:03 UTC (rev 20) @@ -1,7 +0,0 @@ -<?xml version="1.0"?> -<xsp:page xmlns:xsp="http://apache.org/xsp/core/v1"> - <output> - Hello World. The time of request is: - <xsp:expr>scalar localtime</xsp:expr> - </output> -</xsp:page> Copied: trunk/demo/xsp/test.xsp (from rev 18, trunk/demo/test.xsp) Modified: trunk/etc/axkit.conf =================================================================== --- trunk/etc/axkit.conf 2006-07-29 02:34:31 UTC (rev 19) +++ trunk/etc/axkit.conf 2006-07-31 21:07:03 UTC (rev 20) @@ -37,4 +37,9 @@ XSP_Match .*\.xsp </Location> + <Location /tal> + DocumentRoot /Users/matt/Perl/AxKit2/trunk/demo/tal + Plugin demo/serve_tal + </Location> + </Server> Modified: trunk/lib/AxKit2/Processor.pm =================================================================== --- trunk/lib/AxKit2/Processor.pm 2006-07-29 02:34:31 UTC (rev 19) +++ trunk/lib/AxKit2/Processor.pm 2006-07-31 21:07:03 UTC (rev 20) @@ -6,11 +6,12 @@ use Exporter (); our @ISA = qw(Exporter); -our @EXPORT = qw(XSP XSLT Output Render); +our @EXPORT = qw(XSP XSLT TAL Output Render); use XML::LibXML; use AxKit2::Transformer::XSP; use AxKit2::Transformer::XSLT; +use AxKit2::Transformer::TAL; our $parser = XML::LibXML->new(); @@ -76,7 +77,7 @@ sub str_to_transform { my $str = shift; ref($str) and return $str; - if ($str =~ /^(XSP|XSLT)\((.*)\)/) { + if ($str =~ /^(TAL|XSP|XSLT)\((.*)\)/) { return $1->($2); } else { @@ -108,6 +109,11 @@ return AxKit2::Transformer::XSLT->new($stylesheet); } +sub TAL { + my $stylesheet = shift || die "TAL requires a stylesheet"; + return AxKit2::Transformer::TAL->new($stylesheet); +} + sub Output { } Added: trunk/lib/AxKit2/Transformer/TAL.pm =================================================================== --- trunk/lib/AxKit2/Transformer/TAL.pm 2006-07-29 02:34:31 UTC (rev 19) +++ trunk/lib/AxKit2/Transformer/TAL.pm 2006-07-31 21:07:03 UTC (rev 20) @@ -0,0 +1,335 @@ +package AxKit2::Transformer::TAL; + +use strict; +use warnings; + +use base qw(AxKit2::Transformer::XSLT); + +my $parser = XML::LibXML->new(); +my $xslt = XML::LibXSLT->new(); +my $tal2xsl = $xslt->parse_stylesheet($parser->parse_fh(\*DATA)); + +my %cache; +sub transform { + my $self = shift; + my ($pos, $processor) = @_; + + my $dom = $processor->dom; + + my $stylefile = $self->{stylesheet}; + + my $stylesheet = $cache{$stylefile}; + if (!$stylesheet) { + my $style_doc = $parser->parse_file($stylefile); + my $xslt_dom = $tal2xsl->transform($style_doc); + $stylesheet = $xslt->parse_stylesheet($xslt_dom); + + $cache{$stylefile} = $stylesheet; + } + + my $results = $stylesheet->transform($dom); + + return $results, sub { $self->output(@_) }; +} + +sub output { + my ($self, $client, $dom) = @_; + + my ($out, $ct); + if (lc($dom->documentElement->nodeName) eq 'html') { + $out = $dom->toStringHTML(); + $ct = "text/html"; + } + else { + $out = $dom->toStringHTML(); + $ct = "application/xml"; + } + my $enc = "UTF-8"; + + $client->headers_out->header('Content-Length', length($out)); + $client->headers_out->header('Content-Type', "$ct; charset=$enc"); + $client->send_http_headers; + $client->write($out); +} + +1; + +__DATA__ +<?xml version="1.0"?> + +<!-- + Copyright 2004-2005 Bitflux GmbH + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + $Id: popoon.php 4323 2005-05-25 17:45:38Z chregu + +--> + +<xsl:stylesheet version="1.0" + xmlns:metal="http://xml.zope.org/namespaces/metal" + xmlns:bxf="http://bitflux.org/functions" + xmlns:tal="http://xml.zope.org/namespaces/tal" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xslout="whatever" + xmlns:func="http://exslt.org/functions" + extension-element-prefixes="func"> + + <xsl:namespace-alias stylesheet-prefix="xslout" result-prefix="xsl"/> + <func:function name="bxf:tales"> + <xsl:param name="path"/> + <xsl:choose> + <xsl:when test="$path = ''"> + <func:result select="'node()'"/> + </xsl:when> + <xsl:otherwise> + <func:result select="$path"/> + </xsl:otherwise> + </xsl:choose> + </func:function> + <xsl:template match="/"> + <xslout:stylesheet version="1.0" exclude-result-prefixes="bxf tal metal"> + <xsl:choose> + <xsl:when test="local-name(/node()) = 'html'"> + <xslout:output encoding="utf-8" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/> + </xsl:when> + <xsl:otherwise> + <xslout:output encoding="utf-8" method="xml"/> + </xsl:otherwise> + </xsl:choose> + <xsl:apply-templates select="//[EMAIL PROTECTED]:include]" mode="init"/> + <xsl:apply-templates select="//[EMAIL PROTECTED]:match]" mode="init"/> + <xsl:apply-templates select="//[EMAIL PROTECTED]:use-macro]" mode="init"/> + <xslout:template match="/"> + + <xsl:apply-templates/> + </xslout:template> + <!--copy all elements --> + <xslout:template match="*"> + <xslout:copy> + <xslout:apply-templates select="@*"/> + <xslout:apply-templates/> + </xslout:copy> + </xslout:template> + <!-- copy all attributes --> + <xslout:template match="@*"> + <xslout:copy-of select="."/> + </xslout:template> + </xslout:stylesheet> + + </xsl:template> + + + <xsl:template match="[EMAIL PROTECTED]:condition]" priority="10"> + <xslout:if test="{bxf:tales(@tal:condition)}"> + <xsl:apply-templates/> + </xslout:if> + </xsl:template> + + <xsl:template match="[EMAIL PROTECTED]:use-macro]"> + <xsl:variable name="doc" select="substring-before(@metal:use-macro,'#')"/> + <xsl:variable name="path" select="substring-after(@metal:use-macro,'#')"/> + <xsl:apply-templates select="document($doc)//[EMAIL PROTECTED]:define-macro = $path]"/> + </xsl:template> + + <xsl:template match="[EMAIL PROTECTED]:use-macro]" mode="init"> + <xsl:variable name="doc" select="substring-before(@metal:use-macro,'#')"/> + <xsl:variable name="path" select="substring-after(@metal:use-macro,'#')"/> + <xsl:apply-templates select="document($doc)//[EMAIL PROTECTED]:define-macro = $path]" mode="init"/> + </xsl:template> + + <xsl:template match="text()" mode ="init"> + <xsl:if test="ancestor::[EMAIL PROTECTED]:match]"> + <xsl:copy/> + </xsl:if> + </xsl:template> + + + + <xsl:template match="@metal:define-macro"> + </xsl:template> + <xsl:template match="[EMAIL PROTECTED]:content]" name="tal_content"> + <xsl:copy> + <xsl:apply-templates select="@*"/> + <xsl:call-template name="copy-value-apply"> + <xsl:with-param name="path" select="@tal:content"/> + </xsl:call-template> + </xsl:copy> + </xsl:template> + + + <xsl:template match="[EMAIL PROTECTED]:replace]"> + <xsl:call-template name="copy-value-apply"> + <xsl:with-param name="path" select="@tal:replace"/> + </xsl:call-template> + </xsl:template> + + + <xsl:template match="[EMAIL PROTECTED]:repeat]"> + <xsl:variable name="v" select="substring-before(@tal:repeat,' ')"/> + <xsl:variable name="x" select="substring-after(@tal:repeat,' ')"/> + <xslout:for-each select="{bxf:tales($x)}"> + <xslout:variable name="{$v}" select="."/> + <xsl:copy> + <xsl:apply-templates select="@*"/> + <xsl:apply-templates/> + </xsl:copy> + </xslout:for-each> + </xsl:template> + + <!-- special case of above if tal:repeat and tal:content are in the same element --> + <xsl:template match="[EMAIL PROTECTED]:repeat and @tal:content]"> + <xsl:variable name="v" select="substring-before(@tal:repeat,' ')"/> + <xsl:variable name="x" select="substring-after(@tal:repeat,' ')"/> + <xslout:for-each select="{bxf:tales($x)}"> + <xslout:variable name="{$v}" select="."/> + <xsl:call-template name="tal_content"/> + </xslout:for-each> + </xsl:template> + + + <xsl:template match="@*"> + <xsl:if test="namespace-uri() != 'http://xml.zope.org/namespaces/tal'"> + <xsl:copy-of select="."/> + </xsl:if> + </xsl:template> + + <xsl:template match="[EMAIL PROTECTED]:match]"/> + + <xsl:template match="[EMAIL PROTECTED]:include]" mode="init"> + <xsl:call-template name="talIncludes"> + <xsl:with-param name="include" select="@tal:include"/> + </xsl:call-template> + </xsl:template> + + <xsl:template name="talIncludes"> + <xsl:param name="include"/> + <xsl:choose> + <xsl:when test="contains($include,' ')"> + <xslout:include href="{substring-before($include,' ')}"/> + <xsl:call-template name="talIncludes"> + <xsl:with-param name="include" select="substring-after($include,' ')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xslout:include href="{$include}"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="[EMAIL PROTECTED]:match]" mode="init"> + <xslout:template match="[EMAIL PROTECTED]:match}"> + <xsl:apply-templates/> + </xslout:template> + </xsl:template> + + + <!-- outputs value-of, copy-of our apply-templates of $path depending on the first param + "/foo/bar" -> <xsl:value-of select="/foo/bar"/> + "text /foo/bar" -> <xsl:value-of select="/foo/bar"/> + "structure /foo/bar" -> <xsl:copy-of select="/foo/bar"/> + --> + <xsl:template name="copy-value-apply"> + <xsl:param name="path"/> + <xsl:variable name="mode"> + <xsl:value-of select="substring-before($path,' ')"/> + </xsl:variable> + <xsl:variable name="spath"> + <xsl:value-of select="substring-after($path,' ')"/> + </xsl:variable> + + <xsl:choose> + <!-- if no mode, use value-of --> + <xsl:when test="$path ='structure'"> + <xslout:apply-templates select="{bxf:tales('')}"/> + </xsl:when> + <xsl:when test="$mode = ''"> + <xslout:value-of select="{bxf:tales($path)}"/> + </xsl:when> + <xsl:when test="$mode = 'text'"> + <xslout:value-of select="{bxf:tales($spath)}"/> + </xsl:when> + <xsl:when test="$mode = 'text-escaped'"> + <xslout:value-of select="{bxf:tales($spath)}" disable-output-escaping="yes"/> + </xsl:when> + <xsl:when test="$path = 'structure .'"> + <xslout:copy> + <xslout:apply-templates select="@*"/> + <xslout:apply-templates select="{bxf:tales('')}"/> + </xslout:copy> + </xsl:when> + <xsl:when test="$mode = 'structure'"> + <xslout:apply-templates select="{bxf:tales($spath)}"/> + </xsl:when> + </xsl:choose> + </xsl:template> + + + <xsl:template match="@tal:attributes"> + <xsl:call-template name="talAttribute"> + <xsl:with-param name="attr" select="."/> + </xsl:call-template> + </xsl:template> + + <xsl:template name="talAttribute"> + <xsl:param name="attr"/> + <xsl:choose> + <xsl:when test="contains($attr,'; ')"> + + <xsl:call-template name="talAttribute"> + <xsl:with-param name="attr" select="substring-after($attr,'; ')"/> + </xsl:call-template> + <xsl:call-template name="outputTalAttribute"> + <xsl:with-param name="attr" select="substring-before($attr,'; ')"/> + </xsl:call-template> + </xsl:when> + + <xsl:otherwise> + <xsl:call-template name="outputTalAttribute"> + <xsl:with-param name="attr" select="$attr"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="outputTalAttribute"> + <xsl:param name="attr"/> + <xsl:variable name="name" select="substring-before($attr,' ')"/> + <xsl:variable name="value" select="substring-after($attr,' ')"/> + <xslout:attribute name="{$name}"> + <xslout:value-of select="{bxf:tales($value)}"/> + </xslout:attribute> + + </xsl:template> + + <xsl:template match="*"> + <xsl:copy> + <xsl:apply-templates select="@*"/> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + + + <xsl:template match="comment()"> + <xslout:comment> + <xsl:value-of select="."/> + </xslout:comment> + </xsl:template> + + + <xsl:template match="processing-instruction()"> + <xslout:processing-instruction name="{name()}"> + <xsl:value-of select="."/> + </xslout:processing-instruction> + </xsl:template> +</xsl:stylesheet> Added: trunk/plugins/demo/serve_tal =================================================================== --- trunk/plugins/demo/serve_tal 2006-07-29 02:34:31 UTC (rev 19) +++ trunk/plugins/demo/serve_tal 2006-07-31 21:07:03 UTC (rev 20) @@ -0,0 +1,14 @@ +#!/usr/bin/perl -w + +sub hook_xmlresponse { + my ($self, $input) = @_; + + $self->log(LOGDEBUG, "TAL Transform"); + + my $stylefile = $self->client->headers_in->filename; + $stylefile =~ s/\/[^\/]*$/\/tal.html/; + + my $out = $input->transform(TAL($stylefile)); + + return OK, $out; +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]