<?xml version="1.0"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You 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.
-->

<!--
  - XSP Core logicsheet for the Python language
  -
  - @author <a href="mailto:vgritsenko@apache.org>Vadim Gritsenko</a>
  - @version CVS $Id: xsp.xsl 433543 2006-08-22 06:22:54Z crossley $
  -->

<xsl:stylesheet version="1.0"
                xmlns:xsp="http://apache.org/xsp"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:XSLTExtension="org.apache.cocoon.components.language.markup.xsp.XSLTExtension">
  <xsl:output method="text"/>

  <!--
    Set to "strip" to strip empty space like XSLT.
    Else space is preserved to remain compatible.
  -->
  <xsl:variable name="space" select="/xsp:page/@space"/>

  <xsl:variable name="xsp-uri" select="'http://apache.org/xsp'"/>

  <!--
    this variable holds the instance of extension class to properly
    escape text into Java strings

    ovidiu: use the class name as the namespace to identify the
    class. This is supposedly portable across XSLT implementations.
  -->
  <xsl:variable
       name="extension"
       select="XSLTExtension:new()"
       xmlns:XSLTExtension="org.apache.cocoon.components.language.markup.xsp.XSLTExtension"/>



  <xsl:template match="/">
    <code>
      <xsl:text>""" $Cocoon extends: org.apache.cocoon.components.language.markup.xsp.PythonGenerator$ """
</xsl:text>
      <xsl:for-each select="//xsp:dependency">
        <xsl:text>""" $Cocoon depends: </xsl:text>
        <xsl:value-of select="translate(., '\','/')"/>
        <xsl:text>$ """
</xsl:text>
       </xsl:for-each>

      <xsl:apply-templates select="xsp:page"/>
    </code>
  </xsl:template>



  <xsl:template match="xsp:page">
""" Generated by XSP. Edit at your own risk, :-)

    <xsl:if test="$space = 'strip'">
     Whitespace introduced in the XSP will not propagate into
     the resulting XML document! To retain all whitespace,
     remove the "space" attribute from the root &lt;xsp:page&gt;
     element.
    </xsl:if>

Built-in beans for internal use:
    page           - "this" in Java
    contentHandler - page.contentHandler
    xspAttr     - AttributesImpl

Built-in beans available for use:
    context    - org.apache.cocoon.environment.Context
    request    - org.apache.cocoon.environment.Request
    response   - org.apache.cocoon.environment.Response
    parameters - parameters defined in the sitemap
    objectModel- java.util.Map
    resolver   - org.apache.cocoon.environment.SourceResolver
    objectModel - Map
    logger      - Logger
"""

from java import lang
from java import util

<xsl:text>""" User Class "Declarations" """
</xsl:text>
    <xsl:apply-templates select="xsp:logic">
      <xsl:with-param name="indent" select="''"/>
    </xsl:apply-templates>

<xsl:text>""" User Class Initialization """
</xsl:text>
    <xsl:value-of select="xsp:init-page"/>

<xsl:text>""" Document Body """
</xsl:text>
    <xsl:text>contentHandler.startDocument()
</xsl:text>

    <!-- Generate top-level processing instructions -->
    <xsl:apply-templates select="/processing-instruction()"/>

    <!-- Process only 1st non-XSP element as generated root -->
    <xsl:call-template name="process-first-element">
      <xsl:with-param name="content" select="*[not(namespace-uri(.) = $xsp-uri)][1]"/>
    </xsl:call-template>

    <xsl:text>contentHandler.endDocument()
</xsl:text>
  </xsl:template>



  <xsl:template name="process-first-element">
    <xsl:param name="content"/>

    <!-- Generate top-level namespaces declarations -->
    <xsl:variable name="parent-element" select="$content/.."/>
    <xsl:for-each select="$content/namespace::*">
      <xsl:variable name="ns-prefix" select="local-name(.)"/>
      <xsl:variable name="ns-uri" select="string(.)"/>
      <!-- Declare namespaces that also exist on the parent (i.e. not locally declared),
           and filter out "xmlns:xmlns" namespace produced by Xerces+Saxon -->
      <xsl:if test="($ns-prefix != 'xmlns') and $parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri]">
        <xsl:text>contentHandler.startPrefixMapping("</xsl:text>
        <xsl:value-of select="$ns-prefix"/>", "<xsl:value-of select="$ns-uri"/>
        <xsl:text>")
</xsl:text>
      </xsl:if>
    </xsl:for-each>

    <xsl:text>if 1: # Process First Element
</xsl:text>

    <!-- Generate content -->
    <xsl:apply-templates select="$content">
      <xsl:with-param name="indent" select="''"/>
    </xsl:apply-templates>

    <!-- Close top-level namespaces declarations-->
    <xsl:for-each select="$content/namespace::*">
      <xsl:variable name="ns-prefix" select="local-name(.)"/>
      <xsl:variable name="ns-uri" select="string(.)"/>
      <xsl:if test="($ns-prefix != 'xmlns') and $parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri]">
        <xsl:text>contentHandler.endPrefixMapping("</xsl:text>
        <xsl:value-of select="local-name(.)"/>
        <xsl:text>")
</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>



  <xsl:template match="xsp:element">
    <xsl:param name="indent"/>

    <xsl:variable name="zindent">
      <xsl:choose>
        <xsl:when test="string-length(XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])) &gt; 0">
          <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/>
        </xsl:when>
        <xsl:when test="string-length(XSLTExtension:suffix($extension, preceding-sibling::text()[1])) &gt; 0">
          <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$indent"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="uri">
      <xsl:call-template name="get-parameter">
        <xsl:with-param name="name">uri</xsl:with-param>
        <xsl:with-param name="indent" select="$indent"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="prefix">
      <xsl:call-template name="get-parameter">
        <xsl:with-param name="name">prefix</xsl:with-param>
        <xsl:with-param name="indent" select="$indent"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:if test="@name and contains(@name, ':')">
      <xsl:call-template name="error">
        <xsl:with-param name="message">[&lt;xsp:element name="<xsl:value-of select="@name"/>"&gt;]
Name can not contain ':'. If you want to create namespaced element, specify 'uri' and 'prefix'.
        </xsl:with-param>
      </xsl:call-template>
    </xsl:if>

    <xsl:variable name="name">
      <xsl:call-template name="get-parameter">
        <xsl:with-param name="name">name</xsl:with-param>
        <xsl:with-param name="required">true</xsl:with-param>
        <xsl:with-param name="indent" select="$indent"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="raw-name">
      <xsl:if test="
        ($uri = '&quot;&quot;' and $prefix != '&quot;&quot;') or
        ($uri != '&quot;&quot;' and $prefix = '&quot;&quot;')">
        <xsl:call-template name="error">
          <xsl:with-param name="message">[&lt;xsp:element&gt;]
Either both 'uri' and 'prefix' or none of them must be specified
          </xsl:with-param>
        </xsl:call-template>
      </xsl:if>

      <xsl:choose>
        <xsl:when test="$prefix = '&quot;&quot;'">
          <xsl:copy-of select="$name"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>(</xsl:text>
          <xsl:copy-of select="$prefix"/> + ":" + <xsl:copy-of select="$name"/>
          <xsl:text>)</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <!-- Start Element -->
    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;</xsl:text>
    <xsl:value-of select="name(.)"/>
    <xsl:text>&gt;
</xsl:text>
    <!-- Declare namespaces that are not already present on the parent element.
         Note : we could use "../../namespace::*[...]" to get parent element namespaces
         but Xalan 2.0.1 retunrs only the first namespace (Saxon is OK).
         That's why we store the parent element in a variable -->
    <xsl:variable name="parent-element" select=".."/>
    <xsl:for-each select="namespace::*">
      <xsl:variable name="ns-prefix" select="local-name(.)"/>
      <xsl:variable name="ns-uri" select="string(.)"/>
      <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])">
        <xsl:value-of select="$zindent"/>
        <xsl:text>contentHandler.startPrefixMapping("</xsl:text>
        <xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="."/>
        <xsl:text>")
</xsl:text>
      </xsl:if>
    </xsl:for-each>

    <!-- Declare namespace defined by @uri and @prefix attribute -->
    <xsl:if test="$uri != '&quot;&quot;'">
      <xsl:if test="not($parent-element/namespace::*[local-name(.) = $prefix and string(.) = $uri])">
        <xsl:value-of select="$zindent"/>
        <xsl:text>contentHandler.startPrefixMapping(</xsl:text>
        <xsl:value-of select="$prefix"/>, <xsl:value-of select="$uri"/>
        <xsl:text>)
</xsl:text>
      </xsl:if>
    </xsl:if>

    <!-- Attributes -->
    <xsl:apply-templates select="xsp:attribute | xsp:logic[xsp:attribute]">
      <xsl:with-param name="indent" select="$zindent"/>
    </xsl:apply-templates>

    <xsl:value-of select="$zindent"/>
    <xsl:text>contentHandler.startElement(</xsl:text>
    <xsl:copy-of select="$uri"/>, <xsl:copy-of select="$name"/>, <xsl:copy-of select="$raw-name"/>
    <xsl:text>, xspAttr)
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text>xspAttr.clear()
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text>if 1:
</xsl:text>

    <!-- Element body -->
    <xsl:apply-templates select="node()[not(
      (namespace-uri(.) = $xsp-uri and local-name(.) = 'attribute') or
      (namespace-uri(.) = $xsp-uri and local-name(.) = 'logic' and ./xsp:attribute)
      )]">
      <xsl:with-param name="indent" select="concat($zindent, '   ')"/>
    </xsl:apply-templates>

    <xsl:value-of select="$zindent"/>
    <xsl:text>contentHandler.endElement(</xsl:text>
    <xsl:copy-of select="$uri"/>, <xsl:copy-of select="$name"/>, <xsl:copy-of select="$raw-name"/>
    <xsl:text>)
</xsl:text>

    <!-- Declare namespace defined by @uri and @prefix attribute -->
    <xsl:if test="$uri != '&quot;&quot;'">
      <xsl:if test="not($parent-element/namespace::*[local-name(.) = $prefix and string(.) = $uri])">
        <xsl:value-of select="$zindent"/>
        <xsl:text>contentHandler.endPrefixMapping(</xsl:text>
        <xsl:value-of select="$prefix"/>
        <xsl:text>)
</xsl:text>
      </xsl:if>
    </xsl:if>

    <!-- End Namespaces -->
    <xsl:for-each select="namespace::*">
      <xsl:variable name="ns-prefix" select="local-name(.)"/>
      <xsl:variable name="ns-uri" select="string(.)"/>
      <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])">
        <xsl:value-of select="$zindent"/>
        <xsl:text>contentHandler.endPrefixMapping("</xsl:text>
        <xsl:value-of select="local-name(.)"/>
        <xsl:text>")
</xsl:text>
      </xsl:if>
    </xsl:for-each>

    <!-- End Element -->
    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;/</xsl:text>
    <xsl:value-of select="name(.)"/>
    <xsl:text>&gt;
</xsl:text>
  </xsl:template>



  <xsl:template match="xsp:attribute">
    <xsl:param name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/>

    <xsl:variable name="uri">
      <xsl:call-template name="get-parameter">
        <xsl:with-param name="name">uri</xsl:with-param>
        <xsl:with-param name="indent" select="$indent"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="prefix">
      <xsl:call-template name="get-parameter">
        <xsl:with-param name="name">prefix</xsl:with-param>
        <xsl:with-param name="indent" select="$indent"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="name">
      <xsl:call-template name="get-parameter">
        <xsl:with-param name="name">name</xsl:with-param>
        <xsl:with-param name="required">true</xsl:with-param>
        <xsl:with-param name="indent" select="$indent"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="raw-name">
      <xsl:if test="
        ($uri = '&quot;&quot;' and $prefix != '&quot;&quot;') or
        ($uri != '&quot;&quot;' and $prefix = '&quot;&quot;')
      ">
        <xsl:call-template name="error">
          <xsl:with-param name="message">[&lt;xsp:attribute&gt;]
Either both 'uri' and 'prefix' or none of them must be specified
          </xsl:with-param>
        </xsl:call-template>
      </xsl:if>

      <xsl:choose>
        <xsl:when test="$prefix = '&quot;&quot;'">
          <xsl:copy-of select="$name"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>(</xsl:text>
          <xsl:copy-of select="$prefix"/> + ":" + <xsl:copy-of select="$name"/>
          <xsl:text>)</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="content">
      <xsl:for-each select="text()|xsp:expr|xsp:text">
        <xsl:if test="position() &gt; 1">
         <xsl:text> + </xsl:text>
        </xsl:if>
        <xsl:choose>
          <xsl:when test="namespace-uri(.) = $xsp-uri and local-name(.) = 'expr'">
            <xsl:text>(</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>)</xsl:text>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text>"</xsl:text>
            <xsl:value-of select="XSLTExtension:escape($extension, .)"/>
            <xsl:text>"</xsl:text>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
      <xsl:if test="not(text()|xsp:expr|xsp:text)">
        <xsl:text>""</xsl:text>
      </xsl:if>
    </xsl:variable>

    <xsl:text>
</xsl:text>
    <xsl:value-of select="$indent"/>
    <xsl:text>xspAttr.addAttribute(</xsl:text>
    <xsl:copy-of select="$uri"/>, <xsl:copy-of select="$name"/>, <xsl:copy-of select="$raw-name"/>
    <xsl:text>, "CDATA", </xsl:text><xsl:value-of select="normalize-space($content)"/>
    <xsl:text>)
</xsl:text>
  </xsl:template>



  <xsl:template match="xsp:expr">
    <xsl:variable name="indent">
      <xsl:choose>
        <xsl:when test="preceding-sibling::xsp:text[1]">
          <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="namespace-uri(..) = $xsp-uri and local-name(..) != 'content' and local-name(..) != 'element'">
        <!--
             Expression is nested inside another XSP tag:
             preserve its Java type
        -->
        <xsl:text>(</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>)</xsl:text>
      </xsl:when>
      <xsl:when test="string-length(.) = 0">
        <!-- Do nothing -->
      </xsl:when>
      <xsl:otherwise>
        <!-- Output the value as elements or character data depending on its type -->
        <xsl:value-of select="$indent"/>
        <xsl:text>page.xspExpr(</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>)
</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>



  <!-- FIXME: Is this _really_ necessary? -->
  <xsl:template match="xsp:content">
    <xsl:variable name="zindent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/>
    <xsl:text>
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;xsp:content&gt;
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text>if 1:
</xsl:text>
    <xsl:apply-templates>
      <xsl:with-param name="indent" select="XSLTExtension:suffix($extension, text()[1])"/>
    </xsl:apply-templates>
    <xsl:text>
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;/xsp:content&gt;
</xsl:text>
  </xsl:template>



  <xsl:template match="xsp:logic">
    <xsl:variable name="zindent" select="XSLTExtension:suffix($extension, preceding-sibling::xsp:text[1])"/>

    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;xsp:logic&gt;
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text>if 1:
</xsl:text>
    <xsl:apply-templates/>

    <xsl:text>
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;/xsp:logic&gt;
</xsl:text>
  </xsl:template>



  <xsl:template match="xsp:pi">
    <xsl:variable name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/>

    <xsl:variable name="target">
      <xsl:call-template name="get-parameter">
        <xsl:with-param name="name">target</xsl:with-param>
        <xsl:with-param name="indent" select="$indent"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="content">
      <xsl:for-each select="text()|xsp:expr">
        <xsl:choose>
          <xsl:when test="namespace-uri(.) = $xsp-uri and local-name(.) = 'expr'">
            <xsl:text>String(</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>)</xsl:text>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text>"</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>"</xsl:text>
          </xsl:otherwise>
        </xsl:choose>
        <xsp:text> + </xsp:text>
      </xsl:for-each>
      <xsl:text>""</xsl:text>
    </xsl:variable>

    <xsl:value-of select="$indent"/>
    <xsl:text>contentHandler.processingInstruction(</xsl:text>
    <xsl:copy-of select="$target"/>, <xsl:value-of select="normalize-space($content)"/>
    <xsl:text>)
</xsl:text>
  </xsl:template>



  <!-- FIXME: How to create comments in SAX? -->
  <xsl:template match="xsp:comment">
    <xsl:variable name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/>

    <xsl:value-of select="$indent"/>
    <xsl:text>page.xspComment("</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>")
</xsl:text>
  </xsl:template>



  <xsl:template match="*[not(namespace-uri(.) = $xsp-uri)]">
    <xsl:param name="indent"/>

    <xsl:variable name="text-sibling" select="preceding-sibling::xsp:text[string-length(XSLTExtension:suffix($extension, .)) &gt; 0][1]"/>
    <xsl:variable name="textn-sibling" select="preceding-sibling::text()[string-length(XSLTExtension:suffix($extension, .)) &gt; 0][1]"/>
    <xsl:variable name="zindent">
      <xsl:choose>
        <xsl:when test="$text-sibling">
          <xsl:value-of select="XSLTExtension:suffix($extension, $text-sibling)"/>
        </xsl:when>
        <xsl:when test="$textn-sibling">
          <xsl:value-of select="XSLTExtension:suffix($extension, $textn-sibling)"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$indent"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <!-- Start Element -->
    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;</xsl:text>
    <xsl:value-of select="name(.)"/>
    <xsl:text>&gt;
</xsl:text>

    <xsl:variable name="parent-element" select=".."/>
    <xsl:for-each select="namespace::*">
      <xsl:variable name="ns-prefix" select="local-name(.)"/>
      <xsl:variable name="ns-uri" select="string(.)"/>
      <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])">
        <xsl:value-of select="$zindent"/>
        <xsl:text>contentHandler.startPrefixMapping("</xsl:text>
        <xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="."/>
        <xsl:text>")
</xsl:text>
      </xsl:if>
    </xsl:for-each>

    <xsl:apply-templates select="@*"/>

    <xsl:apply-templates select="xsp:attribute | xsp:logic[xsp:attribute]">
      <xsl:with-param name="indent" select="$zindent"/>
    </xsl:apply-templates>

    <xsl:value-of select="$zindent"/>
    <xsl:text>contentHandler.startElement("</xsl:text>
    <xsl:value-of select="namespace-uri(.)"/>", "<xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="name(.)"/>
    <xsl:text>", xspAttr)
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text>xspAttr.clear()
</xsl:text>
    <xsl:value-of select="$zindent"/>
    <xsl:text>if 1:
</xsl:text>

    <xsl:apply-templates select="node()[not(
        (namespace-uri(.) = $xsp-uri and local-name(.) = 'attribute') or
        (namespace-uri(.) = $xsp-uri and local-name(.) = 'logic' and ./xsp:attribute)
      )]">
      <xsl:with-param name="indent" select="concat($zindent, '   ')"/>
    </xsl:apply-templates>

    <xsl:value-of select="$zindent"/>
    <xsl:text>contentHandler.endElement("</xsl:text>
    <xsl:value-of select="namespace-uri(.)"/>", "<xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="name(.)"/>
    <xsl:text>")
</xsl:text>

    <xsl:for-each select="namespace::*">
      <xsl:variable name="ns-prefix" select="local-name(.)"/>
      <xsl:variable name="ns-uri" select="string(.)"/>
      <xsl:if test="not($parent-element/namespace::*[local-name(.) = $ns-prefix and string(.) = $ns-uri])">
        <xsl:value-of select="$zindent"/>
        <xsl:text>contentHandler.endPrefixMapping("</xsl:text>
        <xsl:value-of select="local-name(.)"/>
        <xsl:text>")
</xsl:text>
      </xsl:if>
    </xsl:for-each>

    <!-- End Element -->
    <xsl:value-of select="$zindent"/>
    <xsl:text># &lt;/</xsl:text>
    <xsl:value-of select="name(.)"/>
    <xsl:text>&gt;
</xsl:text>
  </xsl:template>



  <xsl:template match="@*">
    <xsl:param name="indent" select="XSLTExtension:suffix($extension, preceding-sibling::text()[1])"/>

    <!-- Filter out namespace declaration attributes -->
    <xsl:if test="not(starts-with(name(.), 'xmlns:'))">
      <xsl:value-of select="$indent"/>
      <xsl:text>xspAttr.addAttribute("</xsl:text>
      <xsl:value-of select="namespace-uri(.)"/>", "<xsl:value-of select="local-name(.)"/>", "<xsl:value-of select="name(.)"/>", "CDATA", "<xsl:value-of select="XSLTExtension:escape($extension, .)"/>
      <xsl:text>")
</xsl:text>
    </xsl:if>
  </xsl:template>



  <xsl:template match="xsp:text">
    <xsl:param name="indent"/>

    <xsl:variable name="text-sibling" select="preceding-sibling::xsp:text[string-length(XSLTExtension:suffix($extension, .)) &gt; 0][1]"/>
    <xsl:variable name="zindent">
      <xsl:choose>
        <xsl:when test="string-length(XSLTExtension:prefix($extension, .)) &gt; 0">
          <xsl:value-of select="XSLTExtension:prefix($extension, .)"/>
        </xsl:when>
        <xsl:when test="$text-sibling">
          <xsl:value-of select="XSLTExtension:suffix($extension, $text-sibling)"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$indent"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:choose>
      <xsl:when test="namespace-uri(..) = $xsp-uri and (local-name(..) = 'logic' or local-name(..) = 'expr')">
        <xsl:value-of select="."/>
      </xsl:when>
      <xsl:when test="$space = 'strip'">
        <xsl:variable name="txt" select="normalize-space(.)"/>
        <xsl:if test="$txt != '' and $txt != ' '">
          <xsl:value-of select="$zindent"/>
          <xsl:text>page.xspCharacters("</xsl:text>
          <xsl:value-of select="XSLTExtension:escapeJava($extension, $txt)"/>
          <xsl:text>")
</xsl:text>
        </xsl:if>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$zindent"/>
        <xsl:text>page.xspCharacters("</xsl:text>
        <xsl:value-of select="XSLTExtension:escapeJava($extension, .)"/>
        <xsl:text>")
</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>



  <xsl:template match="text()" mode="value">
    <xsl:value-of select="."/>
  </xsl:template>



  <xsl:template match="processing-instruction()">
    <xsl:text>
</xsl:text>
    <xsl:text>contentHandler.processingInstruction("</xsl:text>
    <xsl:value-of select="name()"/>", "<xsl:value-of select="."/>
    <xsl:text>")
</xsl:text>
  </xsl:template>



  <!-- Utility templates -->
  <xsl:template name="get-parameter">
    <xsl:param name="indent" select="'????'"/>

    <xsl:param name="name"/>
    <xsl:param name="default"/>
    <xsl:param name="required">false</xsl:param>

    <xsl:choose>
      <xsl:when test="@*[name(.) = $name]">"<xsl:value-of select="@*[name(.) = $name]"/>"</xsl:when>
      <xsl:when test="xsp:param[@name = $name]">
        <xsl:call-template name="get-parameter-content">
          <xsl:with-param name="content"
                          select="(*[namespace-uri(.)=$xsp-uri and local-name(.) = 'param'])[@name = $name]"/>
          <xsl:with-param name="indent" select="$indent"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="string-length($default) = 0">
            <xsl:choose>
              <xsl:when test="$required = 'true'">
                <xsl:call-template name="error">
                  <xsl:with-param name="message">[Logicsheet processor]
Parameter '<xsl:value-of select="$name"/>' missing in dynamic tag &lt;<xsl:value-of select="name(.)"/>&gt;
                  </xsl:with-param>
                </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>""</xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:otherwise><xsl:copy-of select="$default"/></xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>



  <xsl:template name="get-parameter-content">
    <xsl:param name="indent" select="'????'"/>
    <xsl:param name="content"/>
    <xsl:choose>
      <xsl:when test="$content/*[namespace-uri(.)=$xsp-uri and local-name(.) != 'text']">
        <xsl:apply-templates select="$content/*[namespace-uri(.)=$xsp-uri and local-name(.) != 'text']">
          <xsl:with-param name="indent" select="$indent"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>"<xsl:value-of select="$content"/>"</xsl:otherwise>
    </xsl:choose>
  </xsl:template>



  <xsl:template name="get-nested-content">
    <xsl:param name="indent" select="'????'"/>
    <xsl:param name="content"/>
    <xsl:choose>
      <xsl:when test="$content/*">
        <xsl:apply-templates select="$content/*">
          <xsl:with-param name="indent" select="$indent"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>"<xsl:value-of select="$content"/>"</xsl:otherwise>
    </xsl:choose>
  </xsl:template>



  <xsl:template name="error">
    <xsl:param name="message"/>
    <xsl:message terminate="yes"><xsl:value-of select="$message"/></xsl:message>
  </xsl:template>


  <!-- Ignored elements -->
  <xsl:template match="xsp:logicsheet|xsp:dependency|xsp:param"/>
</xsl:stylesheet>
