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