XSLT 逗号分隔数据的问题 [英] Issues with comma separated data with XSLT
问题描述
我正在尝试使用 XSLT 将 XML 数据转换为 CSV.行用逗号分隔,但有些数据有双引号.我使用以下代码进行转换,但它没有正确处理数据,尤其是带引号的行.
Am Trying to convert an XML data into CSV with XSLT. The rows are separated with commas but some of the data have double quotes. i used the following codes for the conversion but it doesn't handle the data properly, especially the rows with quotes.
这是我的样本数据
<Add>
<Rowinfo>
<LocatorD>Dwelling </LocatorD>
<LName> shark </LName>
<L>1</L>
<AArea>Abesinia Passage</AArea>
</Rowinfo>
当 XSL 应用于上面产生的数据时
when the XSL is applied to the above data it produces
LocatorDesignator,LocatorName, Locator , Thoroughfare , AddressArea
Dwelling , shark , 1 , Abesinia Passage,
Shop 01-Feb,Shop , 1 , Casenapes Square , ,
但预期的结果是产生
LocatorDesignator,LocatorName,Locator, Thoroughfare , AddressArea
Dwelling , shark , 1 , Abesinia Passage ,
Shop 01-Feb , Shop , 1 , Casenapes Square ,
换句话说,当您将其作为 CSV 文件打开时
In other words when you open this as a CSV file
- 商店 01-Feb,商店恰好在一个列中
而不是单独的列,例如:
- Shop 01-Feb,Shop happend to be in a single column
instead of seperate columns such as:
定位器指定器|定位器名称
LocatorDesignator| LocatorName
店铺 01-Feb,店铺|
Shop 01-Feb,shop|
代替
LocatorDesignator| LocatorName
Shop 01-Feb | Shop
推荐答案
这个 XSLT 1.0 样式表...
This XSLT 1.0 style-sheet...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="*/Rowinfo[1]/*" mode="heading" />
<xsl:value-of select="'
'" />
<xsl:apply-templates select="*/Rowinfo" />
</xsl:template>
<xsl:template match="Rowinfo/*" mode="heading" >
<xsl:value-of select="local-name()" />
<xsl:if test="position() != last()">
<xsl:value-of select="','" />
</xsl:if>
</xsl:template>
<xsl:template match="Rowinfo">
<xsl:variable name="line-with-extra-comma">
<xsl:for-each select="*">
<xsl:variable name="col-name" select="local-name()" />
<xsl:if test="../../Rowinfo[1]/*[local-name() = $col-name]">
<xsl:call-template name="csv-encode" />
<xsl:value-of select="','" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="concat(
substring($line-with-extra-comma, 1,
string-length($line-with-extra-comma) - 1),
'
')" />
</xsl:template>
<xsl:template name="escape-value">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text,'"')">
<xsl:value-of select="concat( substring-before($text,'"'), '""')" />
<xsl:call-template name="escape-value">
<xsl:with-param name="text" select="substring-after($text,'"')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="csv-encode">
<xsl:choose>
<xsl:when test="contains(.,',') or starts-with(.,'"')">
<xsl:value-of select="'"'" />
<xsl:call-template name="escape-value">
<xsl:with-param name="text" select="text()" />
</xsl:call-template>
<xsl:value-of select="'"'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
...将把这个输入文件...
...will take this input document...
<Address>
<Rowinfo>
<LocatorDesignator>Dwelling </LocatorDesignator>
<LocatorName> shark </LocatorName>
<Locator>1</Locator>
<AddressArea>Abesinia Passage</AddressArea>
</Rowinfo>
<Rowinfo>
<LocatorDesignator>"Shop 01-Feb</LocatorDesignator>
<LocatorName>"Shop</LocatorName>
<Locator>1</Locator>
<Thoroughfare>Casenapes Square</Thoroughfare>
<AddressArea/>
</Rowinfo>
</Address>
...并将其转换为这个 csv 输出...
...and transform it into this csv output...
LocatorDesignator,LocatorName,Locator,AddressArea
Dwelling , shark ,1,Abesinia Passage
"""Shop 01-Feb","""Shop",1,
注意事项
我假设:
- 列标题由第一行的子元素定义.如果表可能为空(没有行),则需要进行相应调整.
- 按名称排列的元素在后续行中的出现顺序与它们在第一行中的顺序相同.
- 后续行可能包含无关的子元素,但绝不会丢失.多余的元素被删除.
- CSV 输出是正确的 csv 输出.如果值包含逗号或以双引号开头,则使用双引号转义.
- 所有值都是单行的.此脚本不处理多行 csv.
- 输出行终止符是 LF.如果您需要 CR.LF 或其他内容,请相应调整.
这篇关于XSLT 逗号分隔数据的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!