Xslt 需要查找具有最大表单元格数的表行
嗨 我正在使用XSLT1.0。我的输入看起来像Xslt 需要查找具有最大表单元格数的表行,xslt,Xslt,嗨 我正在使用XSLT1.0。我的输入看起来像 <table> <tr> <td/> <td/> <td/> </tr> <tr> <td/> <td/> <td/> </tr> <tr> <td/> <td/> <td/> <td/> </tr> <
<table>
<tr>
<td/>
<td/>
<td/>
</tr>
<tr>
<td/>
<td/>
<td/>
</tr>
<tr>
<td/>
<td/>
<td/>
<td/>
</tr>
</table>
我想知道节点中td的最大数量。在这种情况下,td的最大数量在第3个tr中,因此我的输出应该是4。需要一个模板来完成此操作。提前感谢您需要使用递归。基本上,下面列出的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>
下面是一个不使用递归的示例。它只使用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>
我想知道您是否真的在尝试计数单元格或列。你认为下表的正确结果是什么?
<table>
<tr><td colspan="2"/><td/></tr>
<tr><td/><td colspan="2"/></tr>
</table>
如果你只是在计算细胞数,那么你期望有2个——这就是前面两个答案所提供的。然而,该表实际上有三列,因此如果这是您正在寻找的(比如什么时候),那么您需要稍微调整@Tim C的解决方案:在元素和元素中用sum(td/@colspan)+count(td[not(@colspan)]替换count(td)
不幸的是,即使这样,计算也无法在所有情况下提供正确的列计数。例如,当给定以下条件时,它会得到2而不是3:
<table>
<tr><td rowspan="2"/><td/></tr>
<tr><td/><td/></tr>
</table>
我不知道如何解决这个问题。我也从未在实时数据中见过它(敲敲木头)
还有一件事。我的因果报应不足以对@Tim C的答案发表评论,但我需要写下这句话以免忘记:样式表是错误的,因为它按词汇对单元格计数进行排序(即,它认为“120”
我只想让表模板中变量的最大td数与自身匹配。如何重写它。在变量中捕获结果。@Wilred Springer:递归是不必要的,正如@Tim-C的答案所示。他的解决方案也是更有效的。@vignesh:我建议使用非递归解决方案。我必须同意th Dimitre的评论。尽管如此,我将在这里留下我的答案供将来参考;在某些情况下,您只需要递归。@vingesh为+1。对于每个解决方案,您唯一不能使用xsl的两种情况是:(a)您没有XPath表达式范围之外的节点序列(b)值函数步骤。对于(a)您可以使用最大计算组合标记化。对于(b)您可以运行两阶段转换。这!再加上一些表模型,您还有更多行可以添加列。。。
<?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>