将计数器值从a传递给另一个

时间:2016-10-25 21:34:34

标签: xml xslt

所以这是我的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但它没带东西。

3 个答案:

答案 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>&#xa;</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>不使用参数或变量来传递起始编号值的情况下完全执行此操作,并且不会假设cdcb元素的任何特定顺序

<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>&#xa;</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