我正在使用XSL从XML生成CSV文件。 XML包含带有子元素标签的Main元素,而这些元素又包含不同数量的子元素Tag。 XML的一部分例如如下所示:
<Main>
<Tags>
<Tag>tag1</Tag>
<Tag>tag2</Tag>
<Tag>tag3</Tag>
</Tags>
</Main>
<Main>
<Tags>
<Tag>tag1</Tag>
<Tag>tag2</Tag>
<Tag>tag3</Tag>
<Tag>tag4</Tag>
<Tag>tag5</Tag>
<Tag>tag6</Tag>
</Tags>
</Main>
在XSL中,每个循环都有一个遍历XML文件的所有主要元素的循环。我想打印所有Tag元素的值。我在主循环内的另一个for-each循环中执行此操作。但是,我总是希望迭代10次,无论Tag元素的数量。当我超过可打印标签的数量时,我想在每个剩余的迭代中打印一些文本。
这是我之后的输出:
tag1,tag2,tag3,1,1,1,1,1,1,1,
tag1,tag2,tag3,tag4,tag5,tag6,1,1,1,1,
在每个循环的Tag之后,我正在调用一个模板,提供一个变量,其中包含Tag中的Tag。然后,我希望模板以递归方式调用自身,直到它为当前Main元素的Tag元素完成了不同数量的剩余迭代。标签元素的数量随每次主要迭代而变化,我怀疑这是当前解决方案中的问题(这导致我的转换软件,带有XML工具的Notepad ++崩溃):
<xsl:template match="/">
<xsl:for-each select="Main">
<xsl:for-each select="Tags/Tag">
<xsl:value-of select="Tag"/>
<xsl:text>,</xsl:text>
</xsl:for-each>
<xsl:call-template name="repeatable">
<xsl:with-param name="tagamount" select="count(Tags/*)"/>
</xsl:call-template>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="repeatable">
<xsl:param name="tagamount"/>
<xsl:param name="index" select="0" />
<xsl:text>1,</xsl:text>
<xsl:if test="not($index = 10-$tagamount)">
<xsl:call-template name="repeatable">
<xsl:with-param name="index" select="$index + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
有没有人知道是否可以进行这种不同的迭代,或者我运气不好?
编辑:
我设法解决了这个问题。问题是我忘了在每次递归调用时传递变量tagamount。请参阅下面的解决方案。
答案 0 :(得分:3)
我无法绕过你的代码。怎么样更简单?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:variable name="sep" select="','"/>
<xsl:variable name="LF" select="' '"/>
<xsl:variable name="filler" select="'1,2,3,4,5,6,7,8,9,10'"/>
<xsl:template match="/">
<xsl:for-each select="rt/Main/Tags">
<xsl:for-each select="Tag">
<xsl:value-of select="concat(., $sep)"/>
</xsl:for-each>
<xsl:value-of select="substring($filler, 2*count(Tag)+1)"/>
<xsl:value-of select="$LF"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
注意:
1.您的XML缺少根元素:我使用“rt”作为占位符
2.出于测试目的,我将“1,1,1,......”改为“1,2.3 ...”。
答案 1 :(得分:1)
这是一种方法。
这个XSLT样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<!-- Sets the number of iterations per Tags element. -->
<xsl:variable name="maximum" select="10"/>
<!-- Matches all the Tags elements and calls a recursive template, intializing the count to 1. -->
<xsl:template match="//Tags">
<xsl:call-template name="output-tags">
<xsl:with-param name="count" select="1"/>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<!-- A recursive template that will repeat itself until its count reaches the maximum value.
If the count is equal to or less then the number of Tag elements inside the current Tags
element, then find the Tag element in the count position and print its value. Otherwise,
print 1. -->
<xsl:template name="output-tags">
<xsl:param name="count"/>
<xsl:if test="$count <= $maximum">
<xsl:choose>
<xsl:when test="$count <= count(Tag)">
<xsl:value-of select="Tag[count(preceding-sibling::Tag) = $count - 1]"/>
<xsl:text>,</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>1,</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="output-tags">
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
在应用于示例输入XML时生成以下输出:
tag1,tag2,tag3,1,1,1,1,1,1,1,
tag1,tag2,tag3,tag4,tag5,tag6,1,1,1,1,
答案 2 :(得分:0)
感谢您的回答!
我在发布后立即解决了这个问题。问题是我忘记了使用递归调用发送tagamount变量。添加后,它可以工作。可重复模板如下所示:
<xsl:param name="tagamount"/>
<xsl:param name="index" select="0" />
<xsl:text>1,</xsl:text>
<xsl:if test="not($index = 10-$tagamount)">
<xsl:call-template name="repeatable">
<xsl:with-param name="tagamount" select="$tagamount"/> <-----------
<xsl:with-param name="index" select="$index + 1" />
</xsl:call-template>
</xsl:if>