|
<?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>
|