<!--
Nick's web site: XSLT helper functions.
- Copyright © 2019 Nick Bowler
+ Copyright © 2019-2021 Nick Bowler
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program. If not, see <https://www.gnu.org/licenses/>
-->
<xsl:stylesheet version='1.0'
+ xmlns='http://www.w3.org/1999/xhtml'
xmlns:xhtml='http://www.w3.org/1999/xhtml'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:func='http://exslt.org/functions'
xmlns:f='http://draconx.ca/my-functions'
extension-element-prefixes='func f'>
+<xsl:output method='xml' encoding='UTF-8' indent='yes'
+ doctype-public='-//W3C//DTD XHTML 1.1//EN'
+ doctype-system='http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd' />
+
<!-- Returns true iff the given element is an XHTML span-level element -->
<func:function name='f:element-is-span'>
<xsl:param name='node' select='.' />
<!-- Returns true iff the node is a nonempty text node or a span element -->
<func:function name='f:node-is-span'>
<xsl:param name='node' select='.' />
- <func:result test='( $node/self::text() and normalize-text($node) )
- or f:element-is-span($node)' />
+ <func:result select='( $node/self::text() and normalize-text($node) )
+ or f:element-is-span($node)' />
+</func:function>
+
+<!-- f:ends-with(a, b) returns true iff a ends with b -->
+<func:function name='f:ends-with'>
+ <xsl:param name='str' />
+ <xsl:param name='suffix' />
+ <func:result select='$suffix=substring($str,
+ string-length($str)-string-length($suffix)+1)' />
+</func:function>
+
+<!-- Remove leading whitespace from a string -->
+<func:function name='f:strip-leading'>
+ <xsl:param name='str' select='.' />
+ <xsl:param name='curlen' select='string-length($str)' />
+
+ <xsl:variable name='a' select='substring($str, 1, $curlen)' />
+ <xsl:variable name='b' select='substring($str, 1+$curlen)' />
+
+ <xsl:choose>
+ <xsl:when test='2 > $curlen'>
+ <func:result select='concat(normalize-space($a), $b)' />
+ </xsl:when>
+ <xsl:when test='normalize-space($a) = ""'>
+ <func:result select='f:strip-leading($b)' />
+ </xsl:when>
+ <xsl:otherwise>
+ <func:result select='f:strip-leading($str, ceiling($curlen div 2))' />
+ </xsl:otherwise>
+ </xsl:choose>
+</func:function>
+
+<!-- Remove trailing whitespace from a string -->
+<func:function name='f:strip-trailing'>
+ <xsl:param name='str' select='.' />
+ <xsl:param name='curlen' select='string-length($str)' />
+
+ <xsl:variable name='split' select='string-length($str) - $curlen' />
+ <xsl:variable name='a' select='substring($str, 1, $split)' />
+ <xsl:variable name='b' select='substring($str, 1+$split)' />
+
+ <xsl:choose>
+ <xsl:when test='2 > $curlen'>
+ <func:result select='concat($a, normalize-space($b))' />
+ </xsl:when>
+ <xsl:when test='normalize-space($b) = ""'>
+ <func:result select='f:strip-trailing($a)' />
+ </xsl:when>
+ <xsl:otherwise>
+ <func:result select='f:strip-trailing($str, ceiling($curlen div 2))' />
+ </xsl:otherwise>
+ </xsl:choose>
+</func:function>
+
+<!--
+ Convert the given node to a string containing an XHTML listing for that node.
+-->
+<func:function name='f:xhtml-listing'>
+ <xsl:param name='nodeset' select='.' />
+ <xsl:variable name='node' select='$nodeset[1]' />
+
+ <func:result>
+ <xsl:choose>
+ <xsl:when test='$node/self::text()'>
+ <!-- text node -->
+ <xsl:value-of select='$node' />
+ </xsl:when>
+ <xsl:when test='$node/self::comment()'>
+ <!-- comment node -->
+ <xsl:value-of select='concat("<!--", $node, "-->")' />
+ </xsl:when>
+ <xsl:when test='$node/self::*'>
+ <!-- element node -->
+ <xsl:value-of select='concat("<", local-name($node))' />
+ <xsl:value-of select='f:xhtml-listing($node/@*)' />
+ <xsl:if test='not($node/node())'>/</xsl:if>
+ <xsl:value-of select='concat(">", f:xhtml-listing($node/node()))' />
+ <xsl:if test='$node/node()'>
+ <xsl:value-of select='concat("</", local-name($node), ">")' />
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test='$node'>
+ <!-- attribute node -->
+ <xsl:value-of select='concat(" ", local-name($node), "=")' />
+ <xsl:value-of select='concat("'", $node, "'")' />
+ </xsl:when>
+ </xsl:choose>
+ <xsl:for-each select='$nodeset[position()>1]'>
+ <xsl:value-of select='f:xhtml-listing()' />
+ </xsl:for-each>
+ </func:result>
</func:function>
</xsl:stylesheet>