Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > XML, XSL > XSLT нумерация(помогите)


Автор: artemtereshkov 4.2.2012, 15:25
Всем здравсвуйте.
ОЧЕНЬ НУЖНА ПОМОЩЬ!
Задача состоит в добавлении порядкового номера элементу elem, но идущего не в том порядке, в котором они расположены в исходном документе, а в порядке с учётом располагающихся в элементе linkGroup/link.

Немного сумбурно выразился, но вот что в итоге должно получится:

Код

<list>
  <section>
    <elem pos="1" id="el-0001"/>
    <elem pos="2" id="el-0002"/>
    <link id="ln-0001"/> /* тут обращаемся в linkGroup/link по id="ln-0001" и нумеруем распологающиеся там elem, затем уже обратно */
  </section>
  <section>
    <elem pos="5" id="el-0003"/> /* тут продолжаем нумерацию, после номера в link id="ln-0001" */
    <link id="ln-0002"/> /* тут опять нумеруем элементы сначала в linkGroup/link id="ln-0002", а затем продолжаем здесь нумеровать */
    <elem pos="9" id="el-0004"/>
  </section>
  <linkGroup>
    <link id="ln-0001">
      <elem pos="3" id="el-0005"/>
      <elem pos="4" id="el-0006"/>
    </link>
    <link id="ln-0002">
      <elem pos="6" id="el-0007"/>
      <elem pos="7" id="el-0008"/>
      <elem pos="8" id="el-0009"/>
    </link>
  </linkGroup>
</list>



Я только начинающий xstl-верстальщик и уже всю голову сломал, как именно xslt-стили записать.
Буду очень рад, если кто подскажет методику или лучше фрагмет шаблона, выполняющего данную операцию.

Большое спасибо за помощь)

Автор: diadiavova 5.2.2012, 12:46
Цитата(artemtereshkov @  4.2.2012,  16:25 Найти цитируемый пост)
Я только начинающий xstl-верстальщик и уже всю голову сломал, как именно xslt-стили записать.

Честно говоря, эта задача не для новичка. Тут позицию надо вычислять с использованием рекурсивного шаблона. Ты не указал, как выглядит первоначальный документ, насколько я понял, там все так же, только без атрибутов pos, которые как раз и надо установить. Вот как это выглядит для твоего примера, если что непонятно - спрашивай.
Код

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

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="section/elem">
    <xsl:copy>
      <xsl:apply-templates select="@* |node()"/>
      <xsl:attribute name="pos">
        <xsl:variable name="lc">
          <xsl:call-template name="linkcount">
            <xsl:with-param name="links" select="preceding::link[name(..) = 'section']"/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="count(preceding::elem[name(..) = 'section']) + $lc + 1"/>
      </xsl:attribute>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="link/elem">
    <xsl:copy>
      <xsl:apply-templates select="@* |node()"/>
      <xsl:attribute name="pos">
        <xsl:variable name="parent-id" select="../@id"/>
        <xsl:variable name="section-link" select="//section/link[@id = $parent-id]"/>
        <xsl:variable name="lc">
          <xsl:call-template name="linkcount">
            <xsl:with-param name="links" select="$section-link/preceding::link[name(..) = 'section']"/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="start" select="count($section-link/preceding::elem[name(..) = 'section']) + $lc + 1"/>
        <xsl:value-of select="count(preceding-sibling::elem) + $start"/>
      </xsl:attribute>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template name="linkcount">
    <xsl:param name="links"/>
    <xsl:param name="index" select="count($links)"/>
    <xsl:variable name="result">
      <xsl:value-of select="count(//linkGroup/link[@id = $links[$index]/@id]/elem)"/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$index &lt; 2">
        <xsl:value-of select="$result"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="prevs">
          <xsl:call-template name="linkcount">
            <xsl:with-param name="links" select="$links"/>
            <xsl:with-param name="index" select="$index - 1"/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="$result + $prevs"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>


Автор: artemtereshkov 5.2.2012, 16:01
Спасибо большое, вы мне очень помогли.

Код и правда далеко не для новичка.

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


Автор: diadiavova 5.2.2012, 16:57
Сначала идет шаблон, копирующий все элементы документа. Поскольку он самый первый в документе и указывает на узлы не конкретно, то он имеет самый низкий приоритет и при наличии более высокоприоритеных шаблонов, срабатывают именно они. Далее идут два шаблона для элементов section/elem и link/elem соответственно. Они тоже копируются в документ, но для них устанавливается атрибут pos.

Значение атрибута вычисляется немного по разному. В случае section/elem нужно подсчитать количество всех предшествующих в документе таких же элементов, прибавить к нему количество элементов, на которые ссылаются элементы link и еще единицу. Для элементов link/elem вычисляется похожим способом количество предшествующих elem и link, но только тех, которые предшествуют section/link, ссылающемуся на текущий linkGroup/link. Далее к этому числу прибавляется количество link/elem, предшествующее данному elem.

Именованный шаблон linkcount рекурсивно вычисляет количество elem, на которые ссылаются все link, переданные ему как аргумент links. Параметры index и result используются для реализации рекурсивной логики.

Автор: artemtereshkov 5.2.2012, 22:15
Спасибо еще раз.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)