如何使用密钥引用节点 - XSLT

时间:2014-02-20 01:39:25

标签: xml xslt xslkey

给出以下xml文档......

   <ws>
       <series year="2005" mvp="Jermaine Dye">
          <team name="Chicago White Sox" wins="4" />
          <team name="Houston Astros" wins="0" />
       </series>
       <series year="2004" mvp="Manny Ramirez">
          <team name="Boston Red Sox" wins="4" />
          <team name="St. Louis Cardinals" wins="0" />
       </series>
    </ws>

我已经创建了一个键来获取每个系列中第一个团队的name属性,我正在尝试循环并列出每个系列的每个名称,如下所示;我目前没有回复任何结果,也不确定我的参考价值有什么问题?...

<xsl:key name="winners" match="team[1]" use="@name" />

    <xsl:template match="/">
        <xsl:for-each select="ws/series">
             <xsl:value-of select="key('winners', @name)" />
        </xsl:for-each>
    </xsl:template>

预期的产出将是......

Chicago White Sox (the first team from series 1)
Boston Red Sox (the first team from series 2)

我提供的xml数据只包含2个系列元素,实际上有数百个。该键用于加速转换过程,并与其他键一起生成我的结果文档。

2 个答案:

答案 0 :(得分:1)

  

我想列出每个系列中第一支球队的名字

使用密钥对于这样一个简单的任务来说是不必要的复杂化。试试吧:

<xsl:template match="/">
    <xsl:for-each select="ws/series">
        <xsl:value-of select="team[1]/@name" />
    </xsl:for-each>
</xsl:template>

当然,您需要为此添加某种包装器或分隔符,否则您只会混淆所有名称 - 比如说(假设输出方法是文本):

<xsl:template match="/">
    <xsl:for-each select="ws/series">
        <xsl:value-of select="team[1]/@name" />
        <xsl:if test="position()!=last()">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

修改

要使用密钥(人工)这样做,你必须问自己什么是团队与其系列之间的联系(除了作为一个孩子)。这里的答案是“没有”。但是,团队可以访问其父系列数据。因此,我们可以通过其父系列的某些属性来识别团队,例如年份或MVP。 MVP可能不是该系列的独特之处,所以让我们做出关键:

<xsl:key name="team-by-year" match="team" use="parent::series/@year" />

这就是说:如果你告诉我这一年,我会告诉你那一年系列赛中的球队。所以从这里开始,只需要用当前系列的年份调用一个键:

<xsl:template match="/">
    <xsl:for-each select="ws/series">
        <xsl:value-of select="key('team-by-year', @year)[1]/@name" />
        <xsl:if test="position()!=last()">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

答案 1 :(得分:0)

如果你使用这个

<xsl:stylesheet version='1.0' xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:key name="winners" match="team[1]" use="@name" />

    <xsl:template match="/">
        <xsl:for-each select="ws/series/*">
            <xsl:value-of select="key('winners', @name)/@name" />
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>