如何使用XSLT 1.0编写CSV解析器?
问题描述:
我需要使用XSLT 1.0创建CSV解析器.我已经尝试了一种递归方法,但是我似乎无法匹配行尾,因此printLine-template的输入始终为空.
I need to make a CSV-parser using XSLT 1.0. I have tried a recursive approach, but I can't seem to match the line endrings, so the input to the printLine-template is always empty.
<xsl:template match="/">
<xsl:call-template name="printLine">
<xsl:with-param name="line">
<xsl:value-of select="substring-before(//csvText, '\n')"/>
</xsl:with-param>
<xsl:with-param name="remaining">
<xsl:value-of select="substring-after(//csvText, '\n')"/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="printLine">
<xsl:param name="line"/>
<xsl:param name="remaining"/>
<xsl:value-of select="$line"/><br />
<xsl:if test="remaining != ''">
<xsl:call-template name="printLine">
<xsl:with-param name="line">
<xsl:value-of select="substring-before($remaining, '\n')"/>
</xsl:with-param>
<xsl:with-param name="remaining">
<xsl:value-of select="substring-after($remaining, '\n')"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
答
我找到了解决方案:
<xsl:variable name="ls"><xsl:text>
</xsl:text></xsl:variable>
<xsl:variable name="fs"><xsl:text> </xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:call-template name="printLine">
<xsl:with-param name="line" select="substring-before(//csvText, $ls)"/>
<xsl:with-param name="remaining" select="substring-after(//csvText, $ls)"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="printLine">
<xsl:param name="line"/>
<xsl:param name="remaining"/>
<xsl:call-template name="printFields">
<xsl:with-param name="line" select="$line"/>
</xsl:call-template>
<xsl:if test="$remaining != ''">
<xsl:call-template name="printLine">
<xsl:with-param name="line" select="substring-before($remaining, $ls)"/>
<xsl:with-param name="remaining" select="substring-after($remaining, $ls)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="printFields">
<xsl:param name="line"/>
<!-- render each line and access each field using the getFieldByIndex-template. Example: -->
<div>
<h3>
<xsl:call-template name="getFieldByIndex">
<xsl:with-param name="index" select="1"/>
<xsl:with-param name="line" select="$line"/>
</xsl:call-template>
</h3>
<p>
<xsl:call-template name="getFieldByIndex">
<xsl:with-param name="index" select="4"/>
<xsl:with-param name="line" select="$line"/>
</xsl:call-template>
</p>
</div>
</xsl:template>
<xsl:template name="getFieldByIndex">
<xsl:param name="index"/>
<xsl:param name="line"/>
<xsl:choose>
<xsl:when test="$index > 0">
<xsl:call-template name="getFieldByIndex">
<xsl:with-param name="index" select="$index -1"/>
<xsl:with-param name="line" select="substring-after($line, $fs)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($line,$fs)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
行和字段分隔符存储在 ls 和 fs 变量中.本示例遍历一个制表符分隔的文件.必须为每种用途自定义 printFields -模板.
The line- and field separators are stored in the ls and fs variables. This example traverses a tab-serparated file. The printFields-template has to be customized for each use.