我正在使用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>
答案 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 > 0
的项目和zero
count = 0
模板。
<xsl:apply-templates select="n1:title[count(../n1:entry) > 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更具有声明性,而且对于我来自强制性的脚本和编程背景,我感到有点不舒服。
谢谢你,
扎卡里