.. / XSLT- примеры. Вып.7 Сворачиваем деревья

  1. xslt-recursive
  2. xslt-examples

В предыдущем выпуске (#6) я написал как разворачивать деревья, по существу XSLT-код ничем не отличается от того, как это делается на SQL или PHP или любом другом языке. А вот обратная задача - получение плоского списка сообщений из древовидного другими не-XSLT средствами решается как-то не очень изящно. И это понятно, потому что преобразование XML в XML делать какими-то другими, отличными от XSL средстваим не очень разумно.

Итак нам нужно свернуть ветку обсуждения блога, полученную  в предыдущем выпуске  (набор вложенных друг в друга ненумерованных списков) обратно - в XML набор в виде плоского списка, с указанием parent id. Фрагмент исходного дерева:

Свертывающее XSLT-преобразование выполним двумя способами.

Пример 1. Рекурсивное свертывание

<xsl:template match="/">
     <item>  
         <xsl:apply-templates/>  
     </item>  
 </xsl:template>  

 <xsl:template match="li">  
     <xsl:param name="parentid" select="0"/>  
     
     <topic id="{@id}" parentid="{$parentid}" author="{h3}">  
         <xsl:value-of select="p"/>  
     </topic>  
     <!-- запуск на рекурсивную обработку вложенных сообщений -->  
     <xsl:apply-templates select="ul/li">  
         <xsl:with-param name="parentid" select="@id"/>  
     </xsl:apply-templates>      
     
 </xsl:template>  
             

Сначала вызывается шаблон для формирования корневого элемента. Он формирует корневой элемент списка сообщений item и вызывает шаблоны по умолчанию. Первое сообщение будет отработано шаблоном match="li", которое формирует XML элемент этого сообщения и запускает на рекурсивную обработку все вложенные сообщения (ul/li)

На выходе получается примерно то, что было на входе в предыдущем примере, но порядок сообщений при этом нарушается. Чтобы порядок сообщений сохранялся необходимо ввести сортировку по id. Проделаем это в следующем примере.

Пример 2. Прямое свертывание

<xsl:template match="/">
     <item>  
         <xsl:apply-templates select="//li">  
             <xsl:sort select="id" data-type="number"/>  
         </xsl:apply-templates>  
     </item>  
 </xsl:template>  

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

    
 </xsl:template>  

 

Здесь в первом шаблоне (match="/"), обрабатыващем корневой элемент, задаем напрямую обработку всех сообщений (тегов li)  с указанием порядка сортировки - по id.  Второй шаблон (match="li") обрабатывающий  отдельные сообщения, вычисляет id родительского элемента в переменной parentid и формирует соответствующий элемент сообщения <topic> в выходном дереве

  1. 2008-12-08
  2. xslt-recursive
  3. xslt-examples
  1. erum.ru/article/28 - XSLT- примеры. Вып.6 Разворачиваем деревья (Flattern tree)
  2. www.dpawson.co.uk/xsl/sect2/flatten.html#d5475e70 - How to flatten the source XML tree. (XSLT Questions and Answers - FAQ )
Go Index Test