【问题标题】:XSLT: 'value-of select' using keys and conditions?XSLT:使用键和条件的“选择值”?
【发布时间】:2012-11-22 23:51:12
【问题描述】:

这个问题来自上一个帖子: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 的后代(马)。

在没有指定年龄的情况下,我使用了一个对赢得的赌注进行排序的密钥,就像这样(感谢 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"/>

如你所见,我真的不知道我在做什么,也不知道它是否可能:-)

.

类似的另一种情况是需要计算有多少匹马是获胜者 - answer=4(不是获胜的数量,只是他们是否以速度或小跑获胜......第三种情况需要只是速度或只是小跑)。

我在 Sire 模板中尝试过:

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

但这只会返回一个计数。

如果这里有任何专家可以帮助我前进,我将不胜感激。与其他编程语言相比,我发现 xslt 语法有点混乱且难以记住 - 我希望我能尽快掌握它,因为它非常强大。

问候, 布莱斯·斯坦伯格。

【问题讨论】:

    标签: xslt xpath xslt-2.0


    【解决方案1】:

    这种转变

    <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
    

    【讨论】:

    • AWESOME You da man :-))) 一旦你看到它,看起来很容易。非常感谢,布莱斯。
    • 还有一件事,我可以创建另一个使用第一个键作为匹配的键吗?就像&lt;xsl:key name="kDamSireOffspring" match="kOffspring" use="DamSireID"/&gt; 一样,我还有另一个节点是公牛的母亲,但统计数据仍然来自马匹。如果这里不清楚,我可以创建新问题。
    • @user1840734,布莱斯,不客气。我没有看到任何名为“DamSireID”的元素,因此可能需要一个新问题。我将更新我的答案以显示如何使用另一个键交替选择想要的老年马。
    • @user1840734,布莱斯,我添加了使用第二个密钥的替代解决方案。
    猜你喜欢
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多