需要找到具有最大表格单元格数的表格行

发布于 2024-10-25 18:34:33 字数 380 浏览 1 评论 0原文

你好 我正在使用 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。需要一个模板来执行此操作。提前致谢

Hi
I am using XSLT 1.0. My input looks like,

<table>
<tr>
  <td/>
  <td/>
  <td/>
</tr>
<tr>
  <td/>
  <td/>
  <td/>
</tr>
<tr>
  <td/>
  <td/>
  <td/>
  <td/>
</tr>
</table>

I want to know the maximum number of td in node. In this case, the maximum number of td is in 3rd tr and so my output should be 4. Need a template to do this. Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

云雾 2024-11-01 18:34:33

这是一个不使用递归的示例。它仅使用 xsl:for-each 循环遍历 TR 元素,并按每个元素中 TD 元素的数量排序。第一个是最大值。

最大值被放入一个名为 ma​​xCells 的变量中,作为示例,该变量被设为表的属性。

<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>

Here is an example which does not use recursion. It just uses an xsl:for-each to loop through the TR elements, ordering by the number of TD elements in each. The first one is then the maximum.

The maximum is put in a variable, called maxCells which, as an example, is made an attribute of the table.

<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>

When this stylesheet is applied to the provided table HTML above, the output is as follows:

<table MaxCells="4">
    <tr>
        <td/>
        <td/>
        <td/>
    </tr>
    <tr>
        <td/>
        <td/>
        <td/>
    </tr>
    <tr>
        <td/>
        <td/>
        <td/>
        <td/>
    </tr>
</table>
贪了杯 2024-11-01 18:34:33

我想知道您是否真的想计算单元格或列的数量。您认为下表的正确结果是什么?

<table>
    <tr><td colspan="2"/><td/></tr>
    <tr><td/><td colspan="2"/></tr>
</table>

如果您只是计算细胞数,那么您期望的是 2 - 这就是前面两个答案所提供的。然而,该表实际上有三列,所以如果这就是您正在寻找的内容(例如转换 XHTML表到 CALS),您需要稍微调整 @Tim C 的解决方案:将 count(td) 替换为 sum(td/@colspan) + count(td[not(@ colspan)]) 都在 元素和 中。

不幸的是,即使这样,计算也无法在所有情况下提供正确的列计数。例如,当给出以下内容时,它会得出 2 而不是 3:

<table>
    <tr><td rowspan="2"/><td/></tr>
    <tr><td/><td/></tr>
</table>

我不知道如何解决这个问题。我也从未在实时数据中看到过它(敲木头)。

还有一件事。我的业力不足以评论@Tim C的答案,但我需要写下这个以免我忘记:样式表是错误的,因为它按词法对单元格计数进行排序(即它认为“120”<“19”<“5”) ") 因此,如果您的一行有 5 个单元格,另一行有 10 个单元格,那么您最多会得到 5 个单元格。通过将 data-type="number" 添加到 标记即可轻松解决此问题。

I'd like to know if you are really trying to count cells or rather columns. What would you consider the correct result for the following table?

<table>
    <tr><td colspan="2"/><td/></tr>
    <tr><td/><td colspan="2"/></tr>
</table>

If you're just counting cells then you expect 2 - and that's what both previous answers provide. The table has actually three columns, however, so if that's what you're looking for (like when converting XHTML tables to CALS) you need to tweak @Tim C's solution a bit: replace count(td) with sum(td/@colspan) + count(td[not(@colspan)]) both in the <xsl:sort/> element and in the <xsl:value-of/>.

Unfortunately, even then the calculation fails to provide correct column counts in all cases. For example, it comes up with 2 instead of 3 when given this:

<table>
    <tr><td rowspan="2"/><td/></tr>
    <tr><td/><td/></tr>
</table>

I have no idea how to solve that one. I've never seen it in live data either (knock on wood).

One more thing. My karma is not sufficient to comment on @Tim C's answer but I need to write this lest I forget: the stylesheet is wrong in that it sorts the cell counts lexically (i.e. it thinks "120"<"19"<"5") so if you have a row with 5 cells and another one with 10 you will get 5 as maximum. This is easy to fix by adding data-type="number" to the <xsl:sort/> tag.

烟沫凡尘 2024-11-01 18:34:33

你需要使用递归。基本上,下面列出的 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>

You need to use recursion. Basically, the running-max template listed below runs for every tr child element of a table. It is first applied for the first child tr element, calculates the number of td elements, compares it to a running max, and then continues to do the same for following siblings, if there are any.

<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>
秋千易 2024-11-01 18:34:33
<?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>
<?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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文