<?xml version="1.0" encoding="iso-8859-1"?>

<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:svg="http://www.w3.org/2000/svg">


<xsl:output 
method="xml" 
version="1.0"
encoding="iso-8859-1"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
indent="yes"/>

<xsl:strip-space elements="*" />



<!-- Paramètres -->
<xsl:param name="titre">Arbre XML en SVG</xsl:param>
<xsl:param name="description">génération d'un arbre SVG à partir d'un fichier XML</xsl:param>
<!-- ========================== Variables =========================== -->
<xsl:variable name="tree" select="tree"/>
<xsl:variable name="nb-elements" select="count(tree/node)"/>


<xsl:variable name="nb-niveaux">
<xsl:call-template name="boucle-max">
<xsl:with-param name="n" select="$nb-elements"/>
<xsl:with-param name="valeur-courante" select="1"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="nb-max-element-niveau">
<xsl:call-template name="boucle-nb-element-niveau">
<xsl:with-param name="n" select="$nb-niveaux"/>
<xsl:with-param name="valeur-courante" select="0"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="height" select="( $nb-niveaux * 150 ) + 50"/>
<xsl:variable name="width" select="( $nb-max-element-niveau * 220 ) + 50"/>
<xsl:variable name="middle-width" select=" $width div 2"/>

<!-- ========================== Templates =========================== -->
<xsl:template name="maximum">
<!-- récupère les  deux valeurs en entrée et retourne le maximum -->
<xsl:param name="x1"/>
<xsl:param name="x2"/>


<xsl:variable name="resultat">
<xsl:choose>

<xsl:when test="string(x1) = 'NaN' and string(x2) ='NaN'">
<xsl:value-of select="$x1"/>
</xsl:when>

<xsl:when test="string(x1) = 'NaN'">
<xsl:value-of select="$x2"/>
</xsl:when>

<xsl:when test="string(x2) = 'NaN'">
<xsl:value-of select="$x1"/>
</xsl:when>

<xsl:when test="$x1 > $x2">
<xsl:value-of select="$x1"/>
</xsl:when>

<xsl:otherwise>
<xsl:value-of select="$x2"/>
</xsl:otherwise>

</xsl:choose>
</xsl:variable>

<xsl:copy-of select="$resultat"/>
</xsl:template>


<xsl:template name="boucle-max">
<xsl:param name="n"/>
<xsl:param name="valeur-courante"/>

<xsl:choose>
<xsl:when test="$n > 0">

<xsl:variable name="valeur">
<xsl:call-template name="maximum">
<xsl:with-param name="x1" select="tree/node[position() = $n ]/@level"/>
<xsl:with-param name="x2" select="$valeur-courante"/>
</xsl:call-template>
</xsl:variable>


<xsl:call-template name="boucle-max">
<xsl:with-param name="n" select="$n - 1"/>
<xsl:with-param name="valeur-courante" select="$valeur"/>
</xsl:call-template>

</xsl:when>

<xsl:otherwise>
<xsl:value-of select="$valeur-courante"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>






<xsl:template name="boucle-nb-element-niveau">
<xsl:param name="n"/>
<xsl:param name="valeur-courante"/>


<xsl:choose>
<xsl:when test="$n > 0">

<xsl:variable name="valeur">
<xsl:call-template name="maximum">
<xsl:with-param name="x1">
<xsl:call-template name="compte-elements-niveau">
<xsl:with-param name="level" select="$n"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="x2" select="$valeur-courante"/>
</xsl:call-template>
</xsl:variable>


<xsl:call-template name="boucle-nb-element-niveau">
<xsl:with-param name="n" select="$n - 1"/>
<xsl:with-param name="valeur-courante" select="$valeur"/>
</xsl:call-template>

</xsl:when>

<xsl:otherwise>
<xsl:value-of select="$valeur-courante"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>


<xsl:template name="compte-elements-niveau">
<xsl:param name="level"/>
<xsl:value-of select="count($tree/node[@level = $level ])"/>
</xsl:template>

<xsl:template name="coord-parent-x">
<xsl:param name="level"/>
<xsl:param name="id"/>
<xsl:variable name="parent" select="$tree/node[ @level = $level and @id = $id ]"/>
<xsl:variable name="X" select="(($parent/@order - 1) * 220) + 25"/>
<xsl:value-of select="$X"/>
</xsl:template>

<xsl:template name="coord-parent-y">
<xsl:param name="level"/>
<xsl:param name="id"/>
<xsl:variable name="parent" select="$tree/node[ @level = $level and @id = $id ]"/>
<xsl:variable name="Y" select="(( $parent/@level - 1) * 150) + 30"/>
<xsl:value-of select="$Y"/>
</xsl:template>

<xsl:template name="width-element-niveau-parent">
<xsl:param name="level"/>
<xsl:variable name="level-parent"/>
<xsl:variable name="nb-parent" select="count($tree/node[ @level = $level-parent ])"/>
<xsl:variable name="resultat" select="( $nb-parent * 220 ) + 50"/>
<xsl:value-of select="$resultat"/>
</xsl:template>

<!-- ========================== Templates =========================== -->

<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">

<head>
<title>svg | tracer un arbre</title>
<link rel="stylesheet" type="text/css" href="sitewww.css"/>
<link rel="icon" type="image/gif" href="a.ico" />
<link rel="shortcut icon" type="images/x-icon" href="a.ico" />
<meta name="generator" content="Notepad"/>
<meta name="author" content="Christopher COMPAGNON"/>
<meta content="application/xhtml+xml; charset=iso-8859-1" http-equiv="content-type"/>
<meta name="description" content="site web de C.COMPAGNON"/>
<meta name="keywords" content="XML, XSL, arbre, SVG"/> 
</head>

<body>

<div class="page">
<div id="banner">
<h1 id="title"><span>XSL+SVG : affichage d'un arbre</span></h1>
<p id="tagline">Exemple d'arbre (ou arborescence) XML avec SVG dynamique</p>
</div>
<div id="contenu"> 
 
   
<ul class="menu">
<li><a href="../index.html">Sommaire</a></li>
<li> | </li>
<li><a href="xml-xsl.html">XML/XSL</a></li>
<li> | </li>
<li><a href="contacts.html">Contacts</a></li>
</ul>

<h2>Affichage de l'arbre</h2>
<svg:svg>
<xsl:attribute name="width"><xsl:value-of select="$width"/>px</xsl:attribute>
<xsl:attribute name="height"><xsl:value-of select="$height"/>px</xsl:attribute>
<xsl:attribute name="viewbox">0 0 <xsl:value-of select="$width"/><xsl:text> </xsl:text><xsl:value-of select="$height"/></xsl:attribute>
<xsl:attribute name="preserveAspectRation">xMidYMid Slice</xsl:attribute>

<svg:title><xsl:value-of select="$titre"/></svg:title>
<svg:desc><xsl:value-of select="$description"/></svg:desc>

<xsl:comment>Image SVG générée dynamiquement</xsl:comment>
<xsl:comment>XSLT réalisée par C.COMPAGNON pour AGS dans le cadre de la documentation automatique</xsl:comment>
<xsl:comment>version 1.0</xsl:comment>

<svg:defs>
<xsl:call-template name="svg-defs"/>
</svg:defs>

<xsl:call-template name="svg-trace"/>

</svg:svg>

<ul class="menu">
<li><a href="../index.html">Sommaire</a></li>
<li> | </li>
<li><a href="xml-xsl.html">XML/XSL</a></li>
<li> | </li>
<li><a href="contacts.html">Contacts</a></li>
</ul>

<div class="centre">
<table id="footer">
<tr>
<td><a href="http://www.freebsd.org"><img src="../freebsd.png" alt="FreeBSD" style="border:0px"/></a></td>
<td><a href="http://www.apache.org"><img src="../apache.png" alt="Apache" style="border:0px"/></a></td>
<td>
</td>
<td><img src="../valid-css.png" alt="CSS 2.0" style="border:0px"/></td>
<td><a href="http://validator.w3.org/check?uri=referer"><img src="../valid-xhtml.png" alt="XHTML 1.1" style="border:0px"/></a></td>
</tr>
</table>
</div>

</div>
<div class="copyright"><a href="poweo.html">Ce serveur fonctionne à l'énergie renouvelable</a><br/>© 2009, Christopher Compagnon. Tous droits réservés.</div>

</div>
</body>
</html>

</xsl:template>



<!-- ========================== Template =========================== -->

<xsl:template name="svg-defs">
<!-- définition des objets graphiques -->
<xsl:for-each select="$tree/node">

<svg:g>
<xsl:attribute name="id"><xsl:value-of select="concat('element_',@level,'_',@id)"/></xsl:attribute>
<svg:rect>
<xsl:attribute name="x">0</xsl:attribute>
<xsl:attribute name="y">0</xsl:attribute>
<xsl:attribute name="width">200</xsl:attribute>
<xsl:attribute name="height">30</xsl:attribute>
<xsl:attribute name="rx">15</xsl:attribute>
<xsl:attribute name="ry">15</xsl:attribute>
<xsl:attribute name="style">fill: none; stroke: black; stroke-width: 1;</xsl:attribute>
</svg:rect>

<!-- tracé du connecteur antérieur -->
<svg:line x1="100" y1="0" x2="100" y2="-30" style="fill: none; stroke: black; stroke-width: 1;" />
<svg:circle  cx="100" cy="-30" r="3"/>
<svg:path d="M 95 -15 L 105 -15 L 100 -8 Z"/>

<!-- tracé du connecteur postérieur -->
<svg:line x1="100" y1="30" x2="100" y2="60" style="fill: none; stroke: black; stroke-width: 1;" />
<svg:circle  cx="100" cy="60" r="3"/>

<svg:text x="100" y="19" style="font-family: Arial, Sans-serif; text-anchor: middle; font-size: 10px;"><xsl:value-of select="@label"/></svg:text>
</svg:g>

</xsl:for-each>
</xsl:template>



<xsl:template name="svg-trace">

<!-- tracé des noeuds -->
<xsl:for-each select="$tree/node">
<xsl:variable name="level" select="@level"/>

<!-- Pour le niveau n -->
<xsl:variable name="nb-elements">
<xsl:call-template name="compte-elements-niveau">
<xsl:with-param name="level" select="$level"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="width-niveau" select="( $nb-elements * 220 ) + 50"/>
<xsl:variable name="centre-niveau" select="$width-niveau div 2"/>
<xsl:variable name="correction" select="$middle-width - $centre-niveau"/>

<xsl:variable name="X" select="((@order - 1) * 220) + 25 + $correction"/>
<xsl:variable name="Y" select="(( @level - 1) * 150) + 30"/>

<svg:use>
<xsl:attribute name="xlink:href">#<xsl:value-of select="concat('element_',@level,'_',@id)"/></xsl:attribute>
<xsl:attribute name="transform">translate(<xsl:value-of select="$X"/>,<xsl:value-of select="$Y"/>)</xsl:attribute>
</svg:use>

<!-- tracé des liens -->
<xsl:for-each select="parent">
<xsl:variable name="x0" select="$X + 100"/>
<xsl:variable name="y0" select="$Y"/>

<xsl:variable name="x1">
<xsl:call-template name="coord-parent-x">
<xsl:with-param name="level" select="@level"/>
<xsl:with-param name="id" select="@id"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="y1">
<xsl:call-template name="coord-parent-y">
<xsl:with-param name="level" select="@level"/>
<xsl:with-param name="id" select="@id"/>
</xsl:call-template>
</xsl:variable>

<!-- Pour le niveau n - 1 -->
<xsl:variable name="nb-elements-n-1">
<xsl:call-template name="compte-elements-niveau">
<xsl:with-param name="level" select="@level"/>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="width-niveau-n-1" select="( $nb-elements-n-1 * 220 ) + 50"/>
<xsl:variable name="centre-niveau-n-1" select="$width-niveau-n-1 div 2"/>
<xsl:variable name="correction-n-1" select="$middle-width - $centre-niveau-n-1"/>


<xsl:variable name="x2" select="$x1 + $correction-n-1 + 100"/>
<xsl:variable name="y2" select="$y1 + 30"/>

<svg:line>
<xsl:attribute name="x1"><xsl:value-of select="$x0"/></xsl:attribute>
<xsl:attribute name="y1"><xsl:value-of select="$y0 - 30"/></xsl:attribute>
<xsl:attribute name="x2"><xsl:value-of select="$x2"/></xsl:attribute>
<xsl:attribute name="y2"><xsl:value-of select="$y2 + 30"/></xsl:attribute>
<xsl:attribute name="style">fill: none; stroke: black; stroke-width: 1;</xsl:attribute>
</svg:line>


</xsl:for-each>



</xsl:for-each>

</xsl:template>


<!-- ================================================================== -->
</xsl:stylesheet>