如果标签不存在,则 XSLT 处理 CSV 的空单元格
XSLT Handle empty cells for CSV if the tag does not exist
我已经尝试了很长时间,但找不到捷径:
我想使用 XSLT 从 XML 生成 CSV 输出,CSV 包含特定的 headers,如果存在,我想输出与 headers 相关的标签, 并在标签不存在时输出“,”作为空单元格的 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>
上面的代码运行良好并生成了想要的结果,但我试图找到一个更简单的解决方案,例如循环遍历想要的 header 名称(col1,col2,col3)并检查标签是否带有指定名称存在于 "entry" 元素下,然后在其上存在 apply-templates,否则打印 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 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 ' '"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
演示:https://xsltfiddle.liberty-development.net/naZXVEQ/1
已添加:
how can I specify that I want to display only col1, col2, and col3. That I don't want to display colX or any other columns that could be existed.
只需将 $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> </xsl:text>
</xsl:for-each>
</xsl:template>
我已经尝试了很长时间,但找不到捷径: 我想使用 XSLT 从 XML 生成 CSV 输出,CSV 包含特定的 headers,如果存在,我想输出与 headers 相关的标签, 并在标签不存在时输出“,”作为空单元格的 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>
上面的代码运行良好并生成了想要的结果,但我试图找到一个更简单的解决方案,例如循环遍历想要的 header 名称(col1,col2,col3)并检查标签是否带有指定名称存在于 "entry" 元素下,然后在其上存在 apply-templates,否则打印 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 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 ' '"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
演示:https://xsltfiddle.liberty-development.net/naZXVEQ/1
已添加:
how can I specify that I want to display only col1, col2, and col3. That I don't want to display colX or any other columns that could be existed.
只需将 $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> </xsl:text>
</xsl:for-each>
</xsl:template>