在XSLT for-each语句中将正值与“零”值分开

时间:2010-05-12 07:50:21

标签: xml xslt

我正在使用XSLT遍历XML文件(包含多个表)。页面的部分工作是获取每个表的标题,并显示该标题以及表包含的项目数(即“Problems(5)”)。

我能够获得项目数,但我现在需要将这些项目中的0(零)项分开,并将它们放在表标题列表的底部。我遇到了麻烦,因为其他具有正数的项目需要保留原始顺序/未排序。

以下是标题列表的代码:

<ul>
  <xsl:for-each select="n1:component/n1:structuredBody/n1:component/n1:section/n1:title">
     <li style="list-style-type:none;">
     <div style = "padding:3px"><a href="#{generate-id(.)}">
     <xsl:variable name ="count" select ="count(../n1:entry)"/>
     <xsl:choose>
        <xsl:when test = "$count != 0">
           <xsl:value-of select="."/> (<xsl:value-of select="$count"/>)
        </xsl:when>
        <xsl:otherwise>
           <div id = "zero"><xsl:value-of select="."/> (<xsl:value-of select="$count"/>)</div>
        </xsl:otherwise>
     </xsl:choose>
     </a>
     </div>
     </li>
   </xsl:for-each>
</ul>

现在,“零”div只是将每个链接标记为灰色。

关于如何将“零”div放在列表底部的任何帮助将不胜感激。谢谢!

使用零/非零模板编辑代码:

<xsl:for-each select="n1:component/n1:structuredBody/n1:component/n1:section/n1:title">
   <li style="list-style-type:none;">
      <div style = "padding:3px"><a href="#{generate-id(.)}">
         <xsl:apply-templates select="n1:title[count(../n1:entry) != 0]" mode="nonzero" />
         <xsl:apply-templates select="n1:title[count(../n1:entry) == 0]" mode="zero" />
      </a>
      </div>
   </li>
</xsl:for-each>

4 个答案:

答案 0 :(得分:1)

您可以创建两个模板来处理每个节点上具有mode属性的节点。如果您愿意,可以mode="zero"mode="nonzero"

<xsl:template match="n1:title" mode="zero">
  ...
</xsl:template>
<xsl:template match="n1:title" mode="nonzero">
  ...
</xsl:template>

调用nonzero模板,选择带有count &gt; 0的项目和zero count = 0模板。

<xsl:apply-templates select="n1:title[count(../n1:entry) &gt; 0]" mode="nonzero" />
<xsl:apply-templates select="n1:title[count(../n1:entry) = 0]" mode="zero" />

将来电nonzero模板放在zero模板的调用之上。

答案 1 :(得分:1)

你应该单独穿越它们。您可以使用xsl:apply-templates代替xsl:for-each

来完成此操作
<xsl:template match=".... something ....">
  <ul>
    <xsl:apply-templates select="n1:component/n1:structuredBody/n1:component/n1:section/n1:title[count(../n1:entry) != 0]"/>
    <xsl:apply-templates select="n1:component/n1:structuredBody/n1:component/n1:section/n1:title[count(../n1:entry) = 0]"/>
  </ul>

</xsl:template>

<xsl:template match="n1:title" >
  <li style="list-style-type:none;">
    <div style = "padding:3px"><a href="#{generate-id(.)}">
      <xsl:variable name ="count" select ="count(../n1:entry)"/>
      <xsl:choose>
        <xsl:when test = "$count != 0">
          <xsl:value-of select="."/> (<xsl:value-of select="$count"/>)
        </xsl:when>
        <xsl:otherwise>
          <div id = "zero"><xsl:value-of select="."/> (<xsl:value-of select="$count"/>)</div>
        </xsl:otherwise>
      </xsl:choose>
    </a>
    </div>
  </li>

</xsl:template>

答案 2 :(得分:1)

不需要mode且没有条件逻辑(<xsl:choose>)。

此外,转化只能使用一个<xsl:apply-templates>

<xsl:apply-templates select="n1:title>
  <xsl:sort select="count(../n1:entry) = 0" data-type="number"/>
</xsl:apply-templates>

以下是两个要使用的模板

<!-- There is one or more ../n1:entry -->
<xsl:template match="n1:title"[../n1:entry] >  
  ...  
</xsl:template> 

<!-- No ../n1:entry exists --> 
<xsl:template match="n1:title"[not(../n1:entry)]">  
  ...  
</xsl:template> 

答案 3 :(得分:1)

你可能对你所拥有的东西感到满意,但我喜欢Dimitre的答案,并希望让它适合我自己的学习。

我简化了(我相信的是)输入数据:

<component>
  <section>
    <title>table 1</title>
    <entry/>
  </section>
  <section>
    <title>table 2</title>
  </section>
  <section>
    <title>table 3</title>
    <entry/>
    <entry/>
  </section>
</component>

以及生成的样式表:

<xsl:stylesheet
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/component">
    <ul>
      <xsl:apply-templates select="section">
        <xsl:sort select="count(entry) = 0"/>
      </xsl:apply-templates>
    </ul>
  </xsl:template>

  <xsl:template match="section[entry]">
    <li>
      <xsl:value-of select="title"/>
      <xsl:text> (</xsl:text>
      <xsl:value-of select="count(entry)"/>
      <xsl:text>)</xsl:text>
    </li>
  </xsl:template>

  <xsl:template match="section[not(entry)]">
    <li>
      <div id="zero"><xsl:value-of select="title"/></div>
    </li>
  </xsl:template>
</xsl:stylesheet>

以下是我得到的输出:

<ul>
   <li>table 1 (3)</li>
   <li>table 3 (2)</li>
   <li>
      <div id="zero">table 2</div>
   </li>
</ul>

再次感谢Dimitre建议他做出的解决方案。我喜欢<xsl:apply-templates/>而不是<xsl:for-each/>,因为他们觉得XSL更具有声明性,而且对于我来自强制性的脚本和编程背景,我感到有点不舒服。

谢谢你,
扎卡里