我必须从csv文件中读取并通过xslt生成格式化的对象。我面临两天的问题是,我必须计算行,当一个新值出现在一行时,我必须再次重置为1。
600, A, B, C , D
600, A, B, G, F
600, A, B, E, H
601, A, B, I, K
我的输出现在是这样的
<Object:<path:A/600/1>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
<Object:<path:A/600/2>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
<Object:<path:A/600/3>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
<Object:<path:A/601/4>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
但是我期望这个
<Object:<path:A/600/1>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
<Object:<path:A/600/2>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
<Object:<path:A/600/3>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
<Object:<path:A/601/1>><Data:<ZoneStart:B><ZoneFinish:C><Id:D>>>
在XSLT 1.0中创建计数部分并重新设置它简直要了我的命。需要帮助。
XSLT是一种声明性函数式语言。只要你从过程的角度考虑增加和清除计数器,你就会与语言作斗争,而不是使用它。即使你赢得了战斗(这种情况时有发生),结果也不会很好。
用更声明性的语言重新表述你的明显需求,听起来像是:
- 对于每一行输入,生成一行输出,将输入中的各种字段复制到输出中的适当位置。
- 在每一行输出中插入一个数字,特别是数字1加上输入的第一个字段中具有相同值的紧接输入行数。(因此,具有给定值的第一行获得数字1,第二行获得数字2,等等)
您的输出已经满足第一个要求。你的工作是找到一种功能性的、说明性的方式来满足第二种需求。
满足第二个要求的最方便的方法部分取决于当前如何遍历输入行。(如果您的输入确实是非xml数据,如您所示,那么我不太明白您如何在XSLT 1.0中使用它做任何事情;如果您使用的是XSLT 2.0,那么您可能无意中弄错了问题。
假设您正在显示的多行输入是某个名为'line-by- data'的元素的内容,我将在XSLT 1.0中使用如下方式处理它:
<xsl:template match="line-by-line-data">
<xsl:call-template name="handle-lines">
<xsl:with-param name="lines" select="string(.)"/>
</xsl:call-template>
</xsl:template>
模板handle-lines
将是一个递归模板,它截取一行输入,处理它,并递归地调用自己。
如果您正在使用XSLT 1.0并产生您所显示的输出,我猜您已经有了这样的递归模板,只需要下面的提示。在递归调用中添加两个参数:一个是字段1的值,这样可以方便地检查它是否发生了变化;另一个是您已经看到该字段的值的运行计数。即使从纯过程的角度来看,这也应该让人感觉非常舒服:想象一下你在一种语言中,递归是执行迭代的唯一方法。
如果您正在使用XSLT 1.0并通过其他方式产生您所显示的输出,那么请在您的问题中向我们展示这些方式。
祝你好运!