<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl"  href="/xslt/final.xslt"?><html>
  <head>
    <title>XSLT- примеры. Вып.7 Сворачиваем деревья</title>
    <meta name="css" content=""/>
    <meta name="js" content=""/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="id" content="30"/>
    <link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml"/>
  </head>
  <body>
    <div class="main">
      <div class="wrap">
        <div class="L">
          <h1><a href="/">..</a> / XSLT- примеры. Вып.7 Сворачиваем деревья</h1>
          <ol class="tags big">
            <li>
              <a href="/xslt-recursive">xslt-recursive</a>
            </li>
            <li>
              <a href="/xslt-examples">xslt-examples</a>
            </li>
          </ol>
          <div class="myContent"><p>В <a href="/article/28">предыдущем выпуске (#6)</a> я написал как разворачивать деревья, по существу XSLT-код ничем не отличается от того, как это делается на SQL или PHP или любом другом языке. А вот обратная задача - получение плоского списка сообщений из древовидного другими не-XSLT средствами решается как-то не очень изящно. И это понятно, потому что преобразование XML в XML делать какими-то другими, отличными от XSL средстваим не очень разумно.</p>
<p>Итак нам нужно свернуть ветку обсуждения блога, полученную  в <a href="/article/28">предыдущем выпуске</a>  (набор вложенных друг в друга ненумерованных списков) обратно - в XML набор в виде плоского списка, с указанием parent id. Фрагмент исходного дерева:</p>
<p>Свертывающее XSLT-преобразование выполним двумя способами.</p>
<h2>Пример 1. Рекурсивное свертывание</h2>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">&lt;xsl:template match="/"&gt;
     &lt;item&gt;  
         &lt;xsl:apply-templates/&gt;  
     &lt;/item&gt;  
 &lt;/xsl:template&gt;  

 &lt;xsl:template match="li"&gt;  
     &lt;xsl:param name="parentid" select="0"/&gt;  
     
     &lt;topic id="{@id}" parentid="{$parentid}" author="{h3}"&gt;  
         &lt;xsl:value-of select="p"/&gt;  
     &lt;/topic&gt;  
     &lt;!-- запуск на рекурсивную обработку вложенных сообщений --&gt;  
     &lt;xsl:apply-templates select="ul/li"&gt;  
         &lt;xsl:with-param name="parentid" select="@id"/&gt;  
     &lt;/xsl:apply-templates&gt;      
     
 &lt;/xsl:template&gt;  
             </pre><!--/php--></td>
        </tr>
    </tbody>
</table>
<p>Сначала вызывается шаблон для формирования корневого элемента. Он формирует корневой элемент списка сообщений item и вызывает шаблоны по умолчанию. Первое сообщение будет отработано шаблоном match="li", которое формирует XML элемент этого сообщения и запускает на рекурсивную обработку все вложенные сообщения (ul/li)</p>
<p>На выходе получается примерно то, что было на входе <a href="/article/28">в предыдущем примере</a>, но порядок сообщений при этом нарушается. Чтобы порядок сообщений сохранялся необходимо ввести сортировку по id. Проделаем это в следующем примере.</p>
<h2>Пример 2. Прямое свертывание</h2>

<table class="code">
    <tbody>
        <tr>
            <td><!--php-->
            <pre class="brush: plain">&lt;xsl:template match="/"&gt;
     &lt;item&gt;  
         &lt;xsl:apply-templates select="//li"&gt;  
             &lt;xsl:sort select="id" data-type="number"/&gt;  
         &lt;/xsl:apply-templates&gt;  
     &lt;/item&gt;  
 &lt;/xsl:template&gt;  

 &lt;xsl:template match="li"&gt;  
               &lt;xsl:variable name="parentid"&gt;  
    &lt;xsl:choose&gt;  
        &lt;xsl:when test="ancestor::li[1]/@id"&gt;  &lt;xsl:value-of select="ancestor::li[1]/@id"/&gt;  &lt;/xsl:when&gt;  
        &lt;xsl:otherwise&gt;  0&lt;/xsl:otherwise&gt;  
    &lt;/xsl:choose&gt;  
               &lt;/xsl:variable&gt;  
    
    
     &lt;topic id="{@id}"  author="{h3}" parentid="{$parentid}"&gt;  
         &lt;xsl:value-of select="p"/&gt;  
     &lt;/topic&gt;  
    

    
 &lt;/xsl:template&gt;  </pre><!--/php--></td>
        </tr>
    </tbody>
</table>
<p> </p>
<p>Здесь в первом шаблоне (match="/"), обрабатыващем корневой элемент, задаем напрямую обработку всех сообщений (тегов li)   с указанием порядка сортировки - по id.  Второй шаблон (match="li") обрабатывающий  отдельные сообщения, вычисляет id родительского элемента в переменной parentid и формирует соответствующий элемент сообщения &lt;topic&gt;   в выходном дереве</p></div>
          <ol class="tags big">
            <li class="date">2008-12-08</li>
            <li>
              <a href="/xslt-recursive">xslt-recursive</a>
            </li>
            <li>
              <a href="/xslt-examples">xslt-examples</a>
            </li>
          </ol>
          <ol class="see">
            <li>
              <a href="#"><span>erum.ru/article/28</span> - <b>XSLT- примеры. Вып.6 Разворачиваем деревья (Flattern tree)</b></a>
            </li>
            <li>
              <a href="#"><span>www.dpawson.co.uk/xsl/sect2/flatten.html#d5475e70</span> - <b>How to flatten the source XML tree. (XSLT Questions and Answers - FAQ )</b></a>
            </li>
          </ol>
          <ul class="comment">
            <li id="a274" title="a0">
              <a name="&#x439;&#x446;&#x443;&#x43A;&#x435;&#x43D;" title="" rel="29.04.09"/>
              <div>Спасибо за примеры. В Интернете их немного. Продолжение будет?</div>
            </li>
            <li id="a275" title="a274">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="29.04.09"/>
              <div>Спасибо и вам. <br/>С продолжением сложно. Нет сил. Нет времени. <br/>В интернете XSLT примеров много. Но в основном в англозычном интернете.</div>
            </li>
            <li id="a331" title="a274">
              <a name="Le capitaine Nemo" title="" rel="26.08.09"/>
              <div>Присоединяюсь. Жаль что пополнения нет. Нормальных примеров в инете нет.</div>
            </li>
            <li id="a332" title="a331">
              <a name="&#x418;&#x441;&#x430;&#x430;&#x43A; &#x422;&#x44B;&#x43D;&#x433;&#x44B;&#x43B;&#x447;&#x430;&#x432;" title="erum.ru" rel="26.08.09"/>
              <div>Ищите в англоязычном. А еще лучше пошукайте в магазинах книгу XSLT в примерах. Автора не помню. Она в этом году вышла - еще не раскупили. <br/>Продолжение - будет. Написал что-то типа методички для верстальшиков ~20-30 статей. Но нет времени отредактировать, собрать и опубликовать.</div>
            </li>
            <li id="a338" title="a0">
              <a name="&#x42F;&#x43C;&#x430;&#x43B;" title="" rel="26.09.09"/>
              <div>И опять совпадение:)<br/>Давно использую только xslt В качестве шаблонов. Хотя такие задачи возникают редко. Я не уверен, что их вообще имеест смысл делать на XSLT. Мне кажется что это надо решать на другом уровне. XSLT - тормозной.</div>
            </li>
          </ul>
        </div>
      </div>
      <div class="R">
        <a href="/" title="&#x41D;&#x430; &#x433;&#x43B;&#x430;&#x432;&#x43D;&#x443;&#x44E;"/>
      </div>
    </div>
    <div id="li"/>
  </body>
</html>

