XSLT подменю в три столбца

#
XSLT подменю в три столбца
Возникла небольшая незаурядная для меня ситуация..
Следующим ниже кодом я генерирую подменю:

<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output xmlns="http://www.w3.org/TR/xhtml1/strict" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
encoding="Windows-1251" indent="yes" method="html" omit-xml-declaration="no" version="1.0" media-type="text/xml" />

<xsl:template match="/document">

  <table border="0" style="width:99%">
    <!-- Выбираем узлы структуры -->
    <xsl:apply-templates select="/document/structure/structure[show=1]"/>
  </table>

</xsl:template>

<xsl:template match="/document/structure/structure">
  <!-- Запишем в константу ID структуры, данные для которой будут выводиться пользователю -->
  <xsl:variable name="csid" select="/document/structure/current_structure_id"/>
  <xsl:variable name="mparent_id" select="/document/structure/structure[id_parent=$csid]/id_parent"/>
  <xsl:variable name="sparent_id" select="/document/structure/structure[@id=$csid]/id_parent"/>
  <xsl:variable name="mlink" select="link" />

  <xsl:if test="(id_parent=$mparent_id) or (id_parent=$sparent_id)">

    <xsl:if test="position() = 1">
      <xsl:text disable-output-escaping="yes">
        &lt;tr&gt;
      </xsl:text>
    </xsl:if>

    <td align="left"><div class="submenu_item">
    <xsl:if test="not($csid=@id)">
      <a href="{$mlink}"><xsl:value-of disable-output-escaping="yes" select="name"/></a>
    </xsl:if>
    <xsl:if test="$csid=@id">
      <xsl:value-of disable-output-escaping="yes" select="name"/>
    </xsl:if>
    </div></td>

    <xsl:if test="(position() mod 3)=0">
      <xsl:text disable-output-escaping="yes">
        &lt;/tr&gt;
        &lt;tr&gt;
      </xsl:text>
    </xsl:if>

    <xsl:if test="position() = count(//structure/structure[id_parent=$mparent_id])">
      <xsl:text disable-output-escaping="yes">
       &lt;/tr&gt;
      </xsl:text>
    </xsl:if>
  </xsl:if>

</xsl:template>

</xsl:stylesheet>


Однако он срабатывает только для первой структуры вложенности.. Если же у меня в первой структуре количество элементов не кратно трем, то в последующих страницах из-за position() происходит "сбитие" логики и меню уже получается корявым. Помогите советом, как сделать такое преобразование, чтобы на всех страницах все было тип-топ..

Спасибо большое!
Модератор
#
Re: XSLT подменю в три столбца
Покажите пример "сбития логики" в HTML, чтобы наглядно посмотреть.
#
Re: XSLT подменю в три столбца
HostCMS,
Вот как должно быть (http://ieroglyf.bizhosting.ru/about/) :
<tr>
      <td align="left"><div class="submenu_item"><a href="/about/news/">Новости</a></div></td><td align="left"><div class="submenu_item"><a href="/about/about_us/">О нас</a></div></td><td align="left"><div class="submenu_item"><a href="/about/history/">История компании</a></div></td>
        </tr>
        <tr>
      <td align="left"><div class="submenu_item"><a href="/about/vacancy/">Вакансии</a></div></td><td align="left"><div class="submenu_item"><a href="/about/our_client/">Наши клиенты</a></div></td><td align="left"><div class="submenu_item"><a href="/about/uchast/">Участие в ассоциациях и союзах</a></div></td>
        </tr>
        <tr>
      <td align="left"><div class="submenu_item"><a href="/about/our_friend/">Наши друзья</a></div></td><td align="left"><div class="submenu_item"><a href="/about/party/">Корпоративные вечеринки</a></div></td>
       </tr>


А вот как сбивается (http://ieroglyf.bizhosting.ru/uslugi/) :

<tr><td align="left"><div class="submenu_item"><a href="/uslugi/razrabotka_logotipa_i_firmennogo_stilja/">Разработка логотипа и фирменного стиля</a></div></td>
        </tr>
        <tr>
      <td align="left"><div class="submenu_item"><a href="/uslugi/naruzhnaja_reklama/">Наружная реклама</a></div></td><td align="left"><div class="submenu_item"><a href="/uslugi/proizvodstvo_odezhdy_s_simvolikojj/">Производство одежды с символикой</a></div></td>
       </tr>
      <tr><td align="left"><div class="submenu_item"><a href="/uslugi/reklama_na_transporte/">Реклама на транспорте</a></div></td>
        </tr>

        <tr>
      <td align="left"><div class="submenu_item"><a href="/uslugi/nejjming_i_brending/">Нейминг и Брендинг</a></div></td><td align="left"><div class="submenu_item"><a href="/uslugi/marketingovye_issledovanija/">Маркетинговые исследования</a></div></td><td align="left"><div class="submenu_item"><a href="/uslugi/merchendajjzing/">Мерчендайзинг</a></div></td>
        </tr>
        <tr>
      <td align="left"><div class="submenu_item"><a href="/uslugi/promo-aktsii_i_events/">Промо-акции и events</a></div></td><td align="left"><div class="submenu_item"><a href="/uslugi/product_placement/">Product Placement</a></div></td><td align="left"><div class="submenu_item"><a href="/uslugi/mediaplanirovanie/">Медиапланирование</a></div></td>
        </tr>

        <tr>
      <td align="left"><div class="submenu_item"><a href="/uslugi/pr/">PR</a></div></td></tr>


В структурах(/document/structure) данные подструктуры(/document/structure/structure) идут последовательно.. т.е. содержания подструктур первой структуры отображается корректно (8 элементов), а содержания подструктур второй структуры уже неверно, т.к. первый position() для подструктур второй структуры возвращает 9, что кратно трем. Из-за этого и происходит сбой..

Понимаю что сумбурно понятно, но надеюсь на примере будет виднее... )
#
Re: XSLT подменю в три столбца
Что-то нужно апить тему, т.к. актуально..

Может организовать через for-each? но только для вложенных структур.. тогда position() будет считаться от какого места?
#
Re: XSLT подменю в три столбца
Alvein, тут нужно  серьезно подумать
#
Re: XSLT подменю в три столбца
natalya,
Аха, тоже уже над этим серьезно думаю... пытался через XPath, но как плохо я его знаю.. ((
#
Re: XSLT подменю в три столбца
Чтож, вот и решение данного вопроса.
Данное решение позволяет:
1. Выводить подструктуру выбранной структуры
2. Выводить подструктуру выбранной структуры, если выбран третий уровень вложенности.. Может и большее позволяет, но не факт.

Пришлось немного поковыряться конечно, но все же рад что обучился директиве <xsl:for-each..> Писал сам, но пожалуйста, пользуйтесь на здоровье:

<?xml version="1.0" encoding="windows-1251"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output xmlns="http://www.w3.org/TR/xhtml1/strict" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" encoding="Windows-1251" indent="yes" method="html" omit-xml-declaration="no" version="1.0" media-type="text/xml"/>

<xsl:template match="/document">
<xsl:variable name="csid" select="./structure/current_structure_id"/>
<xsl:variable name="pid" select="//structure[@id=$csid]/id_parent"/>
<xsl:variable name="ppid" select="//structure[@id=$pid]/id_parent"/>

<table border="0" style="width:99%">
<xsl:variable name="mparent_id">
  <xsl:choose>
   <xsl:when test="not($ppid=0) and not($pid=0)">
    <xsl:variable name="csidb" select="//structure[@id=$csid]/id_parent"/>
    <xsl:value-of disable-output-escaping="yes" select="/document/structure/structure[id_parent=$csidb]/id_parent" />
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of disable-output-escaping="yes" select="//structure[id_parent=$csid]/id_parent" />
   </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:variable name="sparent_id">
  <xsl:choose>
   <xsl:when test="not($ppid=0) and not($pid=0)">
    <xsl:variable name="csidb" select="//structure[@id=$csid]/id_parent"/>
    <xsl:value-of disable-output-escaping="yes" select="/document/structure/structure[@id=$csidb]/id_parent" />
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of disable-output-escaping="yes" select="//structure[@id=$csid]/id_parent"/>
   </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:variable name="fif">
  <xsl:choose>
   <xsl:when test="$pid=0">
    <xsl:value-of disable-output-escaping="yes" select="$csid" />
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of disable-output-escaping="yes" select="$sparent_id" />
   </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:for-each select="//structure[@id=$fif]/structure">
  <xsl:if test="position() = 1">
   <xsl:text disable-output-escaping="yes">
    &lt;tr&gt;
   </xsl:text>
  </xsl:if>

  <td align="left"><div class="submenu_item">
   <xsl:if test="not($csid=@id)">
    <a href="{link}"><xsl:value-of disable-output-escaping="yes" select="name"/></a>
   </xsl:if>
   <xsl:if test="$csid=@id">
    <b class="link_active"><xsl:value-of disable-output-escaping="yes" select="name"/></b>
   </xsl:if>
  </div></td>

  <xsl:if test="(position() mod 3)=0">
   <xsl:text disable-output-escaping="yes">
    &lt;/tr&gt;
    &lt;tr&gt;
   </xsl:text>
  </xsl:if>

  <xsl:if test="position() = count(//structure[@id=$fif]/structure)">
   <xsl:text disable-output-escaping="yes">
    &lt;/tr&gt;
   </xsl:text>
  </xsl:if>
</xsl:for-each>

</table>
</xsl:template>

</xsl:stylesheet>


Конечно решение не оптимальное и можно кое-что подправить, но вот пока только такое.

Welcome!
#
Re: XSLT подменю в три столбца
Небольшое дополнение:
Alvein писал(а):
<xsl:for-each select="//structure[@id=$fif]/structure">

нужно исправить на:
Alvein писал(а):
<xsl:for-each select="//structure[@id=$fif]/structure[show=1]">


думаю понятно для чего
Авторизация