|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<xsl:package name="csv-xsl-package" package-version="1.0.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:csv="http://www.loreal.com/hip/fwk/xsl/csv" exclude-result-prefixes="xs csv" declared-modes="yes" version="3.0">
|
|
<!--* Mode declarations ... *-->
|
|
<xsl:mode name="csv:parse-line" visibility="public"/>
|
|
<xsl:mode name="csv:parse-line_new" visibility="public"/>
|
|
<xsl:mode name="csv:parse-field" on-no-match="shallow-copy" visibility="public"/>
|
|
<xsl:mode name="csv:post-process" on-no-match="shallow-copy" visibility="public"/>
|
|
|
|
|
|
<!--* Variable declarations ... *-->
|
|
<xsl:variable name="csv:line-separator" as="xs:string" select="'\r\n?|\n\r?'" visibility="public"/>
|
|
<xsl:variable name="csv:field-separator" as="xs:string" select="','" visibility="public"/>
|
|
<xsl:variable name="csv:quote" as="xs:string" select="'"'" visibility="public" />
|
|
<xsl:variable name="csv:validated-quote" visibility="private"
|
|
as="xs:string"
|
|
select="
|
|
if (string-length($csv:quote) ne 1)
|
|
then error(xs:QName('csv:ERR001'),
|
|
'Incorrect length for $csv:quote, should be 1')
|
|
else $csv:quote" />
|
|
|
|
|
|
|
|
<!--* Attribute-set declaration ... *-->
|
|
<xsl:attribute-set name="csv:field-attributes"
|
|
visibility="public">
|
|
<xsl:attribute name="quoted"
|
|
select="if (starts-with(., $csv:validated-quote))
|
|
then 'yes'
|
|
else 'no'" />
|
|
<xsl:attribute name="type"
|
|
select="if (. castable as xs:decimal)
|
|
then 'decimal'
|
|
else 'string'" />
|
|
</xsl:attribute-set>
|
|
|
|
|
|
<!--* Function declarations ... *-->
|
|
|
|
<!-- [csv:parse] -->
|
|
<xsl:function name="csv:parse" visibility="final">
|
|
<xsl:param name="input" as="xs:string"/>
|
|
<xsl:variable name="result" as="element()">
|
|
<csv>
|
|
<xsl:apply-templates select="(tokenize($input, $csv:line-separator)
|
|
! csv:preprocess-line(.))" mode="csv:parse-line"/>
|
|
</csv>
|
|
</xsl:variable>
|
|
<xsl:apply-templates select="$result" mode="csv:post-process"/>
|
|
</xsl:function>
|
|
|
|
<!-- [csv:parse_new] -->
|
|
<xsl:function name="csv:parse" visibility="final">
|
|
<xsl:param name="input" as="xs:string" />
|
|
<xsl:param name="line-separator" as="xs:string" />
|
|
<xsl:param name="field-separator" as="xs:string" />
|
|
<xsl:variable name="result" as="element()">
|
|
<csv>
|
|
<xsl:apply-templates
|
|
select="(tokenize($input, $line-separator)
|
|
! csv:preprocess-line(.))"
|
|
mode="csv:parse-line_new">
|
|
<xsl:with-param name="field-separator_var" select="$field-separator" />
|
|
</xsl:apply-templates>
|
|
</csv>
|
|
</xsl:variable>
|
|
<xsl:apply-templates select="$result" mode="csv:post-process" />
|
|
</xsl:function>
|
|
|
|
|
|
<!-- [csv:preprocess-line] -->
|
|
<xsl:function name="csv:preprocess-line" as="xs:string?"
|
|
visibility="public">
|
|
<xsl:param name="line" as="xs:string" />
|
|
<xsl:sequence
|
|
select="if (string-length(normalize-space($line)) > 0)
|
|
then replace(replace($line,'\s+$',''),'^\s+','')
|
|
else ()" />
|
|
</xsl:function>
|
|
|
|
<!-- [csv:preprocess-field] -->
|
|
<xsl:function name="csv:preprocess-field" as="xs:string">
|
|
<xsl:param name="field" as="xs:string" />
|
|
<xsl:sequence select="$field" />
|
|
</xsl:function>
|
|
|
|
|
|
|
|
<!--* Templates ... *-->
|
|
|
|
<!-- [csv:parse-line] -->
|
|
<xsl:template match="." mode="csv:parse-line">
|
|
<row>
|
|
<xsl:apply-templates select="tokenize(., $csv:field-separator)"
|
|
mode="csv:parse-field" />
|
|
</row>
|
|
</xsl:template>
|
|
|
|
<!-- [csv:parse-line_new] -->
|
|
<xsl:template match="." mode="csv:parse-line_new">
|
|
<xsl:param name="field-separator_var" />
|
|
<row>
|
|
<xsl:variable name="regex" select="'((?<=' || $field-separator_var || ')' || $csv:validated-quote || '.*?' || $csv:validated-quote || '(?=' || $field-separator_var || ')|(?<=' || $field-separator_var || ')$|^(?=' || $field-separator_var || ')|^' || $csv:validated-quote || '.*?' || $csv:validated-quote || '(?=' || $field-separator_var || ')|(?<=' || $field-separator_var || ')' || $csv:validated-quote || '.*?' || $csv:validated-quote || '$|(?<=' || $field-separator_var || ')[^' || $field-separator_var || ']*?(?=' || $field-separator_var || ')|^[^' || $field-separator_var || ']+(?=' || $field-separator_var || ')|(?<=' || $field-separator_var || ')[^' || $field-separator_var || ']+$|^[^' || $field-separator_var || ']*$)'">
|
|
</xsl:variable>
|
|
<xsl:analyze-string regex="{$regex}"
|
|
select="." flags=";j">
|
|
<xsl:matching-substring>
|
|
<xsl:apply-templates select="regex-group(1)" mode="csv:parse-field"/>
|
|
</xsl:matching-substring>
|
|
</xsl:analyze-string>
|
|
</row>
|
|
</xsl:template>
|
|
|
|
<!-- [csv:parse-field] -->
|
|
<xsl:template match="." mode="csv:parse-field" expand-text="yes">
|
|
<xsl:variable name="string-body-pattern" as="xs:string" select="'([^' || $csv:validated-quote || ']*)'"/>
|
|
<xsl:variable name="quoted-value" as="xs:string" select="$csv:validated-quote
|
|
|| $string-body-pattern
|
|
|| $csv:validated-quote"/>
|
|
<xsl:variable name="unquoted-value" as="xs:string" select="'(.+)'"/>
|
|
<field xsl:use-attribute-sets="csv:field-attributes">{
|
|
csv:preprocess-field(
|
|
replace(.,
|
|
$quoted-value || '|' || $unquoted-value,
|
|
'$1$2'))
|
|
}</field>
|
|
</xsl:template>
|
|
|
|
</xsl:package>
|