我希望借助XSLT1.0将输入xml转换为csv输出。下面是我的输入格式。
<input>
<add add-value="First Name">
<value type="string">New</value>
</add>
<add add-value="Surname">
<value type="string">user1</value>
</add>
<add add-value="Title">
<value type="string">engineer</value>
</add>
<add add-value="Description">
<value type="string">New joinee.</value>
</add>
<add .....
</add>
</input>输出csv由固定数量的列组成,我通过xslt中的变量提供这些列。
下面是我的:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="http://exslt.org/common" >
<xsl:variable name="delimiter" select="','"/>
<xsl:template match="input/add">
<xsl:variable name="SplitWordsSet">
<xsl:call-template name="split">
<xsl:with-param name="pText" select="'First name,Surname,Phone number,Description,Title'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vSplitWords" select="ext:node-set($SplitWordsSet)/*"/>
<xsl:call-template name="counter">
<xsl:with-param name="split-words" select="$vSplitWords"/>
<xsl:with-param name="count"select="1"/>
</xsl:call-template>
</xsl:template>
<!-- Below templtate splits the pText values -->
<xsl:template name="split">
<xsl:param name="pText"/>
<xsl:param name="pElemName" select="'word'"/>
<xsl:variable name="first" select="substring-before(concat($pText,','),',')"/>
<xsl:variable name="remaining" select="substring-after($pText,',')"/>
<xsl:element name="{$pElemName}">
<xsl:value-of select="$first"/>
</xsl:element>
<xsl:choose>
<xsl:when test="$remaining">
<xsl:call-template name="split">
<xsl:with-param name="pText" select="$remaining"/>
<xsl:with-param name="pElemName" select="$pElemName"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- below is recursive template to maintain count of columns values -->
<xsl:template name="counter">
<xsl:param name="count" select="1"/>
<xsl:param name="split-words"/>
<xsl:variable name="split-word" select="$split-words[$count]"/>
<xsl:if test="$count < 6">
<xsl:call-template name="output-csv">
<xsl:with-param name="field-value" select="*[(@add-value = '$split-word')]/value"/>
</xsl:call-template>
<xsl:value-of select="$delimiter"/>
<xsl:call-template name="counter">
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="output-csv">
<xsl:param name="field-value"/>
<xsl:value-of select="$field-value"/>
</xsl:template>
</xsl:stylesheet>我感兴趣的增值属性被传递为pText param.These值是我在输出csv中的列。
我的预期产出:
First name,Surname,Phone number,Description,Title
New,User1,,New joinee,engineer但是我无法得到想要的输出,我只得到逗号的,,,,,,请有人指出我哪里出错了。
发布于 2013-07-29 07:58:15
XSLT中存在一些问题。首先,使用初始模板匹配,您将在添加元素上进行匹配,但是由于它是一个输入元素,表示CSV文件中的一行,因此您可能希望匹配该元素。
<xsl:template match="input">然后,当您调用output-csv模板时,您应该查找带有当前单词的corrent 附加值属性的add元素。
<xsl:call-template name="output-csv">
<xsl:with-param name="field-value" select="add[@add-value = $split-word]/value"/>
</xsl:call-template>但是,您的主要问题是如何递归地调用计数器模板。这里没有重新设置拆分词属性,因此在第二个调用中,参数将为空。
<xsl:call-template name="counter">
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>(也值得指出的是,在XML中,第一个属性是‘Name',但在XSLT中的列名列表中,它是’name‘。XSLT中的字符串比较是有案例感觉的)。
您可以在这里设置参数,但将拆分单词列表作为全局变量可能更好(当然更有效),而不是为每个输入元素拆分它们。
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="urn:schemas-microsoft-com:xslt" >
<xsl:variable name="delimiter" select="','"/>
<xsl:variable name="SplitWordsSet">
<xsl:call-template name="split">
<xsl:with-param name="pText" select="'First name,Surname,Phone number,Description,Title'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vSplitWords" select="ext:node-set($SplitWordsSet)/*"/>
<xsl:template match="input">
<xsl:call-template name="counter">
<xsl:with-param name="count" select="1"/>
</xsl:call-template>
</xsl:template>
<!-- Below templtate splits the pText values -->
<xsl:template name="split">
<xsl:param name="pText"/>
<xsl:param name="pElemName" select="'word'"/>
<xsl:variable name="first" select="substring-before(concat($pText,','),',')"/>
<xsl:variable name="remaining" select="substring-after($pText,',')"/>
<xsl:element name="{$pElemName}">
<xsl:value-of select="$first"/>
</xsl:element>
<xsl:choose>
<xsl:when test="$remaining">
<xsl:call-template name="split">
<xsl:with-param name="pText" select="$remaining"/>
<xsl:with-param name="pElemName" select="$pElemName"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- below is recursive template to maintain count of columns values -->
<xsl:template name="counter">
<xsl:param name="count" select="1"/>
<xsl:param name="split-words"/>
<xsl:variable name="split-word" select="$vSplitWords[$count]"/>
<xsl:call-template name="output-csv">
<xsl:with-param name="field-value" select="add[@add-value = $split-word]/value"/>
</xsl:call-template>
<xsl:if test="$count < 5">
<xsl:value-of select="$delimiter"/>
<xsl:call-template name="counter">
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="output-csv">
<xsl:param name="field-value"/>
<xsl:value-of select="$field-value"/>
</xsl:template>
</xsl:stylesheet>这应该会给你输出
New,user1,,New joinee.,engineer但是,您可以采用另一种方法,而不必使用递归模板。具有与拆分的word元素相匹配的模板,将当前的输入作为参数传入
<xsl:template match="word">
<xsl:param name="input" />
<xsl:if test="position() > 1">
<xsl:value-of select="$delimiter"/>
</xsl:if>
<xsl:value-of select="$input/add[@add-value = current()]/value" />
</xsl:template>然后,每一行都可以输出如下
<xsl:apply-templates select="$vSplitWords">
<xsl:with-param name="input" select="." />
</xsl:apply-templates>也试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="urn:schemas-microsoft-com:xslt" >
<xsl:variable name="delimiter" select="','"/>
<xsl:variable name="SplitWordsSet">
<xsl:call-template name="split">
<xsl:with-param name="pText" select="'First name,Surname,Phone number,Description,Title'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vSplitWords" select="ext:node-set($SplitWordsSet)/*"/>
<xsl:template match="input">
<xsl:apply-templates select="$vSplitWords">
<xsl:with-param name="input" select="." />
</xsl:apply-templates>
</xsl:template>
<!-- Below templtate splits the pText values -->
<xsl:template name="split">
<xsl:param name="pText"/>
<xsl:param name="pElemName" select="'word'"/>
<xsl:variable name="first" select="substring-before(concat($pText,','),',')"/>
<xsl:variable name="remaining" select="substring-after($pText,',')"/>
<xsl:element name="{$pElemName}">
<xsl:value-of select="$first"/>
</xsl:element>
<xsl:choose>
<xsl:when test="$remaining">
<xsl:call-template name="split">
<xsl:with-param name="pText" select="$remaining"/>
<xsl:with-param name="pElemName" select="$pElemName"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="word">
<xsl:param name="input" />
<xsl:if test="position() > 1">
<xsl:value-of select="$delimiter"/>
</xsl:if>
<xsl:value-of select="$input/add[@add-value = current()]/value" />
</xsl:template>
</xsl:stylesheet>https://stackoverflow.com/questions/17917872
复制相似问题