使用 XSLT 将 XML 转换为 CSV
Posted
技术标签:
【中文标题】使用 XSLT 将 XML 转换为 CSV【英文标题】:XML to CSV transformation using XSLT 【发布时间】:2021-07-20 17:47:20 【问题描述】:我正在尝试将我的 xml 输入转换为 csv 输出,详情如下
输入文件:
<Customer>
<item>
<CustomerID>100000069</CustomerID>
<CustomerGroup>EX</CustomerGroup>
<CustomerName>Test Mehmet</CustomerName>
<CustomerStreet>Street</CustomerStreet>
<HouseNumber>123</HouseNumber>
<CustomerCity>Ismaning</CustomerCity>
<CustomerZip></CustomerZip>
<CustomerCountry>DE</CustomerCountry>
</item>
</Customer>
XSL:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name='newline'>
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:template match="/Customer">
<xsl:value-of select="concat('"CustomerID";"CustomerGroup";"CustomerName";"CustomerStreet";"HouseNumber";"CustomerCity";"CustomerZIP";"CustomerCountry"',$newline)"/>
<xsl:for-each select="./item">
<xsl:value-of select="concat('"',./CustomerID,'";"',./CustomerGroup,'";"',./CustomerName,'";"',./CustomerStreet,'";"',./HouseNumber,'";"',./CustomerCity,'";"',./CustomerZIP,'";"',./CustomerCountry,'"',$newline)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我的原始输出:
"CustomerID";"CustomerGroup";"CustomerName";"CustomerStreet";"HouseNumber";"CustomerCity";"CustomerZIP";"CustomerCountry" "100000069";"EX";"Test Mehmet";"Street";"123";"Ismaning";"";"DE"
预期输出:
我需要将所有空值更改为“null”。以下是我的预期输出。
"CustomerID";"CustomerGroup";"CustomerName";"CustomerStreet";"HouseNumber";"CustomerCity";"CustomerZIP";"CustomerCountry" "100000069";"EX";"Test Mehmet";"Street";"123";"Ismaning";null;"DE"
请建议对我的代码进行额外的更改,以便它会在“”出现的任何地方填充 null。
【问题讨论】:
【参考方案1】:假设您仅限于 XSLT 1.0,我建议您这样做:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/Customer">
<!-- header row -->
<xsl:text>"CustomerID";"CustomerGroup";"CustomerName";"CustomerStreet";"HouseNumber";"CustomerCity";"CustomerZIP";"CustomerCountry" </xsl:text>
<!-- data rows -->
<xsl:for-each select="item">
<xsl:call-template name="cell">
<xsl:with-param name="data" select="CustomerID"/>
</xsl:call-template>
<xsl:text>;</xsl:text>
<xsl:call-template name="cell">
<xsl:with-param name="data" select="CustomerGroup"/>
</xsl:call-template>
<xsl:text>;</xsl:text>
<xsl:call-template name="cell">
<xsl:with-param name="data" select="CustomerName"/>
</xsl:call-template>
<xsl:text>;</xsl:text>
<xsl:call-template name="cell">
<xsl:with-param name="data" select="CustomerStreet"/>
</xsl:call-template>
<xsl:text>;</xsl:text>
<xsl:call-template name="cell">
<xsl:with-param name="data" select="HouseNumber"/>
</xsl:call-template>
<xsl:text>;</xsl:text>
<xsl:call-template name="cell">
<xsl:with-param name="data" select="CustomerCity"/>
</xsl:call-template>
<xsl:text>;</xsl:text>
<xsl:call-template name="cell">
<xsl:with-param name="data" select="CustomerZip"/>
</xsl:call-template>
<xsl:text>;</xsl:text>
<xsl:call-template name="cell">
<xsl:with-param name="data" select="CustomerCountry"/>
</xsl:call-template>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="cell">
<xsl:param name="data"/>
<xsl:choose>
<xsl:when test="string($data)">
<xsl:text>"</xsl:text>
<xsl:value-of select="$data"/>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>null</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这有点冗长,但它避免了代码重复。
但是,如果您可以确定所有元素将始终以相同的顺序存在,即使有些可能是空的,您也可以将其缩短为:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/Customer">
<!-- header row -->
<xsl:text>"CustomerID";"CustomerGroup";"CustomerName";"CustomerStreet";"HouseNumber";"CustomerCity";"CustomerZIP";"CustomerCountry" </xsl:text>
<!-- data rows -->
<xsl:for-each select="item">
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="string(.)">
<xsl:text>"</xsl:text>
<xsl:value-of select="."/>
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:otherwise>null</xsl:otherwise>
</xsl:choose>
<xsl:if test="position()!=last()">;</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
【讨论】:
以上是关于使用 XSLT 将 XML 转换为 CSV的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python 或 XSLT 将复杂的 XML 转换为 CSV