Как подсчитать элементы в категориях и сравнить их с другими категориями в XSLT

у меня проблема :-)

Я хотел бы распечатать xml и написать для него xslt. проблема в том, что я хотел бы построить таблицу с моими xml-элементами, но я должен подсчитать, имеет ли каждая строка одинаковое количество столбцов, а если нет, мне нужно добавить элемент значения.

Я знаю, что не могу изменить значение переменных после того, как установил значение, но как тогда я могу сравнить количество процессов в категориях / строках таблицы? (и добавить пустые строки)

XML:

<Settings>
   ...
   ..
  <DashBoard>
    <Category NAME="ph" PICNAME="prh">
      <Process NAME="pd" URL="" PICNAME="prh_prd" />
      <Process NAME="md" URL="" PICNAME="prh_prd" />
      <Process NAME="t" URL="" PICNAME="prh_prd" />
    </Category>
    <Category NAME="cm" PICNAME="cam">
      <Process NAME="ps" URL="" PICNAME="cam_pls" />
      <Process NAME="ea" URL="" PICNAME="cam_eas" />
    </Category>
    <Category NAME="sm" PICNAME="sum">
      <Process NAME="frm" URL="" PICNAME="sum_frm" />
    </Category>
  </DashBoard>
</Settings>

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl=".....">
  <xsl:output method="xml" indent="yes"/>
  <xsl:variable name="relurl" select="/Settings/Picture/@RELATIVEURL"/>

  <xsl:template match="Settings">
    <table id="dashframe" >
      <xsl:apply-templates/>
    </table>
  </xsl:template>

  <xsl:template match="Category">
    <xsl:variable name="altname" select="@NAME" />
    <xsl:variable name="picname" select="@PICNAME" />
    <tr>
      <th>
        <img alt="{$altname}" src="{$relurl}dash_{$picname}_p_01.png" />
      </th>
      <xsl:apply-templates/>
    </tr>
  </xsl:template>

  <xsl:template match="Process">
    <xsl:variable name="altname" select="@NAME" />
    <xsl:variable name="picname" select="@PICNAME" />
    <td>
      <img alt="{$altname}" src="{$relurl}dash_{$picname}_p_01.png" />
    </td>
  </xsl:template>
</xsl:stylesheet>

Желаемый результат:

<table id="dashframe" >
    <tr>
        <th>titel 1</th>
        <td>....</td>
        <td>....</td>
        <td>....</td>
    </tr>
    <tr>
        <th>titel 2</th>
        <td>....</td>
        <td>....</td>
        <td></td>
    </tr>
    <tr>
        <th>titel 3</th>
        <td>....</td>
        <td></td>
        <td></td>
    </tr>
</table>

person jwillmer    schedule 04.03.2011    source источник
comment
Какой желаемый результат? Отметьте этот вопрос stackoverflow.com/ questions / 5182789 / Может быть, вам это поможет.   -  person Alex Nikolaenkov    schedule 04.03.2011


Ответы (3)


Сохранив вашу, эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"/>
    <xsl:variable name="relurl" select="/Settings/Picture/@RELATIVEURL"/>
    <xsl:variable name="vColumns">
        <xsl:for-each select="/Settings/DashBoard/Category">
            <xsl:sort select="count(Process)" order="descending"/>
            <xsl:if test="position()=1">
                <xsl:value-of select="count(Process)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:template match="DashBoard">
        <table id="dashframe" border="1">
            <xsl:apply-templates/>
        </table>
    </xsl:template>
    <xsl:template match="Category">
        <tr>
            <th>
                <img alt="{@NAME}" src="{$relurl}dash_{@PICNAME}_p_01.png"/>
            </th>
            <xsl:call-template name="process"/>
        </tr>
    </xsl:template>
    <xsl:template name="process">
        <xsl:param name="pColumn" select="number($vColumns)"/>
        <xsl:if test="$pColumn">
            <xsl:call-template name="process">
                <xsl:with-param name="pColumn" select="$pColumn - 1"/>
            </xsl:call-template>
            <td>
                <xsl:variable name="vColumn" select="Process[$pColumn]"/>
                <xsl:if test="$vColumn">
                    <img alt="{$vColumn/@NAME}"
                         src="{$relurl}dash_{$vColumn/@PICNAME}_p_01.png"/>
                </xsl:if>
            </td>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

С этим вводом:

<Settings>
    <DashBoard>
        <Category NAME="ph" PICNAME="prh">
            <Process NAME="pd" URL="" PICNAME="prh_prd" />
            <Process NAME="md" URL="" PICNAME="prh_prd" />
            <Process NAME="t" URL="" PICNAME="prh_prd" />
        </Category>
        <Category NAME="cm" PICNAME="cam">
            <Process NAME="ps" URL="" PICNAME="cam_pls" />
            <Process NAME="ea" URL="" PICNAME="cam_eas" />
        </Category>
        <Category NAME="sm" PICNAME="sum">
            <Process NAME="frm" URL="" PICNAME="sum_frm" />
        </Category>
    </DashBoard>
</Settings>

Выход:

<table id="dashframe" border="1">
    <tr>
        <th><img alt="ph" src="dash_prh_p_01.png"></th>
        <td><img alt="pd" src="dash_prh_prd_p_01.png"></td>
        <td><img alt="md" src="dash_prh_prd_p_01.png"></td>
        <td><img alt="t" src="dash_prh_prd_p_01.png"></td>
    </tr>
    <tr>
        <th><img alt="cm" src="dash_cam_p_01.png"></th>
        <td><img alt="ps" src="dash_cam_pls_p_01.png"></td>
        <td><img alt="ea" src="dash_cam_eas_p_01.png"></td>
        <td></td>
    </tr>
    <tr>
        <th><img alt="sm" src="dash_sum_p_01.png"></th>
        <td><img alt="frm" src="dash_sum_frm_p_01.png"></td>
        <td></td>
        <td></td>
    </tr>
</table>

Примечание: хорошо известная максимальная идиома.

person Community    schedule 04.03.2011

спасибо за ответы, я решил сам за последние 4-5 часов ~ _ ~

сначала посчитайте:

<xsl:variable name="maxProcess">
  <xsl:call-template name="db"/>
</xsl:variable>

<xsl:template name="db">
  <xsl:for-each select="/Settings/DashBoard/Category">
    <xsl:sort select="count(Process)" order="descending"/>
    <xsl:if test="position() =1">
      <xsl:value-of select="count(Process)"/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

во-вторых, добавьте процессы и после этого добавьте пустые:

<xsl:template match="Category">
  <tr>
    <td>
      <img .... />
    </td>
    <xsl:apply-templates/>
    <xsl:call-template name="addTDs">
      <xsl:with-param name="rest" select="$maxProcess - count(Process)"/>
    </xsl:call-template>
  </tr>
</xsl:template>

<xsl:template match="Process">
  <td>
     <img ... />
  </td>
</xsl:template>

<xsl:template name="addTDs">
  <xsl:param name="rest"/>
  <xsl:choose>
    <xsl:when test="$rest &gt; 0">
      <td>
        <img ..../>
      </td>
      <xsl:call-template name="addTDs">
        <xsl:with-param name="rest" select="$rest - 1"/>
      </xsl:call-template>
    </xsl:when>
  </xsl:choose>
</xsl:template>
person jwillmer    schedule 04.03.2011

Итак, вы должны сделать это в 2 шага:

  1. Определение строки с максимальным количеством столбцов
  2. Итерирование всех строк, заполнение недостающих столбцов

Итак, первая часть - в чем здесь основная проблема, потому что невозможно выяснить это только с помощью xpath.

Ответы на этот вопрос подтвердили, что:

Найдите максимальное количество дочерних элементов с помощью XPath 1.0

Я пытаюсь ответить на этот вопрос около 30 минут. И я действительно знаком с XML и XSLT по своей работе. Но я просто не мог понять, как найти элемент с максимальным количеством дочерних элементов. Но раньше это делал кто-то другой:

Найдите максимальное значение все дочерние элементы и получить его родительский элемент в XSLT

Кстати: этот парень проголосовал за свой ответ!

Если он у вас есть, мы переходим к шагу 2:

В шаблоне категории просто добавьте вызов следующего шаблона (который представляет собой просто цикл for):

<xsl:template name="for.loop">

   <xsl:param name="i"      />
   <xsl:param name="count"  />

   <xsl:if test="$i &lt;= $count">
      //Generate your "fill up" - colum here
   </xsl:if>

   <!--begin_: RepeatTheLoopUntilFinished-->
   <xsl:if test="$i &lt;= $count">
      <xsl:call-template name="for.loop">
          <xsl:with-param name="i">
              <xsl:value-of select="$i + 1"/>
          </xsl:with-param>
          <xsl:with-param name="count">
              <xsl:value-of select="$count"/>
          </xsl:with-param>
      </xsl:call-template>
   </xsl:if>

Now then you call that template simpy fill in the count(Process) as param i and fill in the count to your previously saved "Maximum" - Node which you got from the first template out of the linked question count(maximumnode/Process) as param count.

Вздох, кажется, вы достигли некоторых точек, где XSLT отчасти сложен.

Надеюсь, это поможет!

person Chris    schedule 04.03.2011
comment
отлично, спасибо, но я помечу сообщение Алехандро как ответ из-за сложности его ответа ;-) - person jwillmer; 04.03.2011
comment
Я полностью согласен с этим :-) Я буду биться головой о дверь всю ночь, потому что я не видел простого способа определить максимальный элемент с помощью сортировки ... просто сортировки ... чувак .... - person Chris; 05.03.2011