Project

Profile

Help

Bug #4532 » string.xsl

Source of string.sef - Jeremy Cronk, 2020-05-08 18:46

 
<?xml version="1.0" encoding="UTF-8"?>
<xsl:package name="com.ivans.connect.utils.string" package-version="0.1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:nx="http://www.ivansinsurance.com/connect" xmlns:st="http://www.ivansinsurance.com/connect/utils/string"
xmlns:s-="http://www.ivansinsurance.com/connect/utils/string/private"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:helper="http://www.ivansinsurance.com/connect/test/helpers" xmlns:dt="http://exslt.org/dates-and-times"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:data="http://www.ivansinsurance.com/connect/lookup-tables" exclude-result-prefixes="#all" version="3.0">
<xsl:expose visibility="public" component="function" names="st:*"/>
<xsl:expose visibility="public" component="variable" names="st:*"/>
<xsl:variable name="st:zeroes"
>0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</xsl:variable>
<xsl:variable name="st:spaces">
<xsl:text> </xsl:text>
</xsl:variable>
<xsl:variable name="st:question-marks"
>????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????</xsl:variable>
<!-- Syntactic sugar function allowing negative start/offset -->
<xsl:function name="st:substr">
<xsl:param name="string" as="xs:string?"/>
<xsl:param name="start"/>
<xsl:param name="offset"/>
<xsl:variable name="adjustor" select="s-:modify-substr-ix($string, ?)"/>
<xsl:sequence select="substring($string, $adjustor($start), $adjustor($offset))"/>
</xsl:function>
<!-- Two-argument version that goes from start index to end of string -->
<xsl:function name="st:substr">
<xsl:param name="string" as="xs:string?"/>
<xsl:param name="start"/>
<xsl:sequence select="substring($string, s-:modify-substr-ix($string, $start))"/>
</xsl:function>
<!-- Helper function for st:substr; calculates positive version of negative indices or returns index if already positive -->
<xsl:function name="s-:modify-substr-ix">
<xsl:param name="string"/>
<xsl:param name="index"/>
<xsl:sequence
select="
if ($index lt 1) then
string-length($string) + $index + 1
else
$index"
/>
</xsl:function>
<!-- A version of translate() that supports character ranges and negations -->
<xsl:function name="st:tr" as="xs:string">
<xsl:param name="source-string" as="xs:string"/>
<xsl:param name="from-pattern" as="xs:string"/>
<xsl:param name="to-string" as="xs:string"/>
<xsl:variable name="from-string"
select="$from-pattern => s-:expand-ranges() => s-:invert-tr-string($source-string)"/>
<xsl:sequence select="translate($source-string, $from-string, $to-string)"/>
</xsl:function>
<!-- Two-argument version just removes characters instead of substituting them -->
<xsl:function name="st:tr" as="xs:string">
<xsl:param name="source-string" as="xs:string"/>
<xsl:param name="from-pattern" as="xs:string"/>
<xsl:sequence select="st:tr($source-string, $from-pattern, '')"/>
</xsl:function>
<!-- Helper function that replaces a range with the characters representing that range, e.g. 'a-d' -> 'abcd'
The '-' range divider can be escaped by a backslash, in which case it's treated as just another character,
e.g. 'a\-d' -> 'a', '-', and 'd' -->
<xsl:function name="s-:expand-ranges">
<xsl:param name="from-pattern"/>
<xsl:variable name="range-regex" as="xs:string">[^\\]-.</xsl:variable>
<xsl:variable name="ranges" select="s-:identify-ranges($from-pattern, $range-regex)"/>
<xsl:variable name="codepoints" select="$ranges ! s-:range-to-codepoints(.)"/>
<xsl:sequence select="replace($from-pattern, $range-regex, '') || codepoints-to-string($codepoints)"/>
</xsl:function>
<!-- Returns character ranges found in the input pattern -->
<xsl:function name="s-:identify-ranges">
<xsl:param name="from-pattern"/>
<xsl:param name="range-regex"/>
<xsl:variable name="match-info" select="analyze-string($from-pattern, '(' || $range-regex || ')')"/>
<xsl:sequence select="$match-info/descendant::fn:group ! data(.)"/>
</xsl:function>
<!-- Converts an a-z style range into codepoints so it can be converted to an XPath 3.0 range -->
<xsl:function name="s-:range-to-codepoints">
<xsl:param name="range"/>
<xsl:variable name="min-max-codepoints" select="s-:min-and-max-range($range) ! string-to-codepoints(.)"/>
<xsl:sequence select="$min-max-codepoints[1] to $min-max-codepoints[2]"/>
</xsl:function>
<!-- get the start and end of a range -->
<xsl:function name="s-:min-and-max-range" as="xs:string*">
<xsl:param name="range"/>
<xsl:sequence select="(1, 3) ! substring($range, ., 1)"/>
</xsl:function>
<!-- Handle negated translation strings, e.g., '^0-9' meaning anything that isn't a number.
The '^' negation character can be escaped by a backslash, in which case it's treated like a normal character. -->
<xsl:function name="s-:invert-tr-string" as="xs:string">
<xsl:param name="from-pattern" as="xs:string"/>
<xsl:param name="source-string" as="xs:string"/>
<xsl:choose>
<xsl:when test="starts-with($from-pattern, '^')">
<xsl:sequence select="translate($source-string, st:substr($from-pattern, 2, -1), '')"/>
</xsl:when>
<xsl:when test="starts-with($from-pattern, '\^')">
<xsl:sequence select="st:substr($from-pattern, 2, -1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$from-pattern"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="st:padding" as="xs:string">
<xsl:param name="string" as="xs:string?"/>
<xsl:param name="length" as="xs:numeric"/>
<xsl:sequence
select="
if ($length le string-length($string)) then
substring($string, 1, $length)
else
st:padding($string || $string, $length)"
/>
</xsl:function>
<xsl:function name="st:spaces" as="xs:string">
<xsl:param name="length" as="xs:integer"/>
<xsl:sequence select="st:padding($st:spaces, $length)"/>
</xsl:function>
<xsl:function name="st:pad-to" as="xs:string">
<xsl:param name="string"/>
<xsl:param name="field-size" as="xs:integer"/>
<xsl:sequence select="st:pad-right($string, $field-size, $st:spaces)"/>
</xsl:function>
<xsl:function name="st:pad-right" as="xs:string">
<xsl:param name="string" as="xs:string?"/>
<xsl:param name="field-size" as="xs:integer"/>
<xsl:param name="padding-string" as="xs:string"/>
<xsl:sequence select="substring($string || $padding-string, 1, $field-size)"/>
</xsl:function>
<xsl:function name="st:pad-left" as="xs:string">
<xsl:param name="string" as="xs:string?"/>
<xsl:param name="field-size" as="xs:integer"/>
<xsl:param name="padding-string" as="xs:string"/>
<xsl:variable name="string-length" select="string-length($string)"/>
<xsl:sequence select="st:substr($padding-string || $string, 0 - $field-size, -1)"/>
</xsl:function>
<xsl:function name="st:pad-number">
<xsl:param name="value"/>
<xsl:param name="field-size"/>
<xsl:variable name="string" select="string($value)"/>
<xsl:sequence select="st:pad-left($string, $field-size, $st:zeroes)"/>
</xsl:function>
<xsl:function name="st:pad-decimal">
<xsl:param name="value"/>
<xsl:param name="field-size"/>
<xsl:variable name="string" select="string($value)"/>
<xsl:sequence select="st:pad-right($string, $field-size, $st:zeroes)"/>
</xsl:function>
<xsl:function name="st:char-seq" as="xs:string*">
<xsl:param name="string" as="xs:string?"/>
<xsl:sequence select="string-to-codepoints($string) ! codepoints-to-string(.)" />
</xsl:function>
</xsl:package>
(2-2/6)