Нужно найти строку таблицы с максимальным количеством ячеек таблицы - PullRequest
3 голосов
/ 23 марта 2011

Привет Я использую XSLT 1.0. Мой вход выглядит как

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

Я хочу знать максимальное количество тд в узле. В этом случае максимальное количество td находится в 3-м tr, и поэтому мой вывод должен быть 4. Для этого нужен шаблон. Заранее спасибо

Ответы [ 4 ]

5 голосов
/ 23 марта 2011

Вот пример, который не использует рекурсию.Он просто использует 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>
0 голосов
/ 24 декабря 2012
<?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 голосов
/ 28 августа 2011

Я хотел бы знать, действительно ли вы пытаетесь сосчитать ячейки или, вернее, столбцы.Что бы вы посчитали правильным результатом для следующей таблицы?

<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.Это легко исправить, добавив <em>data-type = "number" к тег.

0 голосов
/ 23 марта 2011

Вам нужно использовать рекурсию.В основном, шаблон 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 &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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...