开发者

Xslt how to style conditional odd/even rows

I've an html table written using xslt transformation that looks like this

<table>
    <xsl:for-each select="someNode">
        <xsl:if test开发者_JAVA技巧="testThis">
            <tr>
                <!-- <xsl:call-template name="conditionalRowStyle"/> -->
                <td>something</td>
            </tr>
         </xsl:if>
         <tr>
             <!-- <xsl:call-template name="conditionalRowStyle"/> -->
             <td>this is always displayed</td>
         </tr>
         <xsl:if test="testThis2">
            <tr>
                <!-- <xsl:call-template name="conditionalRowStyle"/> -->
                <td>something 2</td>
            </tr>
         </xsl:if>
         ....
    </xsl:for-each>
    <tr>
        <!-- <xsl:call-template name="conditionalRowStyle"/> -->
        <td>this is always displayed</td>
    </tr>
</table>

I need a way to apply different classes oddRow/evenRow to tr elems.

<tr class="evenRow"> or <tr class="oddRow">

I tried to use a template like this after every <tr> elem

<xsl:template name="conditionalRowStyle">
    <xsl:attribute name="class">
        <xsl:choose>
            <xsl:when test="(count(../preceding-sibling::tr) mod 2) = 0">oddrow</xsl:when>
            <xsl:otherwise>evenrow</xsl:otherwise>
        </xsl:choose>
    </xsl:attribute>
</xsl:template>

but this is not working. any idea?


You could probably get away with doing this in just css

tr:nth-child(odd) {
    /*...*/
}
tr:nth-child(odd) {
    /*...*/
}

If you cannot, you could do something like

<xsl:attribute name="class">
    <xsl:choose>
        <xsl:when test="(position() mod 2) != 1">
            <xsl:text>evenRow</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>oddRow</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:attribute>

Note that i wrote this in the SO textbox and haven't tested it.


This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vrtfTrs">
  <tr>
    <td>something</td>
  </tr>
  <tr>
    <td>This is always displayed</td>
  </tr>
  <tr>
    <td>something 2</td>
  </tr>
 </xsl:variable>

 <xsl:variable name="vTrs" select="ext:node-set($vrtfTrs)/*"/>

 <xsl:template match="/nums">
  <html>
    <table>
      <xsl:apply-templates select="num[1]"/>
    </table>
  </html>
 </xsl:template>

 <xsl:template match="num">
   <xsl:param name="pCount" select="0"/>

   <xsl:variable name="vTest1" select=". mod 4 = 1"/>
   <xsl:variable name="vTest2" select=". mod 4 = 2"/>

   <xsl:apply-templates select="$vTrs[1][$vTest1]">
     <xsl:with-param name="pCount" select="$pCount +1"/>
     <xsl:with-param name="pnodevalue" select="."/>
   </xsl:apply-templates>

   <xsl:apply-templates select="$vTrs[2]">
     <xsl:with-param name="pCount" select="$pCount+$vTest1 +1"/>
     <xsl:with-param name="pnodevalue" select="."/>
   </xsl:apply-templates>

   <xsl:apply-templates select="$vTrs[3][$vTest2]">
     <xsl:with-param name="pCount" select="$pCount+$vTest1 +2"/>
     <xsl:with-param name="pnodevalue" select="."/>
   </xsl:apply-templates>

   <xsl:apply-templates select="following-sibling::*[1]">
     <xsl:with-param name="pCount"
          select="$pCount+1+$vTest1+$vTest2"/>
     <xsl:with-param name="pnodevalue" select="."/>
   </xsl:apply-templates>

   <xsl:if test="not(following-sibling::*)">
       <xsl:apply-templates select="$vTrs[2]">
         <xsl:with-param name="pCount" select="$pCount+1+$vTest1+$vTest2"/>
         <xsl:with-param name="pnodevalue" select="."/>
       </xsl:apply-templates>
   </xsl:if>
 </xsl:template>

 <xsl:template match="tr">
  <xsl:param name="pCount"/>
  <xsl:param name="pnodevalue"/>

  <tr class="{concat(substring('even', 1 div ($pCount mod 2 = 0)),
                     substring('odd', 1 div ($pCount mod 2 = 1))
                     )}">
    <xsl:comment>&lt;num><xsl:value-of select="$pnodevalue"/>&lt;/num></xsl:comment>
    <xsl:copy-of select="node()"/>
  </tr>
 </xsl:template>
</xsl:stylesheet>

when applied on this XML document:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

produces the wanted result:

<html>
   <table>
      <tr class="odd">
         <!--<num>01</num>-->
         <td>something</td>
      </tr>
      <tr class="even">
         <!--<num>01</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="odd">
         <!--<num>02</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="even">
         <!--<num>02</num>-->
         <td>something 2</td>
      </tr>
      <tr class="odd">
         <!--<num>03</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="even">
         <!--<num>04</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="odd">
         <!--<num>05</num>-->
         <td>something</td>
      </tr>
      <tr class="even">
         <!--<num>05</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="odd">
         <!--<num>06</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="even">
         <!--<num>06</num>-->
         <td>something 2</td>
      </tr>
      <tr class="odd">
         <!--<num>07</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="even">
         <!--<num>08</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="odd">
         <!--<num>09</num>-->
         <td>something</td>
      </tr>
      <tr class="even">
         <!--<num>09</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="odd">
         <!--<num>10</num>-->
         <td>This is always displayed</td>
      </tr>
      <tr class="even">
         <!--<num>10</num>-->
         <td>something 2</td>
      </tr>
      <tr class="even">
         <!--<num>10</num>-->
         <td>This is always displayed</td>
      </tr>
   </table>
</html>

Do note:

  1. We are using the most fine-grained traversal and processing of an XML document -- node by node. After the identity transformation this is the second most important XSLT design pattern.

  2. The rest of the small tricks are not that important.


It looks like the conditionalRowStyle template to add styles to the table is in the same stylesheet as the one building the table. If that's the case, then it will not work as expected, since the nodes selected in the conditionalRowStyle template will be from the source document (containing someNode) and not the target document (where the generated table elements are.)

You can "hack" this by collecting the table output of the someNode templates to a variable first, which you can then run the conditionalRowStyle template on first before finally outputting the variable value as the result of the stylesheet. But it's much simpler to use two stylesheets, that you run one after the other in a pipeline. The first stylesheet converts the someNode data to a table, and the second applies conditionalRowStyle formatting to the table.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜