XSL样式表 - for-each多次显示数据。我该如何解决?

时间:2014-01-20 21:52:41

标签: xml xslt

在通过本网站和教程获得一些帮助之后,我已经掌握了使用XSLT解析和XML文档的问题。我有一个问题。我试图在表格中显示这个XML数据,其中包含播放器每个属性的各个列。

<bbgame> <- Root
    <team vh="V" id="MSU" name="MISSOURI STATE" record="8-2">
        <linescore line="24,36" score="60">
          <lineprd prd="1" score="24"></lineprd>
          <lineprd prd="2" score="36"></lineprd>
        </linescore>
    <player uni="01" code="01" name="Keith Pickens" checkname="PICKENS,KEITH" gp="1">
          <stats fgm="1" fga="3" fgm3="0" fga3="0" ftm="2" fta="3" tp="4" blk="1" stl="1" ast="0" min="15" oreb="0" dreb="2" treb="2" pf="2" tf="0" to="2" dq="0"></stats>
          <statsbyprd prd="1" fgm="0" fga="1" fgm3="0" fga3="0" ftm="0" fta="0" tp="0" blk="0" stl="0" ast="0" min="7" oreb="0" dreb="0" treb="0" pf="2" tf="0" to="1" dq="0"></statsbyprd>
          <statsbyprd prd="2" fgm="1" fga="2" fgm3="0" fga3="0" ftm="2" fta="3" tp="4" blk="1" stl="1" ast="0" min="8" oreb="0" dreb="2" treb="2" pf="0" tf="0" to="1" dq="0"></statsbyprd>
        </player>
    </team>
</bbgame>

我有两支球队。由团队决定的主页和访问 - vh =“V”或“H”。为简洁起见,我刚刚加入了一个团队。我已将此模板匹配写入样式表。 xsl:template match =“team // player”&gt;

<xsl:template match="team//player">
    <xsl:for-each select="//player">
            <table border="1">
                <tr>
                    <td width="200px"><xsl:value-of select="@checkname"/></td>
                    <td width="50px"> <xsl:value-of select="@fgm"/> </td>
                    <td> <xsl:value-of select="@fga"/></td>
                </tr>
            </table>
        </xsl:for-each>
    </xsl:template>

然而,这些名字被多次显示,有时看起来像30,而且“fga”和“fgm根本没有显示。此外,当我尝试使用<xsl:apply-templates select="team[@vh='v']//player"/>等个别团队调用模板时它也没有用。

我在我的XSL正文中使用:<xsl:apply-templates select="team//player"/>来检索此模板。所有其他的都正常运行但我确定这是一个我无法弄清楚的语法或逻辑错误。谢谢您的帮助。这个网站是一个很好的资源。

编辑:添加根以清除任何混淆。

2 个答案:

答案 0 :(得分:1)

不知道你的XSL的其余部分是什么样的,我可以看到你提供的那个模板缺乏对上下文的理解。

我的意思是你没有引用你认为你的元素,而且你得到任何相关信息的事实是巧合。让我解释一下......

您的模板匹配正在寻找team//player。这就是说寻找任何player团队中的任何地方。如果您只有一个播放器就可以了,但如果您的XML看起来如下所示,那么您可能会访问错误的player

<team>
  <player>
    <player/>
  </player>
</team>

根据apply-templates来电的内容,我会将您的匹配更改为team/player或仅player

下一期是您的for-each。目前,您的模板是在team/player的上下文中设置的,正如我们刚刚介绍的那样。但是,您的for-each设置为//player,由于双斜杠,它在任何上下文中都会查找player。你可以删除双斜线但是你会在team/player/player的上下文中找不到它。我想在这一点上你可能不想要for-each,因为如果模板定义正确,它应该遍历所有player元素。

最后一部分是value-of中的属性。再次返回到模板的上下文,您将在此位置查找属性team/player/@fmgteam/player/@fga两者都不存在。您可以更新选择以包含元素名称stats/@fmgstatsbyprd/@fmg,具体取决于您希望从中获取属性的元素。

答案 1 :(得分:1)

如果我正确理解您的问题,您获得多次单个玩家输出的原因是您的第一个<xsl:template match="team//player">匹配<player>下任何位置的所有<team>元素。对于其中的每一个,<xsl:for-each select="//player">匹配XML中任何位置的所有<player>元素。如此有效,你说“找到每个玩家,然后为每个玩家找到每个玩家”。

属性不匹配的原因是@fgm@fga<stats>的属性,而不是<player>

我怀疑<xsl:apply-templates select="team[@vh='v']//player"/>无效的原因是您的XML中@vh属性的值是大写的'V'。 XPath区分大小写。

在我的解决方案中,我已经修改了您的输入XML示例以包含两个玩家,因为这复制了我认为您的问题(个别玩家输出多次)。

<team vh="V" id="MSU" name="MISSOURI STATE" record="8-2">
  <linescore line="24,36" score="60">
    <lineprd prd="1" score="24"></lineprd>
    <lineprd prd="2" score="36"></lineprd>
  </linescore>
  <player uni="01" code="01" name="Keith Pickens" checkname="PICKENS,KEITH" gp="1">
    <stats fgm="1" fga="3" fgm3="0" fga3="0" ftm="2" fta="3" tp="4" blk="1" stl="1" ast="0" min="15" oreb="0" dreb="2" treb="2" pf="2" tf="0" to="2" dq="0"></stats>
    <statsbyprd prd="1" fgm="0" fga="1" fgm3="0" fga3="0" ftm="0" fta="0" tp="0" blk="0" stl="0" ast="0" min="7" oreb="0" dreb="0" treb="0" pf="2" tf="0" to="1" dq="0"></statsbyprd>
    <statsbyprd prd="2" fgm="1" fga="2" fgm3="0" fga3="0" ftm="2" fta="3" tp="4" blk="1" stl="1" ast="0" min="8" oreb="0" dreb="2" treb="2" pf="0" tf="0" to="1" dq="0"></statsbyprd>
  </player>
  <player uni="01" code="01" name="Robbie Fowler" checkname="FOWLER,ROBBIE" gp="1">
    <stats fgm="1" fga="3" fgm3="0" fga3="0" ftm="2" fta="3" tp="4" blk="1" stl="1" ast="0" min="15" oreb="0" dreb="2" treb="2" pf="2" tf="0" to="2" dq="0"></stats>
    <statsbyprd prd="1" fgm="0" fga="1" fgm3="0" fga3="0" ftm="0" fta="0" tp="0" blk="0" stl="0" ast="0" min="7" oreb="0" dreb="0" treb="0" pf="2" tf="0" to="1" dq="0"></statsbyprd>
    <statsbyprd prd="2" fgm="1" fga="2" fgm3="0" fga3="0" ftm="2" fta="3" tp="4" blk="1" stl="1" ast="0" min="8" oreb="0" dreb="2" treb="2" pf="0" tf="0" to="1" dq="0"></statsbyprd>
  </player>
</team>

在这种情况下,以下XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="team/player">
    <table border="1">
      <tr>
    <td width="200px"><xsl:value-of select="@checkname"/></td>
    <td width="50px"> <xsl:value-of select="stats/@fgm"/> </td>
    <td> <xsl:value-of select="stats/@fga"/></td>
      </tr>
    </table>
  </xsl:template>
</xsl:stylesheet>

生成此输出HTML:

<table border="1">
   <tr>
      <td width="200px">PICKENS,KEITH</td>
      <td width="50px">1</td>
      <td>3</td>
   </tr>
</table>
<table border="1">
   <tr>
      <td width="200px">FOWLER,ROBBIE</td>
      <td width="50px">1</td>
      <td>3</td>
   </tr>
</table>