2 Nick's web site: XSLT helper functions.
4 Copyright © 2019-2020 Nick Bowler
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>
19 <xsl:stylesheet version='1.0'
20 xmlns:xhtml='http://www.w3.org/1999/xhtml'
21 xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
22 xmlns:func='http://exslt.org/functions'
23 xmlns:f='http://draconx.ca/my-functions'
24 extension-element-prefixes='func f'>
26 <!-- Returns true iff the given element is an XHTML span-level element -->
27 <func:function name='f:element-is-span'>
28 <xsl:param name='node' select='.' />
29 <func:result select='$node/self::xhtml:a
30 or $node/self::xhtml:abbr
31 or $node/self::xhtml:acronym
32 or $node/self::xhtml:b
33 or $node/self::xhtml:bdo
34 or $node/self::xhtml:big
35 or $node/self::xhtml:br
36 or $node/self::xhtml:button
37 or $node/self::xhtml:cite
38 or $node/self::xhtml:code
39 or $node/self::xhtml:dfn
40 or $node/self::xhtml:em
41 or $node/self::xhtml:i
42 or $node/self::xhtml:img
43 or $node/self::xhtml:input
44 or $node/self::xhtml:kbd
45 or $node/self::xhtml:label
46 or $node/self::xhtml:map
47 or $node/self::xhtml:object
48 or $node/self::xhtml:q
49 or $node/self::xhtml:samp
50 or $node/self::xhtml:script
51 or $node/self::xhtml:select
52 or $node/self::xhtml:small
53 or $node/self::xhtml:span
54 or $node/self::xhtml:strong
55 or $node/self::xhtml:sub
56 or $node/self::xhtml:sup
57 or $node/self::xhtml:textarea
58 or $node/self::xhtml:time
59 or $node/self::xhtml:tt
60 or $node/self::xhtml:var' />
63 <!-- Returns true iff the node is a nonempty text node or a span element -->
64 <func:function name='f:node-is-span'>
65 <xsl:param name='node' select='.' />
66 <func:result select='( $node/self::text() and normalize-text($node) )
67 or f:element-is-span($node)' />
70 <!-- Remove leading whitespace from a string -->
71 <func:function name='f:strip-leading'>
72 <xsl:param name='str' select='.' />
73 <xsl:param name='curlen' select='string-length($str)' />
75 <xsl:variable name='a' select='substring($str, 1, $curlen)' />
76 <xsl:variable name='b' select='substring($str, 1+$curlen)' />
79 <xsl:when test='2 > $curlen'>
80 <func:result select='concat(normalize-space($a), $b)' />
82 <xsl:when test='normalize-space($a) = ""'>
83 <func:result select='f:strip-leading($b)' />
86 <func:result select='f:strip-leading($str, ceiling($curlen div 2))' />
91 <!-- Remove trailing whitespace from a string -->
92 <func:function name='f:strip-trailing'>
93 <xsl:param name='str' select='.' />
94 <xsl:param name='curlen' select='string-length($str)' />
96 <xsl:variable name='split' select='string-length($str) - $curlen' />
97 <xsl:variable name='a' select='substring($str, 1, $split)' />
98 <xsl:variable name='b' select='substring($str, 1+$split)' />
101 <xsl:when test='2 > $curlen'>
102 <func:result select='concat($a, normalize-space($b))' />
104 <xsl:when test='normalize-space($b) = ""'>
105 <func:result select='f:strip-trailing($a)' />
108 <func:result select='f:strip-trailing($str, ceiling($curlen div 2))' />
114 Convert the given node to a string containing an XHTML listing for that node.
116 <func:function name='f:xhtml-listing'>
117 <xsl:param name='nodeset' select='.' />
118 <xsl:variable name='node' select='$nodeset[1]' />
122 <xsl:when test='$node/self::text()'>
124 <xsl:value-of select='$node' />
126 <xsl:when test='$node/self::comment()'>
127 <!-- comment node -->
128 <xsl:value-of select='concat("<!--", $node, "-->")' />
130 <xsl:when test='$node/self::*'>
131 <!-- element node -->
132 <xsl:value-of select='concat("<", local-name($node))' />
133 <xsl:value-of select='f:xhtml-listing($node/@*)' />
134 <xsl:if test='not($node/node())'>/</xsl:if>
135 <xsl:value-of select='concat(">", f:xhtml-listing($node/node()))' />
136 <xsl:if test='$node/node()'>
137 <xsl:value-of select='concat("</", local-name($node), ">")' />
140 <xsl:when test='$node'>
141 <!-- attribute node -->
142 <xsl:value-of select='concat(" ", local-name($node), "=")' />
143 <xsl:value-of select='concat("'", $node, "'")' />
146 <xsl:for-each select='$nodeset[position()>1]'>
147 <xsl:value-of select='f:xhtml-listing()' />