XML XSL问题

时间:2009-05-27 17:24:24

标签: xml xslt xhtml

我有一个包含大约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>

2 个答案:

答案 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-eachxsl:if条件:

<xsl:for-each select="case-study/category[. = $catName and @solution = $solName]">

当然,这种解释只是为了说明这一点。 Tomalak关于避免使用for-each的观点是非常有效的,他的解决方案非常棒。