Рекурсия в XML-документе через XSLT

Discussion in 'PHP' started by Kuzya, 7 May 2009.

  1. Kuzya

    Kuzya Elder - Старейшина

    Joined:
    27 Apr 2008
    Messages:
    166
    Likes Received:
    106
    Reputations:
    30
    Есть xml-документ представляющий из себя что-то типа древа файлов.
    Пример:
    Code:
    <root>
    <dir name="dir1" />
    <dir name="dir2" />
    <dir name="dir3" >
        <file name="file1.ext" />
        <file name="file2.ext" />
        <file name="file3.ext" />
        <dir name="dir4" >
            <file name="file4.ext" />
        </dir>
    </dir>
    </root>
    Как видите - описаны директории и входящие в них файлы/папки. Нужно каким то образом с помощью XSLT привести эту информацию в HTML-вид с сохранением порядка расположения в документе. Я попробовал следующие правила (пишу на память)
    Code:
    <xsl:tempate match="dir">
    <b><xsl:apply-templates /></b>
    </xsl:template>
    <xsl:tempate match="file">
    <i><xsl:apply-templates /></i>
    </xsl:template>
    Типа все директории выделяем жирным,а файлы - курсивом. Но так обрабатываются только корневые элементы. Вложенные же остаются без внимания. Появилась идея обходить через for-each-конструкцию каждый тег и проверять есть ли в нём вложенные элементы. Если есть то проверять эти элементы так же с помощью for-each и т.д. То есть что-то типа рекурсии с for-each. Но как это сделать ума не приложу. Если можно было бы описывать в XSLT что ни будь типа функций то проблема решилась бы сразу. Порылся в книжках по XML+XSLT, но не нашёл ничего нужного. Может я вообще не в том направлении копаю, или просто знаний мало? Помогите пожалуйста разобраться.
     
  2. oRb

    oRb Elder - Старейшина

    Joined:
    9 May 2008
    Messages:
    294
    Likes Received:
    581
    Reputations:
    256
    Это будет выглядить как-то так:
    Code:
    <?xml version="1.0" encoding="windows-1251"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes" encoding="windows-1251" media-type="text/html" omit-xml-declaration="yes"/>
    
    <xsl:template match="/root">
    <table width="100%" cellspacing="0" cellpadding="5" border="0">
    	<tr>
    		<th>Name</th>
    	</tr>	
    	<xsl:call-template name="tree"><xsl:with-param name="level" select="0"/></xsl:call-template>
    </table>
    </xsl:template>
    
    <xsl:template name="tree">
    	<xsl:param name="level"/>
    	<xsl:for-each select="dir">
    		<tr>
    			<td><div><xsl:attribute name="style">margin-left: <xsl:value-of select="$level*10"/>px</xsl:attribute><xsl:value-of select="@name"/></span></td>
    		</tr>
    		<xsl:call-template name="tree"><xsl:with-param name="level" select="$level + 1"/></xsl:call-template>
    	</xsl:for-each>
    	<xsl:for-each select="file">
    		<tr>
    			<td><div><xsl:attribute name="style">margin-left: <xsl:value-of select="$level*10"/>px</xsl:attribute><xsl:value-of select="@name"/></span></td>
    		</tr>
    	</xsl:for-each>
    </xsl:template>
    </xsl:stylesheet>
    зы: с XSLT не работал уже давно, писал не проверяя, так что код не факт, что рабочий.
     
    2 people like this.
  3. Kuzya

    Kuzya Elder - Старейшина

    Joined:
    27 Apr 2008
    Messages:
    166
    Likes Received:
    106
    Reputations:
    30
    oRb, спасибо тебе огромное! Оказывается В моей книге просто не описывается операция call-template!