在 XSLT 代码中从 csv 读取空值而不移动单元格值

Posted

技术标签:

【中文标题】在 XSLT 代码中从 csv 读取空值而不移动单元格值【英文标题】:Reading null values from csv in XSLT code without shifting the cells values 【发布时间】:2021-05-26 17:24:42 【问题描述】:

我有这两行来自 csv 文件

<ROOT>
1,M,40,0,5,0,Personeelsvoorschot,0
2,M,40,0,6,0,Personeelsvoorschot,0
</ROOT>

在 XSLT 代码中,我得到标签中的每个单元格,如下所示(行号、虚拟 1 等),但是当我尝试将任何具有空值的单元格并进行测试时,问题发生了,标签没有得到null ,它获取下一个错误的单元格值,我会感谢你的帮助

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common"extension-element-prefixes="exsl">
<xsl:output method="xml" encoding="UTF-8"  indent="no" byte-order-mark="no"/>
<xsl:strip-space elements="*"/>
<!--<xsl:preserve-space elements="*"/>-->
<xsl:template match="@*|node()">
    <xsl:copy >
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:key name="k1" match="row" use="cell[0]"/>
<xsl:key name="k2" match="row" use="concat(cell[1], '|', cell[3])"/>
<xsl:template match="/">
    <xsl:element name="ProcessSalaryJournals">
            <xsl:variable name="rows">
                <xsl:call-template name="tokenize">
                    <xsl:with-param name="text" select="ProcessADPMultilinkSalaryJournalUpload/DataArea/ADPMultilinkSalaryJournalUpload/ADPMultilinkSalaryJournalUploaddocument/ROOT"/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="data">
                <xsl:for-each select="exsl:node-set($rows)/row[position() > 0]">
                    <row>
                        <xsl:call-template name="tokenize">
                            <xsl:with-param name="text" select="."/>
                            <xsl:with-param name="delimiter" select="','"/>
                            <xsl:with-param name="name" select="'cell'"/>
                        </xsl:call-template>
                    </row>
                </xsl:for-each>
            </xsl:variable>
            <!-- output -->
            <SalaryJournals>
            <xsl:for-each select="exsl:node-set($data)/row[count(. | key('k1', cell[1])[1]) = 1]">
                    <SalaryJournal>
                        <LineNumber>
                            <xsl:value-of select="cell[1]"/>
                        </LineNumber>
                        <Dummy1>
                            <xsl:value-of select="cell[2] " />
                        </Dummy1>
                        <Dummy2>
                            <xsl:value-of select="cell[3] " />
                        </Dummy2>
                        <Dummy3>
                            <xsl:value-of select="cell[4] " />
                        </Dummy3>
                        <Dummy4>
                            <xsl:value-of select="cell[5] " />
                        </Dummy4>
                        <Dummy5>
                            <xsl:value-of select="cell[6] " />
                        </Dummy5>
                        <VoucherText>
                            <xsl:value-of select="cell[7] " />
                        </VoucherText>
                        <AccountingDate>
                            <xsl:value-of select="cell[8] " />
                        </AccountingDate>
                    </SalaryJournal>
                </xsl:for-each>
            </SalaryJournals>
        </xsl:element>
        <xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="delimiter" select="'&#10;'"/>
    <xsl:param name="name" select="'row'"/>
    <xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
    <xsl:if test="$token">
        <xsl:element name="$name">
            <xsl:value-of select="$token"/>
        </xsl:element>
    </xsl:if>
    <xsl:if test="contains($text, $delimiter)">
        <!-- recursive call -->
        <xsl:call-template name="tokenize">
            <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
            <xsl:with-param name="delimiter" select="$delimiter"/>
            <xsl:with-param name="name" select="$name"/>
        </xsl:call-template>
    </xsl:if>
   </xsl:template>
 </xsl:stylesheet>

【问题讨论】:

输入数据如何准确地查找“null”值?为什么 XSLT 有 version="2.0" 却使用非常 XSLT 1.0 的习语,如 Muenchian 分组和命名模板来标记化,尽管 XSLT 2.0 有 for-each-grouptokenize 函数? 数据将类似于 1,M,,0,5,,Personelsvoorschot,0 而不是 1,M,40,0,5,0,Personelsvoorschot,0 您使用 XSLT 2.0 处理器吗? 我认为xsl:if test="$token" 需要删除 是的,当我删除 xsl:if test="$token" 谢谢 :) 【参考方案1】:

如果用于标记化的模板需要找到空字符串标记,例如1,M,,0,5,,Personeelsvoorschot,0 中两个逗号之间的空字符串,我认为需要删除 xsl:if test="$token"

【讨论】:

以上是关于在 XSLT 代码中从 csv 读取空值而不移动单元格值的主要内容,如果未能解决你的问题,请参考以下文章

在JavaScript / jQuery中从列中获取所有值而不重复

在用户输入值而不覆盖以前的值后,如何写入 .csv 文件的下一行?

有没有办法使用 read.csv 从字符串值而不是 R 中的文件读取?

Python 3:检查迭代器的下一个值而不进行迭代

在 java spark 中从 REST API 读取 csv

Apache Spark (PySpark) 在读取 CSV 时处理空值