您好 我正在使用XSLT 1.0。我的输入看起来像,
<table>
<tr>
<td/>
<td/>
<td/>
</tr>
<tr>
<td/>
<td/>
<td/>
</tr>
<tr>
<td/>
<td/>
<td/>
<td/>
</tr>
</table>
我想知道节点中td的最大数量。在这种情况下,td的最大数量是在第3个tr中,所以我的输出应该是4.需要一个模板来执行此操作。提前致谢
答案 0 :(得分:5)
这是一个不使用递归的示例。它只使用xsl:for-each循环遍历TR元素,按每个元素中TD元素的数量排序。第一个是最大值。
最大值放在一个名为 maxCells 的变量中,作为一个例子,它是表格的一个属性。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="table"/>
</xsl:template>
<xsl:template match="table">
<!-- Variable holding the maximum number of cells in a row -->
<xsl:variable name="maxCells">
<xsl:for-each select="tr">
<xsl:sort select="count(td)" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="count(td)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<!-- Copy the table, adding the maximum cells as an attribute -->
<xsl:copy>
<xsl:attribute name="MaxCells">
<xsl:value-of select="$maxCells"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!-- Identity Transform -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当此样式表应用于上面提供的表格HTML时,输出如下:
<table MaxCells="4">
<tr>
<td/>
<td/>
<td/>
</tr>
<tr>
<td/>
<td/>
<td/>
</tr>
<tr>
<td/>
<td/>
<td/>
<td/>
</tr>
</table>
答案 1 :(得分:0)
您需要使用递归。基本上,下面列出的running-max模板针对表的每个tr子元素运行。它首先应用于第一个子tr元素,计算td元素的数量,将其与运行的最大值进行比较,然后继续对后续兄弟元素执行相同操作(如果有)。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:variable name="count">
<xsl:apply-templates select="table"/>
</xsl:variable>
</xsl:template>
<xsl:template match="table">
<xsl:apply-templates select="tr[1]" mode="running-max"/>
</xsl:template>
<xsl:template match="tr" mode="running-max">
<xsl:param name="max" select="'0'"/>
<xsl:variable name="size" select="count(td)"/>
<xsl:variable name="newmax">
<xsl:choose>
<xsl:when test="$size > $max">
<xsl:value-of select="$size"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$max"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="following-sibling::tr">
<xsl:apply-templates select="following-sibling::tr[position()=1]" mode="running-max">
<xsl:with-param name="max" select="$newmax"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$newmax"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
我想知道你是否真的想要计算细胞或列。您认为下表的正确结果是什么?
<table>
<tr><td colspan="2"/><td/></tr>
<tr><td/><td colspan="2"/></tr>
</table>
如果你只计算细胞,那么你期望2 - 这就是之前的答案所提供的。该表实际上有三列,但是,如果您正在寻找(例如converting XHTML tables to CALS时),您需要稍微调整@Tim C的解决方案:替换 count(td)与 sum(td / @colspan)+ count(td [not(@colspan)])一起在&lt; xsl:sort /&gt; 元素和< EM>&LT; XSL:value-of的/&GT;
不幸的是,即使这样,计算也无法在所有情况下提供正确的列数。例如,当给出这个时,它会出现2而不是3:
<table>
<tr><td rowspan="2"/><td/></tr>
<tr><td/><td/></tr>
</table>
我不知道如何解决这个问题。我从来没有在实时数据中看到它(敲木头)。
还有一件事。我的业力不足以评论@Tim C的答案,但我需要写这个以免我忘记:样式表是错误的,因为它在词汇上排序细胞计数(即它认为“120”&lt;“19”&lt;“5 “)所以,如果你有一个包含5个单元格的行,另一个包含10个单元格,那么你将得到5个最大值。通过将 data-type =“number”添加到&lt; xsl:sort /&gt; 标记中,可以轻松解决此问题。
答案 3 :(得分:0)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:variable name="table-temp">
<xsl:apply-templates select="*:table"/>
</xsl:variable>
<xsl:template match="/">
<root>
<xsl:for-each select="$table-temp/table/descendant::tr">
<cout>
<xsl:value-of select="count(child::td)"/>
</cout>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template match="*:table">
<xsl:element name="table">
<xsl:attribute name="style"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*:tbody">
<xsl:element name="tbody">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*:thead">
<xsl:element name="thead">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*:tr">
<xsl:element name="tr">
<xsl:attribute name="style"/>
<xsl:variable name="rowspan">
<xsl:if test="preceding-sibling::*:tr/child::*:td/@rowspan">
<xsl:value-of select="sum(preceding-sibling::*:tr/child::*:td/@rowspan)"/>
</xsl:if>
<xsl:if test="preceding-sibling::*:tr/child::*:th/@rowspan">
<xsl:value-of select="sum(preceding-sibling::*:tr/child::*:th/@rowspan)"/>
</xsl:if>
</xsl:variable>
<xsl:variable name="td-pos" select="preceding-sibling::tr[child::td/@rowspan]/position()"/>
<xsl:variable name="th-pos" select="preceding-sibling::tr[child::th/@rowspan]/position()"/>
<xsl:for-each select="1 to $td-pos[last()]">
<xsl:element name="td"/>
</xsl:for-each>
<xsl:for-each select="1 to $th-pos[last()]">
<xsl:element name="td"/>
</xsl:for-each>
<xsl:if test="child::*:td/@colspan|child::*:th/@colspan">
<xsl:variable name="num">
<xsl:if test="child::*:th/@colspan">
<xsl:value-of select="sum(child::*:th/@colspan)-1"/>
</xsl:if>
<xsl:if test="child::*:td/@colspan">
<xsl:value-of select="sum(child::*:td/@colspan)-1"/>
</xsl:if>
</xsl:variable>
<xsl:for-each select="1 to $num">
<xsl:element name="td">
<xsl:attribute name="style"/>
</xsl:element>
</xsl:for-each>
</xsl:if>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*:td">
<xsl:element name="td">
<xsl:attribute name="style"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*:th">
<xsl:element name="td">
<xsl:attribute name="style"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>