XSLT以行显示元素

时间:2012-02-13 15:11:27

标签: xml xslt

我遇到了一个XSLT难题 - 你无法在一个条件语句中打开一个元素并在另一个条件语句中关闭它。我在Stackoverflow的其他地方看到了与此相关的明显相关问题,但对于低脑功率的XSLT初学者来说,答案有点莫名其妙。

基本上我正试图在整个页面的列中显示我的XML中的项目。我现在只想做两个列,但我想要一个没有硬编码的列数的解决方案。

我的XML数据是这样的,有大约100个节点:

   <?xml version="1.0" encoding="UTF-8"?>
    <response>
        <node type="category">
            <collection>
                <node>
                    <articleId>1</articleId>
                    <headline>Merry Christmas says Google as it unveils animated Jingle Bells Doodle</headline>
                </node>
                <node>
                    <articleId>2</articleId>
                    <headline>Google activating 700,000 Android phones every day</headline>
                </node>
                <node>
                    <articleId>3</articleId>
                    <headline>Google attacked by music industry over 'broken pledges' on illegal downloading</headline>
                </node>
            </collection>
        </node>
    </response>

我想把它翻译成:

    <div>
        <div class="left">
            [ the articleId ]
            [ the headline ]
        </div>
        <div class="right">
            [ the articleId ]
            [ the headline ]
        </div>
    </div>

左边的第1条,右边的第2条,左边下一行的第3条等等。

我们已经尝试过这样的XSLT

<xsl:for-each select="$collection/spi:node[(position() mod $columns) != 0]">
<xsl:variable name="pos" select="position()"/>
<xsl:variable name="node" select="."/>
<div>
    <div class="left">
        <xsl:value-of select="../spi:node[$pos]/spi:articleId"/>]
        <xsl:value-of select="../spi:node[$pos]/spi:headline"/>
    </div>
    <div class="right">
        <xsl:value-of select="../spi:node[$pos + 1]/spi:articleId"/>
        <xsl:value-of select="../spi:node[$pos + 1]/spi:headline"/>
    </div>
</div>
</xsl:for-each>

但这只会导致空div和奇怪的重复文章。任何XSLT专家都能指出我们正确的方向吗?

干杯

1 个答案:

答案 0 :(得分:1)

如果您要写出 $ pos 变量的值,您会发现它变为1,2,3 ......等等,而不是1,3,......这是你可能期待什么。这就是你想重复的原因。我想。

事实上,没有必要使用 $ pos 变量来查找节点,因为每次都会在对中的第一个节点上定位,所以你需要做的就是这样的事情

  <xsl:for-each select="$collection/spi:node[(position() mod $columns) != 0]">
     <div>
        <div class="left">
           <xsl:value-of select="articleId"/>
           <xsl:value-of select="headline"/>
        </div>
        <div class="right">
           <xsl:value-of select="following-sibling::spi:node[1]/articleId"/>
           <xsl:value-of select="following-sibling::spi:node[1]/headline"/>
        </div>
     </div>
  </xsl:for-each>

请注意,通常最佳做法是使用 xsl:apply-templates ,而不是 xsl:for-each ,因此您可以像这样重写它:

<xsl:template match="/">
   <xsl:variable name="collection" select="response/node/collection"/>
   <xsl:apply-templates 
      select="$collection/spi:node[(position() mod $columns) != 0]" mode="group"/>
</xsl:template>

<xsl:template match="node" mode="group">
   <div>
      <div class="left">
         <xsl:call-template name="spi:node"/>
      </div>
      <div class="right">
         <xsl:apply-templates select="following-sibling::spi:node[1]"/>
      </div>
   </div>
</xsl:template>

<xsl:template name="node" match="node">
   <xsl:value-of select="articleId"/>
   <xsl:value-of select="headline"/>
</xsl:template>