【问题标题】:How do I apply templates to each selected node in a for-each?如何将模板应用于 for-each 中的每个选定节点?
【发布时间】:2009-10-25 10:16:05
【问题描述】:

我知道我在这里遗漏了一些东西。在下面的 XSLT 转换中,实际结果与期望的结果不匹配。

for-each 中,我想将match="track" 模板应用于每个选定的track 元素。如果我正确理解 XSLT,在当前设置下,只有每个选定 track 元素的子节点与模板匹配,而不是 track 元素本身。

如何使track 元素根据需要通过模板?我需要重新考虑我的整个方法吗?

注意:转换是使用 PHP 执行的。为简洁起见,省略了 XML 声明。

XML 文档:

<album>
    <title>Grave Dancers Union</title>
    <track id="shove">Somebody To Shove</track>
    <track id="gold">Black Gold</track>
    <track id="train">Runaway Train</track>
    <producer>Michael Beinhorn</producer>
</album>

XSL 样式表:

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/album">
        <ol>
            <xsl:for-each select="track">
                <li><xsl:apply-templates/></li>
            </xsl:for-each>
        </ol>
    </xsl:template>

    <xsl:template match="track">
        <a href="{@id}"><xsl:apply-templates/></a>
    </xsl:template>
</xsl:stylesheet>

结果:

<ol>
    <li>Somebody To Shove</li>
    <li>Black Gold</li>
    <li>Runaway Train</li>
</ol>

期望的结果:

<ol>
    <li><a href="shove">Somebody To Shove</a></li>
    <li><a href="gold">Black Gold</a></li>
    <li><a href="train">Runaway Train</a></li>
</ol>

【问题讨论】:

    标签: xslt foreach apply-templates


    【解决方案1】:

    我同意 'ndim' 的观点,即您可能应该重组您的 XSLT 以取消 xsl:for-each 循环。

    或者,您可以修改 xsl:apply-templates 以选择 xsl:for-each 中的当前轨道节点

    <xsl:for-each select="track">
       <li>
          <xsl:apply-templates select="." />
       </li>
    </xsl:for-each>
    

    如果需要,保留 xsl:for-each 至少可以让您以其他顺序对曲目进行排序。

    【讨论】:

    • 很好的分类。由于排序,我想这是最好的解决方案。
    • 我可以发誓我已经尝试过了,但我想没有。不过,这正是我想要的!
    【解决方案2】:

    我会对其进行一些重组(如果您不需要通过for-each 方法进行排序):

    <xsl:template match="/album">
      <ol>
        <xsl:apply-templates select="track"/>
      </ol>
    </xsl:template>
    
    <xsl:template match="track">
      <li><a href="{@id}"><xsl:apply-templates/></a></li>
    <xsl:template>
    

    这看起来更短,更中肯,恕我直言。

    我猜你的

        <xsl:for-each select="track">
           <li><xsl:apply-templates/></li>
        </xsl:for-each>
    

    遍历所有带有for-each 的跟踪元素,然后将默认规则应用于其后代。因此for-each 的内容与match="track" 模板具有相同的上下文节点,因此match="track" 模板永远不会匹配。

    如果你真的想以这种方式使用for-each,你需要在你的方法中改变以下两件事之一:

    1. match="track" 模板中添加name="track" 属性,然后在for-each 中使用&lt;xsl:call-template/&gt;(我的想法,比Tim C 更糟糕)
    2. 使用Tim C 的解决方案,使用&lt;xsl:apply-templates select="."/&gt;。这样做的好处是避免命名并保留对曲目进行排序的可能性。

    【讨论】:

    • 重组解决方案似乎不像我想要的那样模块化(它不允许我在页面/站点的其他地方也包含 &lt;dl&gt;&lt;table&gt; 中的轨道,至少不使用相同的样式表),但您可能是对的,因为它是本示例中最流畅的解决方案。
    • @Jakob 我知道这很古老,但我只想指出您可以使用mode 属性为相同的节点选择另一个模板。喜欢&lt;xsl:apply-templates mode="table"&gt;&lt;xsl:template match="track" mode="table"&gt;...&lt;/xsl:template&gt;
    【解决方案3】:

    我认为使用应用模板和模板模式是更简洁的解决方案:

    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >
    
      <xsl:template match="/">
        <body>
          <xsl:apply-templates select="album" mode="ol" />
        </body>
      </xsl:template>
    
      <xsl:template match="album" mode="ol">
        <ol>
          <xsl:apply-templates select="track" mode="li" />
        </ol>
      </xsl:template>
    
      <xsl:template match="track" mode="li">
        <li>
          <xsl:apply-templates select="." />
        </li>
      </xsl:template>
    
      <xsl:template match="track">
        <a href="{@id}">
          <xsl:value-of select="." />
        </a>
      </xsl:template>
    
    
    </xsl:stylesheet>
    

    结果:

    <body>
      <ol>
        <li>
          <a href="shove">Somebody To Shove</a>
        </li>
        <li>
          <a href="gold">Black Gold</a>
        </li>
        <li>
          <a href="train">Runaway Train</a>
        </li>
      </ol>
    </body>
    

    【讨论】:

      【解决方案4】:

      for-each 语句将上下文节点从专辑更改为曲目。 默认情况下,apply-templates 调用将模板应用于上下文节点的子节点,在您的情况下,该子节点是 track 元素的子节点。因此,匹配“track”的模板永远不会被击中。

      【讨论】:

        猜你喜欢
        • 2018-08-30
        • 2011-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-07
        • 1970-01-01
        • 2015-01-25
        • 2016-07-18
        相关资源
        最近更新 更多