Как получить rowspan с помощью xslt - PullRequest
0 голосов
/ 09 марта 2019

У меня есть XML-файл, который я хочу удалить <td>, когда parent:tr/precedeing-sibling::tr/td[position()]/text() = curent()[position()]/tex() получил его, но я хочу добавить диапазон строк после удаления td.

<table>
    <tr>
        <td>Emp</td>
        <td>Salary</td>
        <td>Id</td>
        <td>Address</td>
        <td>contact</td>
    </tr>
    <tr>
        <td>SIngh</td>
        <td>50000</td>
        <td>01</td>
        <td>Delhi</td>
        <td>0112145</td>
    </tr>
    <tr>
        <td>SIngh</td>
        <td>50000</td>
        <td>02</td>
        <td>033</td>
        <td>045</td>
    </tr>
</table>

<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="td">
    <xsl:variable name="pos" select="count(parent::tr/preceding-sibling::tr//td[ position()]/text() = current()[position()]/text())"/>
    <xsl:choose>
        <xsl:when test="parent::tr/preceding-sibling::tr/td[ position()]/text() = current()[position()]/text()"/>
        <xsl:otherwise>
            <td>
                <xsl:if test="preceding-sibling::*[1][self::td[ position()]]/text() = parent::tr/preceding-sibling::tr/td[ position()]/text()">
                    <xsl:attribute name="rowspan">
                        <xsl:value-of select="$pos"/>
                    </xsl:attribute>
                </xsl:if>
                <xsl:apply-templates/>
            </td>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

1 Ответ

0 голосов
/ 10 марта 2019

Кажется, это довольно сложная задача, которую можно решить в XSLT 3, используя xsl:iterate для обработки каждого столбца с xsl:for-each-group group-adjacent для добавления атрибута rowspan.Чтобы продолжить обработку следующего столбца, я оставил ячейки, которые должны быть удалены во временном результате, но с атрибутом delete, чтобы на последнем шаге их можно было удалить:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:mode name="delete-rows" on-no-match="shallow-copy"/>

  <xsl:template match="td[@delete]" mode="delete-rows"/>

  <xsl:output method="html" html-version="5"/>

  <xsl:template match="table">
      <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:iterate select="1 to count(tr[1]/td)">
              <xsl:param name="rows" select="tr"/>
              <xsl:on-completion>
                  <xsl:apply-templates select="$rows" mode="delete-rows"/>
              </xsl:on-completion>
              <xsl:variable name="col" select="."/>
              <xsl:variable name="new-rows" as="element(tr)*">
                  <xsl:for-each-group select="$rows" group-adjacent="td[$col]">
                      <xsl:choose>
                          <xsl:when test="current-group()[2]">
                              <xsl:apply-templates select="current-group()">
                                  <xsl:with-param name="col" select="$col"/>
                              </xsl:apply-templates>                              
                          </xsl:when>
                          <xsl:otherwise>
                              <xsl:copy-of select="."/>
                          </xsl:otherwise>
                      </xsl:choose>
                  </xsl:for-each-group>                  
              </xsl:variable>
              <xsl:next-iteration>
                  <xsl:with-param name="rows" select="$new-rows"/>
              </xsl:next-iteration>
          </xsl:iterate>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="tr">
      <xsl:param name="col"/>
      <xsl:copy>
          <xsl:copy-of select="td[position() lt $col]"/>
          <xsl:choose>
              <xsl:when test="position() eq 1">
                  <td rowspan="{count(current-group())}">
                      <xsl:copy-of select="td[$col]/node()"/>
                  </td>
               </xsl:when>
               <xsl:otherwise>
                   <td delete="yes"/>
               </xsl:otherwise>
          </xsl:choose>          
          <xsl:copy-of select="td[position() gt $col]"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / jyRYYia

...