XSLT 1.0 - создание электронной таблицы XML с двумя таблицами на основе отдельных элементов XML - PullRequest
1 голос
/ 06 марта 2019

Мне нужно создать файл XML Spreadsheet (SpreadsheetML) в определенном формате из документа XML, который содержит данные, структурированные в отдельные элементы (с использованием XSLT 1.0). Упрощенный образец ниже:

<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) Мне нужно добавить несколько специальных ячеек, значения которых я получу из XML-элемента SummaryTable.

Другими словами, выходной формат 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

Я думал о выполнении цикла for-each определенное количество раз (например, 7), чтобы я распечатал первые семь строк вместе со сводной таблицей, а затем снова выполнил цикл for-each на DetailsTable/row элементы, но пропускают первые 7 позиций индекса, но это выглядит как неприятный обходной путь.

Есть еще идеи?

1 Ответ

2 голосов
/ 06 марта 2019

Одним из решений, хотя оно и выглядит не очень элегантно, является использование рекурсивного шаблона, который увеличивает номер строки до тех пор, пока не достигнет конца строк подробностей или сводки, в зависимости от того, что больше.

Попробуйте это 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

...