我有一个包含大约150个条目的xml文档。我正在以几种方式对条目进行排序。一个是按字母顺序排列的,通过XSLT显示并且工作得很好,其他的是按类别和解决方案,这些问题是按行交替显示颜色。
当我迭代未显示的条目时,问题出现了,即使它们没有显示,它们似乎也被包含在计数中。我曾经在匿名用户面前问过这个问题,希望这次我更清楚。
感谢您的帮助。
XML Doc。
<case-studies>
<!-- #### X #### -->
<case-study>
<name>Entry 1</name>
<category solution="Performance">Medical</category>
<category solution="Medical">Security</category>
<category solution="Industry">Medical</category>
<category solution="A-Z">X</category>
</case-study>
<!-- #### Y #### -->
<case-study>
<name>Entry 2</name>
<category solution="Industry">Education</category>
<category solution="Convergence">Education</category>
<category solution="A-Z">Y</category>
</case-study>
</case-studies>
XSLT电话
<%
Dim mm_xsl As MM.XSLTransform = new MM.XSLTransform()
mm_xsl.setXML(Server.MapPath("/data/xml/case-studies/case-studiesTest.xml"))
mm_xsl.setXSL(Server.MapPath("/data/xslt/case-studies/categoryLandingOther.xsl"))
mm_xsl.addParameter("solName", "Industry")
mm_xsl.addParameter("catName", "Business services")
Response.write(mm_xsl.Transform())
%>
xslt的部分
<xsl:for-each select="case-studies/case-study/category[. = $catName]">
<!--xsl:sort select="../name" /-->
<xsl:if test="@solution[. = $solName]">
<tr>
<xsl:if test="(position() mod 2 = 1)">
<xsl:attribute name="bgcolor">#e7e7e7</xsl:attribute>
</xsl:if>
<td class="cell1">
</td>
<td class="cell2" style="padding-top:2px;">» <a href="{../url}"><xsl:value-of select="../name"/></a></td>
<td class="cell3">
<xsl:for-each select="../solutionType">
<div class="clearRight"><xsl:value-of select="."/></div>
</xsl:for-each>
</td>
</tr>
</xsl:if>
</xsl:for-each>
答案 0 :(得分:2)
首先:尽量避免<xsl:for-each>
。 It's a bad choice most of the time.
第二步:仅选择要输出的节点,行替换将起作用:
<xsl:template match="/case-studies">
<xsl:apply-templates select="case-study[
category = $catName
and
category/@solution = $solName
]">
<xsl:sort select="name" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="case-study">
<tr>
<xsl:if test="position() mod 2 = 1">
<xsl:attribute name="bgcolor">#e7e7e7</xsl:attribute>
</xsl:if>
<td class="cell1" />
<td class="cell2" style="padding-top:2px;">
<xsl:text>» </xsl:text>
<a href="{url}"><xsl:value-of select="name"/></a>
</td>
<td class="cell3">
<xsl:apply-templates select="solutionType" />
</td>
</tr>
</xsl:template>
<xsl:template match="solutionType">
<div class="clearRight">
<xsl:value-of select="."/>
</div>
</xsl:template>
编辑:
您可以使用<xsl:key>
来加快选择过程,但如果您在同一转换过程中反复查询相同的数据,这只会产生积极影响。
<xsl:key name="kCaseStudy"
match="case-study"
use="concat(category, category/@solution)"
/>
<!-- no need to be in "/case-studies" context this time -->
<xsl:template match="/">
<xsl:apply-templates select="key('kCaseStudy', concat($catName, $solName))">
<xsl:sort select="name" />
</xsl:apply-templates>
</xsl:template>
<!-- ... code that uses "key('kCaseStudy', ...)" again ... -->
答案 1 :(得分:1)
@Tomalak 总是打败我(有更好更详细的答案)!
行交替的问题在于两行:
<xsl:for-each select="case-studies/case-study/category[. = $catName]">
和
<xsl:if test="@solution[. = $solName]">
您会选择与上述谓词条件匹配的节点集。处理器会记住此循环的其余部分。然后,您应用另一个条件,进一步限制处理的节点(但不循环)。
使用position()
函数测试循环内的位置...它保留总数。节点与<xsl:for...
循环匹配的节点(不排除<xsl:if
条件过滤掉的节点。)
解决方案是结合xsl:for-each
和xsl:if
条件:
<xsl:for-each select="case-study/category[. = $catName and @solution = $solName]">
当然,这种解释只是为了说明这一点。 Tomalak关于避免使用for-each的观点是非常有效的,他的解决方案非常棒。