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><num><xsl:value-of select="$pnodevalue"/></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:
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.
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.
精彩评论