通过在XSLT中开始/结束属性值来计算元素

时间:2013-12-08 10:34:50

标签: xml xslt

当前XML

<table>
    <tr>
        <tc rowspan="start">content</tc>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc rowspan="end"/>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc rowspan="end"/>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc>content</tc>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
</table>

所需的输出

<table>
    <tr>
        <tc rowspan="3">content</tc>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>

        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>

        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc>content</tc>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>

</table>

文档中可能有多个带有rowspans的表,并且同一个表中有多个带有rowspan的单元格,因此仅使用rowspan属性计算以下silbings是不够的。相反,我需要计算所有后续兄弟姐妹,直到下一个rowspan="start"发生。

我假设有一个for-each-group解决方案,但无法弄清楚细节。

此外,同一rowspan中可以有多个tr

XML示例是:

<table>
    <tr>
        <tc rowspan="start">content</tc>
        <tc rowspan="start">content</tc>
        <tc>content</tc>
    </tr>
    <tr>
        <tc rowspan="end">content</tc>
        <tc rowspan="end">content</tc>
        <tc>content</tc>
    </tr>
    <tr>
        <tc rowspan="end">content</tc>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc>content</tc>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc>content</tc>        
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
</table>

所需的输出将是:

<table>
    <tr>
        <tc rowspan="3">content</tc>
        <tc rowspan="2">content</tc>
        <tc>content</tc>
    </tr>
    <tr>


        <tc>content</tc>
    </tr>
    <tr>

        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc>content</tc>
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
    <tr>
        <tc>content</tc>        
        <tc>content</tc>        
        <tc>content</tc>
    </tr>
</table>

1 个答案:

答案 0 :(得分:1)

使用编辑后的输入样本,我认为使用

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

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

<xsl:template match="table">
  <xsl:copy>
    <xsl:for-each-group select="tr" group-adjacent="boolean(tc/@rowspan)">
      <xsl:choose>
        <xsl:when test="current-grouping-key()">
           <xsl:for-each-group select="current-group()" group-starting-with="tr[tc[@rowspan = 'start']]">
              <xsl:apply-templates select="current-group()"/>
           </xsl:for-each-group>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="current-group()"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

<xsl:template match="tr/tc[@rowspan = 'start']">
  <tc rowspan="{count(current-group())}">
    <xsl:apply-templates/>
  </tc>
</xsl:template>

<xsl:template match="tc[@rowspan = 'end']"/>

</xsl:stylesheet>

应该给出正确的结果。

我仍然不确定这是否能解决您的问题,因为到目前为止我们还没有看到更复杂的输入样本。