代码之家  ›  专栏  ›  技术社区  ›  Bartosz

XSLT 1.0-构建一个XML电子表格,其中有两个基于单独XML元素的表

  •  1
  • Bartosz  · 技术社区  · 7 年前

    <Root>
    <DetailsTable>
        <row data="1"/>
        <row data="2"/>
        <row data="3"/>
        <row data="4"/>
        <row data="5"/>
        <row data="6"/>
        <row data="7"/>
        <row data="8"/>
        <row data="9"/>
        <row data="10"/>
        <row data="11"/>
        <row data="12"/>
        <row data="13"/>
        <row data="14"/>
    </DetailsTable>
    
    <SummaryTable>
        <row data="A"/>
        <row data="B"/>
        <row data="C"/>
    </SummaryTable>    
    </Root>
    

    所需的输出应该在Excel工作表中分为两个单独的“表”,其中一个在另一个中间,如屏幕截图所示:

    enter image description here

    问题是,在XSLT转换中,我需要一行一行地打印行,所有单元格都必须在打印行时打印-因此,对于某些行(例如索引4、5、6、7),我需要添加一些特殊单元格,从 SummaryTable XML元素。

    换句话说,输出XML格式类似于:

        <Table>
       <Row>
        <Cell><Data >DetailsTable</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >1</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >2</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >3</Data></Cell>
        <Cell><Data >SummaryTable</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >4</Data></Cell>
        <Cell><Data >A</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >5</Data></Cell>
        <Cell><Data >B</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >6</Data></Cell>
        <Cell><Data >C</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >7</Data></Cell>
       </Row>
       <Row>
        <Cell><Data >8</Data></Cell>
       </Row>
       <Row>
    </Table>
    

    position()

    for-each 永远不会迭代到索引4、5、6、7,因此不会打印我的摘要表-这种情况下的预期输出应该是:

    enter image description here

    为每个人 在上再次循环 DetailsTable/row 元素,但跳过前7个指数位置,但这似乎是一个令人讨厌的解决办法。

    还有其他想法吗?

    0 回复  |  直到 7 年前
        1
  •  2
  •   Tim C    7 年前

    一种解决方案是使用递归模板,该模板会增加一个行号,直到到达detail行或summary行的末尾,具体取决于哪个行的值更大。

    试试这个XSLT:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:param name="firstSummaryRow" select="4" />
    
      <xsl:variable name="lastDetailRow" select="1 + count(/*/DetailsTable/row)" />
      <xsl:variable name="lastSummaryRow" select="$firstSummaryRow + count(/*/SummaryTable/row)" />
    
      <xsl:template match="/*">
        <xsl:call-template name="Rows" />
      </xsl:template>
    
      <xsl:template name="Rows">
        <xsl:param name="rowNumber" select="1" />
        <Row>
          <Cell>
            <Data>
              <xsl:choose>
                <xsl:when test="$rowNumber = 1">Details Table</xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="DetailsTable/row[position() = $rowNumber - 1]/@data" />
                </xsl:otherwise>
              </xsl:choose>
            </Data>
          </Cell>
          <xsl:if test="$rowNumber >= $firstSummaryRow and $rowNumber &lt;= $lastSummaryRow">
            <Cell Index="3">
              <Data>
                <xsl:choose>
                  <xsl:when test="$rowNumber = $firstSummaryRow">Summary Table</xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="SummaryTable/row[position() = $rowNumber - $firstSummaryRow]/@data" /> 
                  </xsl:otherwise>
                </xsl:choose>
              </Data>
            </Cell>
          </xsl:if>
        </Row>
        <xsl:if test="$rowNumber &lt; $lastDetailRow or $rowNumber &lt; $lastSummaryRow">
          <xsl:call-template name="Rows">
            <xsl:with-param name="rowNumber" select="$rowNumber + 1" />
          </xsl:call-template>
        </xsl:if>
      </xsl:template>
    </xsl:stylesheet>
    

    看它在行动 http://xsltfiddle.liberty-development.net/pPzifpd