You must find the table row that has the maximum number of table elements

Hi I am using XSLT 1.0. My input is as follows:

<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 a node. In this case, the maximum number td is in the third tr, so my output should be 4. I need to create a template for this. thanks in advance

+3
source share
4 answers

You need to use recursion. Basically, the running-max pattern below is run for each tr of the table's child. It is first applied to the first child of tr, calculates the number of td elements, compares it with the current max and then continues to do the same for the next siblings, if 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 &gt; $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>
0

, . 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>
+5

, , , . ?

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

, 2 - , . , , , (, XHTML CALS), @Tim C a : count (td) (td/@colspan) + count (td [not (@colspan)]) < xsl: sort/ > < xsl: - > .

, . , 2 3:

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

, . ( ).

One more thing. My karma is not enough to comment on @Tim C's answer, but I need to write this so that I don’t forget: the stylesheet is incorrect in that it sorts the number of cells lexically (that is, it thinks "120" <"19" <5 " ), so if you have a row with 5 cells and another with 10, you get a maximum of 5. This can be easily fixed by adding the data type = "number" to the <xsl: sort /> tag.

0
source
<?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>
0
source

All Articles