Динамические строки XSL & XML с пустыми ячейками - PullRequest
0 голосов
/ 31 августа 2018

Я очень плохо знаком с XSL и пытаюсь построить таблицу в следующей структуре: enter image description here

Я использую этот XML:

<CARS>
    <CAR>
        <CAR_NUM>65</CAR_NUM>
        <DRIVERS>
            <DRIVER>
                <DRIVER_NUM>123</DRIVER_NUM>
                <DRIVER_NAME>STEVE RODGERS</DRIVER_NAME>
            </DRIVER>
        </DRIVERS>
        <STATS>
            <STAT>
                <LAP>1</LAP>
                <TIME>3:21:10</TIME>
            </STAT>
            <STAT>
                <LAP>2</LAP>
                <TIME>3:21:07</TIME>
            </STAT>
        </STATS>
    </CAR>
    <CAR>
        <CAR_NUM>22</CAR_NUM>

        <DRIVERS>
            <DRIVER>
                <DRIVER_NUM>143</DRIVER_NUM>
                <DRIVER_NAME>TONY STARK</DRIVER_NAME>
            </DRIVER>
            <DRIVER>
                <DRIVER_NUM>155</DRIVER_NUM>
                <DRIVER_NAME>JAMES RHODES</DRIVER_NAME>
            </DRIVER>
        </DRIVERS>

        <STATS>
            <STAT>
                <LAP>1</LAP>
                <TIME>3:22:39</TIME>
            </STAT>
            <STAT>
                <LAP>2</LAP>
                <TIME>3:19:17</TIME>
            </STAT>
            <STAT>
                <LAP>3</LAP>
                <TIME>3:15:46</TIME>
            </STAT>
            <STAT>
                <LAP>4</LAP>
                <TIME>3:17:22</TIME>
            </STAT>
        </STATS>
    </CAR>
</CARS>

Невозможно иметь больше водителей, чем кругов. Вложение таблицы в CAR NUMBER все испортило для меня, потому что я не знаю, как рекурсивно генерировать пустые поля (я предполагаю) с использованием XSL.

Я знаю, что моя первая попытка далеко, но вот она ...

<table>
    <xsl:for-each select="CARS/CAR">
    <tr>
        <td><xsl:value-of select="CAR_NUM"/>
        </td>
        <xsl:for-each select="DRIVERS/DRIVER">
        <td><xsl:value-of select="DRIVER_NUM"/>
        </td>
        <td><xsl:value-of select="DRIVER_NAME"/>
        </td>
        </xsl:for-each>
        <xsl:for-each select="STATS/STAT">
        <td><xsl:value-of select="LAP"/>
        </td>
        <td><xsl:value-of select="TIME"/>
        </td>
        </xsl:for-each>
        </tr>
        </xsl:for-each>
</table>

Эта попытка приводит к:

65 123 СТИВ РОДЖЕРС 1 3:21:10 2 3: 21: 07

22 143 Тони Старк 155 Джеймс Роудс 1 3:22:39 2 3:19:17 3 3:15:46 4 3: 17: 22 * ​​1018 *

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

EDIT: Исследуя его, я считаю, что мне нужно проанализировать XML как иерархические уровни:

Tier 1: CAR_NUM
Tier 2: DRIVER_NUM, DRIVER_NAME
Tier 3: LAP, TIME

Мне нужно вложить пару если после запуска первой записи:

T1->T2->T3 - End the row, then test for next record in T2 (if found go to T2)
T2->T3 - End the row, then test for next record in T2 (if not found, go T3)
T3

1 Ответ

0 голосов
/ 01 сентября 2018

Как указано в комментарии, я не совсем понял, как соотносить гонщиков с кругами, если соотношение просто так, что все гонщики, кроме последнего, делают только один круг, а последний гонщик делает все оставшиеся круги, то вы можете реализовать что следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
        <style>
            th, td { vertical-align: top }
        </style>
      </head>
      <body>
          <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="CARS">
      <table>
          <thead>
              <tr>
                  <th>CAR NUMBER</th>
                  <th>DRIVER NUMBER</th>
                  <th>DRIVER NAME</th>
                  <th>LAP</th>
                  <th>TIME</th>
              </tr>
          </thead>
          <xsl:apply-templates select="CAR"/>
      </table>
  </xsl:template>

  <xsl:template match="CAR">
      <tbody>
          <xsl:apply-templates select="STATS/STAT"/>
      </tbody>
  </xsl:template>

  <xsl:template match="STAT">
      <tr>
          <xsl:call-template name="create-cells"/>
      </tr>
  </xsl:template>

  <xsl:template match="STAT[1]">
      <tr>
          <td rowspan="{count(../STAT)}">
              <xsl:value-of select="ancestor::CAR/CAR_NUM"/>
          </td>
          <xsl:call-template name="create-cells"/>
      </tr>
  </xsl:template>

  <xsl:template name="create-cells">
      <xsl:variable name="pos" select="position()"/>
      <xsl:apply-templates select="ancestor::CAR/DRIVERS/DRIVER[$pos]/*"/>
      <xsl:apply-templates/>      
  </xsl:template>

  <xsl:template match="DRIVER/*">
      <td>
          <xsl:apply-templates/>
      </td>
  </xsl:template>

  <xsl:template match="DRIVER[last()]/*">
      <td rowspan="{count(ancestor::CAR/STATS/STAT) - count(../DRIVER)}">
          <xsl:apply-templates/>
      </td>
  </xsl:template>

  <xsl:template match="LAP | TIME">
      <td>
          <xsl:value-of select="."/>
      </td>
  </xsl:template>

</xsl:stylesheet>

Онлайн на https://xsltfiddle.liberty -development.net / 6qVRKwy

Созданная HTML-таблица выглядит так, как нужно.

...