XSLT:使用键和条件''select-of select'?

时间:2012-11-22 23:51:13

标签: xslt xpath xslt-2.0

这个问题从前一个帖子开始:XSLT: Sorting based on sum of values from other nodes

我现在可以使用密钥从其他节点获取数据。 我现在无法获得的是现在应用条件来选择我在使用这些键时所拥有的数据所需的语法或方法。

这是我正在使用的简化xml(从上一个修改过来强调问题):

<Horses>
    <Horse>
        <ID>1</ID>
        <Name>hrsA</Name>
        <SireID>101</SireID>
        <Age>3</Age>
        <Pace>
            <Stakes>20</Stakes>
            <Wins>0</Wins>
        </Pace>
    </Horse>
    <Horse>
        <ID>2</ID>
        <Name>hrsB</Name>
        <SireID>101</SireID>
        <Age>6</Age>
        <Pace>
            <Stakes>1600</Stakes>
            <Wins>9</Wins>
        </Pace>
    </Horse>
    <Horse>
        <ID>3</ID>
        <Name>hrsC</Name>
        <SireID>101</SireID>
        <Age>3</Age>
        <Trot>
            <Stakes>200</Stakes>
            <Wins>2</Wins>
        </Trot>
    </Horse>
    <Horse>
        <ID>4</ID>
        <Name>hrsD</Name>
        <SireID>101</SireID>
        <Age>4</Age>
        <Pace>
            <Stakes>50</Stakes>
            <Wins>0</Wins>
        </Pace>
        <Trot>
            <Stakes>100</Stakes>
            <Wins>1</Wins>
        </Trot>
    </Horse>
    <Horse>
        <ID>5</ID>
        <Name>hrsE</Name>
        <SireID>101</SireID>
        <Age>3</Age>
        <Pace>
            <Stakes>100</Stakes>
            <Wins>1</Wins>
        </Pace>
        <Trot>
            <Stakes>300</Stakes>
            <Wins>1</Wins>
        </Trot>
    </Horse>
</Horses>
<Sires>
    <Sire>
        <ID>101</ID>
        <Name>srA</Name>
        <LiveFoalsALL>117</LiveFoalsALL>
    </Sire>
</Sires>

在一种情况下,我需要让属于一个Sire的后代(Horses)达到一定年龄。

如果没有指定年龄,我会使用一个按照赌注进行排序的钥匙(感谢Dimitre):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kOffspring" match="Horse" use="SireID"/>

 <xsl:template match="/*">
  <xsl:apply-templates select="Sires/Sire">
   <xsl:sort select="sum(key('kOffspring', ID)/*/Stakes)"
             data-type="number" order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="Sire">
    <!-- get the data I want -->
 </xsl:template>
</xsl:stylesheet>

现在,在“获取我想要的数据”中,我试图只获得3岁的马(年龄= 3) 例如,要获得srA的3岁获胜后代(答案= 2),我需要这样的事情,我在想:

<xsl:value-of select="count(key('kOffspring', ID)[Age=3]/*/Wins)"/>

但是这不起作用......或者我是否需要为每个我想要使用某些条件语法(?)的年龄创建一个新密钥,如:

<xsl:key name="kOffspring" match="Horse[/Age=3]" use="SireID"/>

你可以看到我真的不知道我在做什么,或者甚至可能: - )

同样情况下的另一种情况是需要计算有多少匹马是赢家 - 答案= 4(不是胜利的数量,只是他们是否以节奏或小跑的方式获胜......第三种情况要求只是步调或只是在小跑)。

我在Sire模板中尝试了这个:

<xsl:value-of select="count(key('kOffspring', ID)/*/Wins &gt; 0)"/>

但这只会返回一个计数。

如果这里的任何专家能帮助我帮助我,我将不胜感激。与其他编程语言相比,我发现xslt语法有点令人困惑,难以记住 - 我希望我能很快得到它,因为它非常强大。

此致   布莱斯斯滕贝格。

1 个答案:

答案 0 :(得分:3)

此转化

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kOffspring" match="Horse" use="SireID"/>

 <xsl:template match="/*">
  <xsl:apply-templates select="Sires/Sire">
   <xsl:sort select="sum(key('kOffspring', ID)/*/Stakes)"
             data-type="number" order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="Sire">
     Sire <xsl:value-of select="concat(ID,' (', Name, ') Stakes: ')"/>
   <xsl:value-of select="sum(key('kOffspring', ID)/*/Stakes)"/>
     3 year old winning offspring: <xsl:value-of
     select="count(key('kOffspring', ID)[Age = 3 and */Wins > 0])"/>
     Offspring that ever were a winner: <xsl:value-of
      select="count(key('kOffspring', ID)[*/Wins > 0])"/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML (提供的片段,包含在单个顶部元素中,使其成为格式良好的XML文档):

<t>
    <Horses>
        <Horse>
            <ID>1</ID>
            <Name>hrsA</Name>
            <SireID>101</SireID>
            <Age>3</Age>
            <Pace>
                <Stakes>20</Stakes>
                <Wins>0</Wins>
            </Pace>
        </Horse>
        <Horse>
            <ID>2</ID>
            <Name>hrsB</Name>
            <SireID>101</SireID>
            <Age>6</Age>
            <Pace>
                <Stakes>1600</Stakes>
                <Wins>9</Wins>
            </Pace>
        </Horse>
        <Horse>
            <ID>3</ID>
            <Name>hrsC</Name>
            <SireID>101</SireID>
            <Age>3</Age>
            <Trot>
                <Stakes>200</Stakes>
                <Wins>2</Wins>
            </Trot>
        </Horse>
        <Horse>
            <ID>4</ID>
            <Name>hrsD</Name>
            <SireID>101</SireID>
            <Age>4</Age>
            <Pace>
                <Stakes>50</Stakes>
                <Wins>0</Wins>
            </Pace>
            <Trot>
                <Stakes>100</Stakes>
                <Wins>1</Wins>
            </Trot>
        </Horse>
        <Horse>
            <ID>5</ID>
            <Name>hrsE</Name>
            <SireID>101</SireID>
            <Age>3</Age>
            <Pace>
                <Stakes>100</Stakes>
                <Wins>1</Wins>
            </Pace>
            <Trot>
                <Stakes>300</Stakes>
                <Wins>1</Wins>
            </Trot>
        </Horse>
    </Horses>
    <Sires>
        <Sire>
            <ID>101</ID>
            <Name>srA</Name>
            <LiveFoalsALL>117</LiveFoalsALL>
        </Sire>
    </Sires>
</t>

会产生想要的正确结果:

 Sire 101 (srA) Stakes: 2370
 3 year old winning offspring: 2
 Offspring that ever were a winner: 4

或者,一个可能更有效的解决方案是使用另一个复合键,它的两个部分是SireIDAge

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kOffspring" match="Horse" use="SireID"/>
 <xsl:key name="kOffspringBySireIdAndAge" match="Horse"
  use="concat(SireID, '+', Age)"/>

 <xsl:template match="/*">
  <xsl:apply-templates select="Sires/Sire">
   <xsl:sort select="sum(key('kOffspring', ID)/*/Stakes)"
             data-type="number" order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="Sire">
     Sire <xsl:value-of select="concat(ID,' (', Name, ') Stakes: ')"/>
   <xsl:value-of select="sum(key('kOffspring', ID)/*/Stakes)"/>
     3 year old winning offspring: <xsl:value-of
     select="count(key('kOffspringBySireIdAndAge', concat(ID, '+3'))
                       [*/Wins > 0]
                  )"/>
     Offspring that ever were a winner: <xsl:value-of
      select="count(key('kOffspring', ID)[*/Wins > 0])"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一XML文档(上图)时,会产生相同的正确结果

 Sire 101 (srA) Stakes: 2370
 3 year old winning offspring: 2
 Offspring that ever were a winner: 4