我对如何编写下面的递归循环感到困惑。尝试逗号分隔但看起来像循环只会起作用。任何解决方案,想法都会有所帮助?谢谢我使用的是XML版本1.下面只是一个例子。
我的XML来源:
<Groceries>
<fruit>Apple,Banana,Peach,Lemon</fruit>
</Groceries>
我正在寻找一个XSLT来获得下面的输出。
所以我想要的XML输出应该是这样的:
<Foods>
<Food raw="Lemon" cat="Fruit" val="Lemon"/>
<Food raw="Apple" cat="Fruit" val="Apple"/>
<Food raw="Peach" cat="Fruit" val="Peach"/>
<Food raw="Banana" cat="Fruit" val="Banana"/>
</Foods>
我尝试创建XSLT解决方案是:
<xsl:element name="Fruit">
<xsl:attribute name="raw">
<xsl:value-of select="substring-before(fruit,',')"/>
</xsl:attribute>
<xsl:attribute name="cat">Fruit</xsl:attribute>
<xsl:attribute name="val">
<xsl:value-of select="substring-before(fruit,',')"/>
</xsl:attribute>
</xsl:element>
<xsl:text>
</xsl:text>
<xsl:element name="Fruit">
<xsl:attribute name="raw">
<xsl:value-of select="substring-after(fruit,',')"/>
</xsl:attribute>
<xsl:attribute name="cat">Fruit</xsl:attribute>
<xsl:attribute name="val">
<xsl:value-of select="substring- after(fruit,',')"/>
</xsl:attribute>
</xsl:element>
<xsl:text>
</xsl:text>
由于
答案 0 :(得分:0)
带有递归模板的XSLT-1.0实现了预期的结果:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Groceries">
<Foods>
<xsl:call-template name="fruit"> <!-- call the recursive template -->
<xsl:with-param name="txt" select="concat(fruit/text(),',')" /> <!-- add a leading ',' to make the recursive template behave properly -->
</xsl:call-template>
</Foods>
</xsl:template>
<xsl:template name="fruit">
<xsl:param name="txt" />
<xsl:if test="$txt != ''">
<xsl:variable name="x" select="normalize-space(substring-before($txt,','))"/>
<Food raw="{$x}" cat="Fruit" val="{$x}" /> <!-- add 'Food' element with attributes -->
<xsl:call-template name="fruit"> <!-- call the recursive template with the rest of the comma-separated-string -->
<xsl:with-param name="txt" select="normalize-space(substring-after($txt,','))" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
其输出符合要求:
<?xml version="1.0"?>
<Foods>
<Food raw="Apple" cat="Fruit" val="Apple"/>
<Food raw="Banana" cat="Fruit" val="Banana"/>
<Food raw="Peach" cat="Fruit" val="Peach"/>
<Food raw="Lemon" cat="Fruit" val="Lemon"/>
</Foods>
答案 1 :(得分:0)
通过为template
元素提供名称,让它在满足某些条件时调用自身,并使用call-template
元素在内容上调用它来构建递归模板。您的尝试完全没有尝试,因为它不包含任何template
或call-template
元素,并且不是有效的XSLT样式表。
此代码将递归地生成所描述的输出,包括所描述的输出元素的看似随机顺序。
<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
<output media-type="application/xml"/>
<template name="parse.CSV.string">
<param name="CSV.string.element"/>
<param name="CSV.string" select="string($CSV.string.element/child::text())"/>
<param name="required.item.string" select="string($CSV.string.element/child::text())"/>
<variable name="item.string">
<choose>
<when test="contains($CSV.string, ',')">
<value-of select="substring-before($CSV.string, ',')"/>
</when>
<otherwise>
<value-of select="$CSV.string"/>
</otherwise>
</choose>
</variable>
<choose>
<when test="$item.string = $required.item.string">
<element name="Food">
<attribute name="raw">
<value-of select="$item.string"/>
</attribute>
<attribute name="cat">Fruit</attribute>
<attribute name="val">
<value-of select="$item.string"/>
</attribute>
</element>
</when>
<when test="contains($CSV.string, ',')">
<call-template name="parse.CSV.string">
<with-param name="CSV.string.element" select="$CSV.string.element"/>
<with-param name="CSV.string" select="substring-after($CSV.string, ',')"/>
<with-param name="required.item.string" select="$required.item.string"/>
</call-template>
</when>
</choose>
</template>
<template match="/child::Groceries">
<element name="Foods">
<call-template name="parse.CSV.string">
<with-param name="CSV.string.element" select="child::fruit"/>
<with-param name="required.item.string" select="'Lemon'"/>
</call-template>
<call-template name="parse.CSV.string">
<with-param name="CSV.string.element" select="child::fruit"/>
<with-param name="required.item.string" select="'Apple'"/>
</call-template>
<call-template name="parse.CSV.string">
<with-param name="CSV.string.element" select="child::fruit"/>
<with-param name="required.item.string" select="'Peach'"/>
</call-template>
<call-template name="parse.CSV.string">
<with-param name="CSV.string.element" select="child::fruit"/>
<with-param name="required.item.string" select="'Banana'"/>
</call-template>
</element>
</template>
</transform>