XSL - XSL-FO

Définition

XSL-FO (eXtensible Stylesheet Language – Formatting Objects) est le dernier langage, après XSLT et Xpath, de la famille XSL. Ce langage permet le formattage d'un document XML afin de mettre en forme ce dernier dans un document « final » (un fichier PDF par exemple).

XSL-FO est une recommandation du W3C depuis le 15 octobre 2001.




Fonctionnement

Tout comme pour XSLT, un fichier XSLT-FO (format .fo) est avant tout un fichier XML. Encore une fois, le langage XSLT-FO est un langage basé sur le langage XML. Cela n'est pas le fruit du hasard et permet des tâches automatisées très intéressantes comme nous le verrons plus tard.

Un document XSL-FO permet de décrire le document de sortie désiré grâce à plusieurs balises spéciales définissant le type de document voulu, le titre de celui-ci, la taille des marges, le texte des en-têtes etc.

Une fois la feuille XSL-FO écrite, il suffit de faire appel à un processeur XSL-FO qui va générer un fichier final en suivant précisement les règles écrites dans la feuille .fo




Exemple

Voici un exemple très simple d'un fichier .fo :

Comme vu précédemment, une feuille XSL-FO est avant tout une feuille XML. Ainsi, on retrouve une nouvelle fois la balise spéciale xml en haut du document. Encore une fois, il n'y a ici qu'un seul noeud racine, et encore une fois il s'agit ici d'une balise spéciale (fo:root) spécifiant que nous sommes ici dans une feuille XSL-FO.

La première partie du document (la balise layout-master-set) permet de définir les différents patrons qui seront utilisés pour créer le document. Ici, nous n'avons qu'un seul patron (region-body) pour lequel nous précisons quelques propriétés, comme le nombre de colonne ou les marges.

La deuxième partie du document décrit le contenu du rendu final. Ici, on décrit le contenu de notre patron "region-body". On utilise ici un élément "block" (un paragraphe) avec un alignement centré et une couleur de police bleu, dans lequel nous écrivons "Bonjour !".

Ce simple fichier XSL-FO permet la création d'un document tout simple ne contenant qu'une unique phrase "Bonjour" en bleu avec une police 10. Il est bien sur possible de créer des choses bien plus complexes comme nous allons le voir plus loin. Le but ici est seulement de donner un apercu des possibilités de XSL-FO, notamment lorsqu'il est utilisé conjointement avec les autres langages XSL. Pour une description plus détaillé du langage, voir la page de liens.




XSLT + XSL-FO

Un fichier XSL-FO est donc avant tout un fichier XML. Nous allons maintenant voir pourquoi cela est important et surtout très utile. Dans le chapitre précédent, nous avions vu qu'une feuille de style XSLT permet de transformer un document XML en un autre document XML. Ainsi, il est donc possible de transformer un fichier XML en un fichier XSL-FO grâce à XSLT puis d'utiliser ce fichier XSL-FO pour créer un document final, comme un pdf. On se retrouve ici avec une chaine du style :

qui permet de transformer de manière totalement automatisée un document XML simple en un document pdf (par exemple).

Pour illuster les possibilités offertes par l'ensemble de la famille XSL, reprenons notre exemple de document XML décrivant une école :


Ecrivons maintenant une feuille de style XSLT pour transformer notre fichier XML en un fichier XSL-FO :

			
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
	<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" >
	
	<!-- Déclaration de la mise en page -->
		<fo:layout-master-set>
		<fo:simple-page-master master-name="Hogwarts" margin="2cm">
			<fo:region-body margin="1.5cm 0 2cm 0" column-count="1" />
			<fo:region-before extent="1cm" />
			<fo:region-after precedence="true" extent="1cm" />
		</fo:simple-page-master>
		</fo:layout-master-set>
		
	<!-- Corps du document -->
		<fo:page-sequence master-reference="Hogwarts" font-family="Times" font-size="10pt" line-height="1.5em" text-align="justify">
			<fo:static-content flow-name="xsl-region-before">

				<fo:table table-layout="fixed" border-bottom="1px solid #ccc" font-size=".9em" color="#666">
					<fo:table-column column-width="5cm" />
					<fo:table-column column-width="6.31cm" />
					<fo:table-column column-width="5cm" />
					<fo:table-body>
						<fo:table-row>
							<fo:table-cell>
								<fo:block>Février 2012</fo:block>
							</fo:table-cell>
							<fo:table-cell>
								<fo:block text-align="center" font-weight="bold">POUDLARD</fo:block>
							</fo:table-cell>
							<fo:table-cell>
								<fo:block text-align="right">Effectifs</fo:block>
							</fo:table-cell>
						</fo:table-row>
					</fo:table-body>
				</fo:table>
			</fo:static-content>
			<fo:static-content flow-name="xsl-region-after">
				<fo:block border-top="1px solid #ccc" color="#666" font-size=".9em" text-align="center">page <fo:page-number /></fo:block>
			</fo:static-content>
			<fo:flow flow-name="xsl-region-body">
				<!-- un titre -->
				<fo:block font-size="40pt" font-weight="bold" space-after="1em" text-align="center" color="red">
					Poudlard
				</fo:block>
				<fo:block font-style="italic" font-size="14pt" border-bottom="1px solid #999" space-after="2em" text-align="center" color="blue"> 
				Promotion 1998
				</fo:block>
				<fo:block text-indent="2em" space-after="1em" font-size="12pt" text-align="center" font-weight="bold">
				   Les professeurs à Poudlard sont :
				</fo:block>
				<xsl:for-each select="hogwarts/prof">
					<xsl:sort select="nom"/>
					<fo:block text-indent="2em" space-after="2em" font-size="10pt" text-align="center" font-weight="normal"> Mr <xsl:value-of select="nom"/><xsl:text> </xsl:text><xsl:value-of select="prenom"/></fo:block>
				</xsl:for-each>
	
				<fo:block text-indent="2em" space-after="1em" font-size="12pt" text-align="center" font-weight="bold">
				   Les élèves de Poudlard sont :
				</fo:block>
				<xsl:for-each select="hogwarts/élève">
					<xsl:sort select="nom"/>
					<fo:block text-indent="2em" space-after="2em" font-size="10pt" text-align="center" font-weight="normal"><xsl:value-of select="nom"/><xsl:text> </xsl:text><xsl:value-of select="prenom"/></fo:block>
				</xsl:for-each>
				
				<fo:block font-style="italic" font-size="14pt" border-bottom="1px solid #999" space-after="2em" text-align="center" color="blue"> 
				Résultats
				</fo:block>
				
				<fo:block text-indent="2em" space-after="2em" font-size="12pt" text-align="left" font-weight="bold">
				   Potion :
				</fo:block>
				   <xsl:for-each select="hogwarts/élève">
						<xsl:if test="matiere[@nom='Potion']/@note > 9">
							<fo:block text-indent="2em" space-after="0em" font-size="10pt" font-weight="normal" color="green"><xsl:value-of select="nom"/><xsl:text> </xsl:text><xsl:value-of select="prenom"/> a validé la matière avec la note de <xsl:value-of select="matiere[@nom='Potion']/@note"/></fo:block>
						</xsl:if>
						<xsl:if	test="matiere[@nom='Potion']/@note < 10">
							<fo:block text-indent="2em" space-after="0em" font-size="10pt" font-weight="normal" color="red"><xsl:value-of select="nom"/><xsl:text> </xsl:text><xsl:value-of select="prenom"/> n'a PAS validé la matière la note de <xsl:value-of select="matiere[@nom='Potion']/@note"/></fo:block>
						</xsl:if>
				 </xsl:for-each>
				 
				<fo:block text-indent="2em" space-after="2em" space-before="10em" font-size="12pt" text-align="left" font-weight="bold">
				   Divination :
				</fo:block>
				   <xsl:for-each select="hogwarts/élève">
						<xsl:if test="matiere[@nom='Divination']/@note > 9">
							<fo:block text-indent="2em" space-after="0em" font-size="10pt" font-weight="normal" color="green"><xsl:value-of select="nom"/><xsl:text> </xsl:text><xsl:value-of select="prenom"/> a validé la matière avec la note de <xsl:value-of select="matiere[@nom='Divination']/@note"/></fo:block>
						</xsl:if>
						<xsl:if	test="matiere[@nom='Divination']/@note < 10">
							<fo:block text-indent="2em" space-after="0em" font-size="10pt" font-weight="normal" color="red"><xsl:value-of select="nom"/><xsl:text> </xsl:text><xsl:value-of select="prenom"/> n'a PAS validé la matière avec la note de <xsl:value-of select="matiere[@nom='Divination']/@note"/></fo:block>
						</xsl:if>
				 </xsl:for-each>
								
			</fo:flow>
		</fo:page-sequence>	

	</fo:root>	
</xsl:template>
</xsl:stylesheet>

La feuille de style est ici bien plus complexe que ce que l'on a pu voir précédemment. Néanmoins le principe est identique : nous fabriquons un nouveau fichier XML, ici un fichier XSL-FO, à partir des informations contenu dans notre document XML d'origine. L'utilisation simultanée des balises XSLT, des balises XSL-FO et des expressions XPath nous permet de définir un fichier pdf totalement dynamiquement à partir des multiples informations éparpillées dans le document XML d'origine.

Finalement, après transformation XSLT nous obtenons un fichier.fo qui s'avère être un fichier XSL-FO tout à fait valide. Il n'y a plus qu'à utiliser un processeur XSL-FO pour obtenir le document final, en format pdf :

Le fichier PDF final