PDA

Просмотр полной версии : Рекурсия в XML-документе через XSLT


Kuzya
07.05.2009, 09:03
Есть xml-документ представляющий из себя что-то типа древа файлов.
Пример:
<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-вид с сохранением порядка расположения в документе. Я попробовал следующие правила (пишу на память)
<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, но не нашёл ничего нужного. Может я вообще не в том направлении копаю, или просто знаний мало? Помогите пожалуйста разобраться.

oRb
07.05.2009, 10:53
Это будет выглядить как-то так:
<?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 не работал уже давно, писал не проверяя, так что код не факт, что рабочий.

Kuzya
08.05.2009, 17:06
oRb, спасибо тебе огромное! Оказывается В моей книге просто не описывается операция call-template!