-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCSVtoXML.xslt
125 lines (119 loc) · 6.17 KB
/
CSVtoXML.xslt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="fn"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="xs fn">
<!-- This stylesheet orginates with work by Andrew J Welch
See http://andrewjwelch.com/code/xslt/csv/csv-to-xml_v2.html
Changes by Keith W. Boone
* Turned main template into a function
* Enabled element naming derived from first row
* Enabled renaming of wrapper elements
-->
<xsl:output indent="yes" encoding="US-ASCII"/>
<!--xsl:template name="main" match="/">
<xsl:call-template name="getSheetAsXML">
<xsl:with-param name="names" select="('results', 'result')"/>
<xsl:with-param name="attribute">value</xsl:with-param>
<xsl:with-param name="useFieldNames" select="true()"/>
<xsl:with-param name="pathToCSV"
>TheCovidTrackingProjectDataTo2020-04-07.csv</xsl:with-param>
</xsl:call-template>
</xsl:template -->
<xsl:function name="fn:getTokens" as="xs:string+">
<xsl:param name="str" as="xs:string"/>
<xsl:analyze-string select="concat(translate($str, '
', ''), ',')"
regex='(("[^"]*")+|[^,]*),'>
<xsl:matching-substring>
<xsl:sequence select='replace(regex-group(1), "^""|""$|("")""", "$1")'/>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:function>
<xsl:function name="fn:getSheetAsXML">
<xsl:param name="pathToCSV"/>
<xsl:value-of select="fn:getSheetAsXML($pathToCSV, true(), false(), ('root', 'row'))"/>
</xsl:function>
<xsl:template name="fn:getSheetAsXML">
<xsl:param name="pathToCSV"/>
<xsl:param name="useFieldNames" select="true()"/>
<xsl:value-of
select="fn:getSheetAsXML($pathToCSV, $useFieldNames, false(), ('root', 'row'))"/>
</xsl:template>
<xsl:template name="getSheetAsXML">
<xsl:param name="pathToCSV"/>
<xsl:param name="useFieldNames"/>
<xsl:param name="attribute"/>
<xsl:param name="names"/>
<xsl:param name="omitEmpty" select="true()"/>
<xsl:choose>
<xsl:when test="unparsed-text-available($pathToCSV)">
<xsl:variable name="csv" select="unparsed-text($pathToCSV)"/>
<xsl:variable name="lines" select="tokenize($csv, '
')" as="xs:string+"/>
<xsl:variable name="elemNames" select="fn:getTokens($lines[1])" as="xs:string+"/>
<xsl:element name="{$names[1]}">
<xsl:for-each select="$lines[position() > 1]">
<xsl:variable name="lineItems" select="fn:getTokens(.)" as="xs:string+"/>
<xsl:if test="string-length(string-join(.,'')) != 0 or not($omitEmpty)">
<xsl:element name="{$names[2]}">
<xsl:for-each select="$elemNames">
<xsl:variable name="pos" select="position()"/>
<xsl:variable name="elemName"
select="
if ($useFieldNames) then
.
else
'elem'"/>
<xsl:if
test="string-length($lineItems[$pos]) != 0 or not($omitEmpty)">
<xsl:element name="{$elemName}">
<xsl:if test="not($useFieldNames)">
<xsl:attribute name="name" select="."/>
</xsl:if>
<xsl:choose>
<xsl:when test="$attribute">
<xsl:attribute name="{$attribute}"
select="$lineItems[$pos]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$lineItems[$pos]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:text>Cannot locate : </xsl:text>
<xsl:value-of select="$pathToCSV"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:function name="fn:getSheetAsXML">
<xsl:param name="pathToCSV"/>
<xsl:param name="useFieldNames"/>
<xsl:param name="attribute"/>
<xsl:param name="names"/>
<xsl:call-template name="getSheetAsXML">
<xsl:with-param name="pathToCSV" select="$pathToCSV"/>
<xsl:with-param name="useFieldNames" select="$useFieldNames"/>
<xsl:with-param name="attribute" select="$attribute"/>
<xsl:with-param name="names" select="$names"/>
</xsl:call-template>
</xsl:function>
<xsl:function name="fn:getSheet">
<xsl:param name="sheet"/>
<xsl:param name="cv"/>
<xsl:copy-of select="if ( ends-with($sheet, '.csv')) then (fn:loadCSV($sheet,$cv)) else document($sheet,$cv)"/>
</xsl:function>
<xsl:function name="fn:loadCSV">
<xsl:param name="sheet"/>
<xsl:param name="cv"/>
<xsl:call-template name="getSheetAsXML">
<xsl:with-param name="names" select="('results', 'result')"/>
<xsl:with-param name="attribute">value</xsl:with-param>
<xsl:with-param name="useFieldNames" select="true()"/>
<xsl:with-param name="pathToCSV" select="$sheet" />
</xsl:call-template>
</xsl:function>
</xsl:stylesheet>