XSLT / XPath-计算相邻节点

时间:2019-09-07 20:54:31

标签: xslt xpath

我想将具有行跨度的表从docx-xml转换为html。问题是要计算跨越单元格的数量。我需要html属性“ rowspan”的行数。

在docx-xml中,第一个具有行距的单元格用<span-element/attribute>表示。以下跨度单元格仅由<span-element>表示-没有属性。因此,我需要在<span-elements>之后立即计算<span-element> with attribute的数量。

我需要分别对每列中的单元格进行计数-因为每列中的单元格可以是另一个不同的行跨度。 我也不能只计算一列中<span-element>的总数-因为可以有一个以上的行跨度。

我尝试了不同的方法:我用<xsl:value-of select="count(following-sibling::w:tc[1][//w:vmerge])"/>来数-只要行距只有一次出现就可以了。我试图用for-each-group对相邻节点进行分组,但是不知道如何计算其中的节点。

原始代码的简化结构:

<tbl>
    <tr>
       <tc>...</tc>
       <tc>...</tc>
       <tc>...</tc>
       <tc>...</tc>
     </tr>
     <tr>
       <tc>
      <span-element/start-attribute>
       </tc>
        <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
     <tr>
        <tc>
       <span-element>
    </tc>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
     <tr>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
     <tr>
    <tc>
      <span-element/start-attribute>
       </tc>
    <tc>
      <span-element/start-attribute>
       </tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
     <tr>
    <tc>
      <span-element>
        </tc>
    <tc>
      <span-element>
        </tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
     <tr>
    <tc>
      <span-element>
       </tc>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
     <tr>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
     <tr>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
    <tc>...</tc>
     </tr>
</tbl>

我的模板:

<xsl:template match="tc">
        <xsl:choose>
            <xsl:when test="span-element[@start-attribute]">
                <td>
                    <xsl:attribute name="rowspan">
                        <xsl:value-of select="count(following-sibling::tc[1][span-element])"/>
                    </xsl:attribute>
                    <xsl:value-of select="."/>
                </td>
            </xsl:when>
            <xsl:when test="span-element[not(@start-attribute)]"/>
            <xsl:otherwise>
                <td>
                    <xsl:apply-templates/>
                </td>
            </xsl:otherwise>
        </xsl:choose>

第二个<xsl:when>根据需要的HTML结果删除具有“ span-element”而没有“ start-attribute”的单元格的出现。真实文档中也有gridspan,我以后也需要集成(这就是为什么在下面第四行和第七行提供的实际结果中只比预期的少一个单元格的原因。)

实际结果:

<!DOCTYPE HTML>
<table xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" border="1">
   <tr>
      <th>Zeile 1, Zelle 1</th>
      <th>Zeile 1, Zelle 2</th>
      <th>Zeile 1, Zelle 3</th>
      <th>Zeile 1, Zelle 4</th>
   </tr>
   <tr>
      <td rowspan="3">Zeile 2 + 3, Zelle 1</td>
      <td>Zeile 2, Zelle 2</td>
      <td>Zeile 2, Zelle 3</td>
      <td>Zeile 2, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 3, Zelle 2</td>
      <td>Zeile 3, Zelle 3</td>
      <td>Zeile 3, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 4, Zelle 1</td>
      <td>Zeile 4, Zelle 2 + 3</td>
      <td>Zeile 4, Zelle 4</td>
   </tr>
   <tr>
      <td rowspan="3">Zeile 5 + 6 +7, Zelle 1</td>
      <td rowspan="2">Zeile 5 + 6, Zelle 2</td>
      <td>Zeile 5, Zelle 3</td>
      <td>Zeile 5, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 6, Zelle 3</td>
      <td>Zeile 6, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 7, Zelle 2 + 3</td>
      <td>Zeile 7, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 8, Zelle 1</td>
      <td>Zeile 8, Zelle 2</td>
      <td>Zeile 8, Zelle 3</td>
      <td>Zeile 8, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 9, Zelle 1</td>
      <td>Zeile 9, Zelle 2</td>
      <td>Zeile 9, Zelle 3</td>
      <td>Zeile 9, Zelle 4</td>
   </tr>
</table>

想要的结果:

<!DOCTYPE HTML>
<table xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" border="1">
   <tr>
      <th>Zeile 1, Zelle 1</th>
      <th>Zeile 1, Zelle 2</th>
      <th>Zeile 1, Zelle 3</th>
      <th>Zeile 1, Zelle 4</th>
   </tr>
   <tr>
      <td rowspan="2">Zeile 2 + 3, Zelle 1</td>
      <td>Zeile 2, Zelle 2</td>
      <td>Zeile 2, Zelle 3</td>
      <td>Zeile 2, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 3, Zelle 2</td>
      <td>Zeile 3, Zelle 3</td>
      <td>Zeile 3, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 4, Zelle 1</td>
      <td>Zeile 4, Zelle 2 + 3</td>
      <td>Zeile 4, Zelle 4</td>
   </tr>
   <tr>
      <td rowspan="3">Zeile 5 + 6 +7, Zelle 1</td>
      <td rowspan="2">Zeile 5 + 6, Zelle 2</td>
      <td>Zeile 5, Zelle 3</td>
      <td>Zeile 5, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 6, Zelle 3</td>
      <td>Zeile 6, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 7, Zelle 2 + 3</td>
      <td>Zeile 7, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 8, Zelle 1</td>
      <td>Zeile 8, Zelle 2</td>
      <td>Zeile 8, Zelle 3</td>
      <td>Zeile 8, Zelle 4</td>
   </tr>
   <tr>
      <td>Zeile 9, Zelle 1</td>
      <td>Zeile 9, Zelle 2</td>
      <td>Zeile 9, Zelle 3</td>
      <td>Zeile 9, Zelle 4</td>
   </tr>
</table>

1 个答案:

答案 0 :(得分:0)

在XSLT / XPath 1.0上下文中,遍历跟随轴对分组相邻点更好。当前组中节点的选择和后续组中节点的选择通过Kayian方法与设置操作结合在一起。

此样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
  <xsl:strip-space elements="*"/>
  <xsl:template match="node()|@*">
      <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="span-element[@start-attribute]"/>
  <xsl:template match="tc[span-element[not(@start-attribute)]]"/>
  <xsl:template match="tc">
    <td>
        <xsl:apply-templates select="." mode="rowspan">
            <xsl:with-param name="position" select="position()"/>
        </xsl:apply-templates>
        <xsl:apply-templates select="@*|node()"/>
    </td>
  </xsl:template>

  <xsl:template match="node()" mode="rowspan"/>
  <xsl:template match="tc[span-element/@start-attribute]" mode="rowspan">
      <xsl:param name="position"/>
      <xsl:variable 
        name="followings" 
        select="../following-sibling::tr/tc[$position]/span-element"/>
      <xsl:variable 
        name="mark" 
        select="$followings[@start-attribute][1]"/>
      <xsl:attribute name="rowspan">
          <xsl:value-of 
          select="count($followings[count(.|$mark|$mark/following::*)
                                    !=count($mark|$mark/following::*)]) + 1"/>
      </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

使用此格式的输入:

<tbl>
    <tr>
       <tc>...</tc>
       <tc>...</tc>
       <tc>...</tc>
       <tc>...</tc>
     </tr>
     <tr>
       <tc>
         <span-element start-attribute=""/>
       </tc>
       <tc>...</tc>
       <tc>...</tc>
       <tc>...</tc>
     </tr>
     <tr>
        <tc>
         <span-element/>
        </tc>
        <tc>...</tc>
        <tc>...</tc>
        <tc>...</tc>
     </tr>
     <tr>
       <tc>...</tc>
       <tc>...</tc>
       <tc>...</tc>
       <tc>...</tc>
     </tr>
     <tr>
       <tc>
        <span-element start-attribute=""/>
       </tc>
       <tc>
        <span-element start-attribute=""/>
       </tc>
       <tc>...</tc>
       <tc>...</tc>
     </tr>
     <tr>
      <tc>
        <span-element/>
      </tc>
      <tc>
       <span-element/>
      </tc>
      <tc>...</tc>
      <tc>...</tc>
     </tr>
     <tr>
      <tc>
        <span-element/>
      </tc>
      <tc>...</tc>
      <tc>...</tc>
      <tc>...</tc>
     </tr>
     <tr>
      <tc>...</tc>
      <tc>...</tc>
      <tc>...</tc>
      <tc>...</tc>
     </tr>
     <tr>
      <tc>...</tc>
      <tc>...</tc>
      <tc>...</tc>
      <tc>...</tc>
     </tr>
</tbl>

输出:

<tbl>
   <tr>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td rowspan="2"/>
      <td>...</td>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td>...</td>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td rowspan="3"/>
      <td rowspan="2"/>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td>...</td>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
   </tr>
   <tr>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
   </tr>
</tbl>

注意:这假设输入源具有正确的堡垒(例如,没有重叠)。

相关问题