如果标签不存在,XSLT 处理 CSV 的空单元格

Posted

技术标签:

【中文标题】如果标签不存在,XSLT 处理 CSV 的空单元格【英文标题】:XSLT Handle empty cells for CSV if the tag does not exist 【发布时间】:2020-07-13 17:52:09 【问题描述】:

我已经尝试了很长时间,但我找不到捷径解决方案: 我想使用 XSLT 从 XML 生成 CSV 输出,CSV 包含特定的标题,如果存在,我想输出与标题相关的标签,并输出“,”作为空单元格的 CSV 分隔符当标签不存在时。

示例: XML 输入

<rootElm>
   <entry>
      <col1>text</col1>
      <col2>text</col2>
      <col3>text</col3>
      <colX>text</colX>
   </entry>
   <entry>
      <col1>text</col1>
      <col3>text</col3>
      <colX>text</colX>
   </entry>
   <entry>
      <col1>text</col1>
      <col2>text</col2>
      <colX>text</colX>
   </entry>
</rootElm>

XSL:

<xsl:template match="entry">
    <xsl:choose>
        <xsl:when test="col1">
            <xsl:apply-templates select="col1"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text> ,</xsl:text> <!-- comma separator to output empty cell if tag not exist -->
        </xsl:otherwise>
    </xsl:choose>

        <xsl:when test="col2">
            <xsl:apply-templates select="col2"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text> ,</xsl:text>
        </xsl:otherwise>
    </xsl:choose>

        <xsl:when test="col3">
            <xsl:apply-templates select="col3"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text> ,</xsl:text> 
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

上面的代码运行良好并生成了想要的结果,但我试图找到一个更简单的解决方案,例如遍历想要的标题名称(col1,col2,col3)并检查具有指定名称的标签是否存在于“entry”元素,然后在其上应用模板,否则打印 CSV 分隔符“,”。这可以使用 XSLT 实现吗?

CSV 输出:

text,text,text
text,,text //col2 doesn't exist for the second entry
text,text, //col3 doesn't exist for the third entry

【问题讨论】:

请始终指定您的处理器支持的 XSLT 版本。 @michael.hor257k 完成,xslt-2.0 【参考方案1】:

尝试类似:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>

<xsl:template match="/rootElm">
    <xsl:variable name="col" select="distinct-values(entry/*/name())"/>
    <xsl:for-each select="entry">
        <xsl:variable name="entry" select="."/>
        <xsl:for-each select="$col">
            <xsl:value-of select="$entry/*[name()=current()]"/>
            <xsl:value-of select="if(position()!=last()) then',' else '&#10;'"/>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

演示:https://xsltfiddle.liberty-development.net/naZXVEQ/1


补充:

如何指定我只想显示 col1、col2 和 col3。我不想显示 colX 或任何其他可能存在的列。

只需将$col 变量定义更改为

<xsl:variable name="col" select="('col1', 'col2', 'col3')"/> 

甚至更简单:

<xsl:template match="/rootElm">
    <xsl:for-each select="entry">
        <xsl:value-of select="string(col1), string(col2), string(col3)" separator=","/>
        <xsl:text>&#10;</xsl:text> 
    </xsl:for-each>
</xsl:template>

【讨论】:

这几乎是我正在寻找的,但我如何指定我只想显示 col1、col2 和 col3。我不想显示 colX 或任何其他可能存在的列。 查看我帖子的补充内容。 请注意,根据 W3C 规范,distinct-values() 结果的顺序是未定义的。在撒克逊,distinct-values() 按“首次出现的顺序”提供结果,这可能是这里想要的,但其他处理器可能会提供“随机”顺序。

以上是关于如果标签不存在,XSLT 处理 CSV 的空单元格的主要内容,如果未能解决你的问题,请参考以下文章

tableView + CoreData 上的空单元格

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

处理 VBA 中的空单元格以进行访问

XSLT可通过工作表单击的单元格单元格

保留空间的空电子表格[关闭]

Excel PowerQuery:数字列中的空值