我编写了一些使用一个XML文档来过滤另一个XML文档的XSLT。现在我想使用position()
对输出元素进行编号,但我的过滤条件并未内置到我的<xsl:for-each>
中,因此position()
为我提供了编号间隔的结果。我如何摆脱差距?
<xsl:variable name="Astring">
<a><b>10</b><b>20</b><b>30</b></a>
</xsl:variable>
<xsl:variable name="A" select="msxml:node-set($Astring)" />
<xsl:variable name="Bstring">
<c><d>20</d><d>30</d></c>
</xsl:variable>
<xsl:variable name="B" select="msxml:node-set($Bstring)" />
<e>
<xsl:for-each select="$A/a/b">
<xsl:variable name="matchvalue" select="text()" />
<xsl:if test="count($B/c/d[text() = $matchvalue]) > 0">
<xsl:element name="f">
<xsl:attribute name="i">
<xsl:value-of select="position()" />
</xsl:attribute>
<xsl:copy-of select="text()" />
</xsl:element>
</xsl:if>
</xsl:for-each>
</e>
结果如下:
<e>
<f i="2">20</f>
<f i="3">30</f>
</e>
...但我想要这个:
<e>
<f i="1">20</f>
<f i="2">30</f>
</e>
有没有办法在<xsl:if>
<xsl:for-each>
属性中加入上述select
过滤测试?
注意:我看过this question re:过滤和this one re:计数器,但前者不对其结果进行编号,后者使用position()。
答案 0 :(得分:3)
为什么你不能在for-each循环中包含你的条件有什么特别的原因吗?
<xsl:for-each select="$A/a/b[$B/c/d = .]">
我在Visual Studio中对此进行了测试,它适用于此示例。
这是输出:
<e>
<f i="1">20</f>
<f i="2">30</f>
</e>
答案 1 :(得分:2)
我不确定为什么当<xsl:for-each>
显然是更好的选择时,人们总是希望使用<xsl:apply-templates>
。
好的,这是修辞。我知道为什么会这样:<xsl:for-each>
似乎更容易。但事实并非如此 - 以下两个模板取代了整个for-each构造:
<xsl:template match="/">
<e><xsl:apply-templates select="$B/c/d[$A/a/b = .]" /></e>
</xsl:template>
<xsl:template match="d">
<f i="{position()}"><xsl:value-of select="." /></f>
</xsl:template>
输出:
<e>
<f i="1">20</f>
<f i="2">30</f>
</e>
好吧,我有点作弊。您可以将<xsl:for-each>
版本压缩为:
<xsl:template match="/">
<e>
<xsl:for-each select="$B/c/d[$A/a/b = .]">
<f i="{position()}"><xsl:value-of select="." /></f>
</xsl:for-each>
</e>
</xsl:template>
然而,它缺乏<xsl:apply-templates>
变种的轻盈,恕我直言。