Diese CsvEscape
Funktion ist XSLT 1.0 und entweicht Spaltenwerte ,
, "
und neue Zeilen wie RFC 4180 oder Excel. Es nutzt die Tatsache, dass Sie XSLT-Vorlagen rekursiv aufrufen können:
- Die Vorlage
EscapeQuotes
ersetzt alle doppelten Anführungszeichen rekursiv ab dem Anfang der Zeichenfolge durch zwei doppelte Anführungszeichen.
- Die Vorlage
CsvEscape
prüft, ob der Text ein Komma oder ein doppeltes Anführungszeichen enthält, und umgibt in diesem Fall die gesamte Zeichenfolge mit zwei doppelten Anführungszeichen und fordert EscapeQuotes
die Zeichenfolge auf.
Anwendungsbeispiel: xsltproc xmltocsv.xslt file.xml > file.csv
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template name="EscapeQuotes">
<xsl:param name="value"/>
<xsl:choose>
<xsl:when test="contains($value,'"')">
<xsl:value-of select="substring-before($value,'"')"/>
<xsl:text>""</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="substring-after($value,'"')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="CsvEscape">
<xsl:param name="value"/>
<xsl:choose>
<xsl:when test="contains($value,',')">
<xsl:text>"</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test="contains($value,'
')">
<xsl:text>"</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test="contains($value,'"')">
<xsl:text>"</xsl:text>
<xsl:call-template name="EscapeQuotes">
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:text>project,name,language,owner,state,startDate</xsl:text>
<xsl:text>
</xsl:text>
<xsl:for-each select="projects/project">
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(name)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(language)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(owner)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(state)"/></xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="CsvEscape"><xsl:with-param name="value" select="normalize-space(startDate)"/></xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>