所以这是我的XML
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
</cd>
<cb>
<title>Car</title>
<speed>420</speed>
<hp>1200</hp>
</cb>
<cb>
<title>something</title>
<speed>blabla</speed>
<hp>31415</hp>
</cb>
</catalog>
这是我的XSLT,每个循环包含2个
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="catalog/cd">
<xsl:number value="position()" format="1. "/>
<xsl:value-of select="title"/>
<br/>
</xsl:for-each>
<xsl:for-each select="catalog/cb">
<xsl:number value="position()" format="1. "/>
<xsl:value-of select="hp"/>
<br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这是我的输出
1 Empire Burlesque
1 1200
2 31415
问题是:我能以某种方式将计数器值从第一个for-each传递到第二个并将其用作位置的输入吗?所以我的输出将是:(1。Empire Burlesque 2. 1200 3. 31415)我认为某些东西是Position()+ Variable但它没带东西。
答案 0 :(得分:1)
这是你可以看到它的一种方式:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="count-cd" select="count(catalog/cd)" />
<xsl:for-each select="catalog/cd">
<xsl:number value="position()" format="1. "/>
<xsl:value-of select="title"/>
<br/>
</xsl:for-each>
<xsl:for-each select="catalog/cb">
<xsl:number value="$count-cd + position()" format="1. "/>
<xsl:value-of select="hp"/>
<br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
测试,清洁解决方案
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--without this, xsl number will not produce numbers 1,2,3 but 2,4,6.
We need to stop parsing unwanted nodes -->
<xsl:strip-space elements="*"/>
<!--match either catalog/cd or catalog/cb -->
<xsl:template match="catalog/cd|catalog/cb">
<xsl:number value="position()" format="1. "/>
<xsl:apply-templates/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="catalog/cd/title">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="catalog/cb/hp">
<xsl:value-of select="."/>
</xsl:template>
<!--we need to stop processing text for all other nodes -->
<xsl:template match="text()"/>
</xsl:stylesheet>
注意:在输出中,cd和cb节点的显示顺序与源文档中的顺序相同。
这个解决方案(对我来说)是XSLT的更惯用的用法。无需使用for-each。 每个细节都有简短的特定模板,而不是一个长模板。
答案 2 :(得分:1)
我喜欢 Bartosz Bilicki 的解决方案,但问题在于输出 首先是所有
cd
数据,然后是所有cb
数据。在当前的XML文档中,<cd>
只是发生在所有<cb>
之前 - 通常这些可能是混合的。 没有传递起始编号值。 。 强>
这是一个简短/简单的解决方案,在没有 <xsl:for-each>
且不使用参数或变量来传递起始编号值的情况下完全执行此操作,并且不会假设cd
或cb
元素的任何特定顺序:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:apply-templates select="*">
<xsl:sort select="string-length(substring-before('cdcb', name()))"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="cd|cb">
<xsl:number value="position()" format="1. "/>
<xsl:value-of select="hp | self::cd/title"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
</cd>
<cb>
<title>Car</title>
<speed>420</speed>
<hp>1200</hp>
</cb>
<cb>
<title>something</title>
<speed>blabla</speed>
<hp>31415</hp>
</cb>
</catalog>
产生了想要的正确结果:
1. Empire Burlesque
2. 1200
3. 31415