objectif : parser un fichier xml, récupérer les valeurs afin de les insérer dans une base de données mysql :
fichier source xml avec des records du type :

<XML>
<RECORDS>
<RECORD>
<REFERENCE_TYPE>0</REFERENCE_TYPE> 
<REFNUM>1</REFNUM> 
<AUTHORS>
<AUTHOR>Fortino, S. trad</AUTHOR> 
<AUTHOR>bigoudi</AUTHOR> 
</AUTHORS>
<YEAR>1993</YEAR> 
<TITLE>Mexique : des femmes partie prenante du mouvement social</TITLE> 
<SECONDARY_TITLE>Cahiers du Feminisme</SECONDARY_TITLE> 
<CUSTOM4>T & M</CUSTOM4> 
<ABSTRACT>Deux experiences sont relatees : la creation de la Maison de la femme "Rosario Castellanos" a Oaxaca qui a pour but d'offrir un soutien aux femmes et d'impulser des groupes de prise de conscience ; la creation de la COCODEM (Commission de coordination pour le developpement de la femme) au sein des syndicats enseignants pour faire prendre en compte les inegalites de genre par les instances syndicales</ABSTRACT> 
<NOTES>Using Smart Source Parsing 1994; (67-68) 38-42 ill French</NOTES> 
</RECORD>
...
</RECORDS>

La feuille de style associé est la suivante :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" /> 
<xsl:template match="/">
<xsl:for-each select="RECORDS/RECORD">
insert into category(<xsl:for-each select="*"> 
<xsl:value-of select="name()" /> 
<xsl:if test="position() != count(../*)">,</xsl:if> 
</xsl:for-each>)
values ( <xsl:for-each select="*">
<xsl:if test="not(number(.) or (number(.)=0))">"</xsl:if> 
<xsl:value-of select="normalize-space(.)" /> 
<xsl:for-each select="./AUTHOR">
<xsl:value-of select="." /> 
<xsl:if test="position() !=last()">
<xsl:if test="position() != count(../*)">;</xsl:if> 
</xsl:if>
</xsl:for-each>
<xsl:if test="position() = count(../*)" /> 
<xsl:if test="not(number(.) or (number(.)=0))">"</xsl:if> 
<xsl:if test="position() != count(../*)">,</xsl:if> 
</xsl:for-each>) 
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Le problème que je n'arrive pas à résoudre c'est que la valeur du champ AUTHORS est reproduite 2 fois (redondance) :
"Fortino Sabine bigoudiFortino Sabine; bigoudi"
alors que l'objectif est de ne récupérer que la valeur "Fortino Sabine;bigoudi" le point virgue (;) étant le séparateur des 2 valeurs de l'attribut auteur.
voilà est-ce clair? : en parcourant la liste je n'ai pas trouvé non plus la solution àmlon problème, c'est pourquoi je me suis résolu à en faire état désireux de sortir de l'impasse dans laquelle je patauge depuis quelque temps Smiley decu
adresse pour constater l'effet du script actuel :
http://publications.u-paris10.fr/seb2.xml

merci d'avance Smiley smile
Modifié par roro2005 (05 Nov 2005 - 19:59)
Administrateur
Hello roro2005 et bienvenue ici,

Attention à l'écriture correcte des codes dans les messages du forum.
Tu as dû survoler les Règles et ne pas lire celle qui recommande de baliser correctement tes codes afin de faciliter leur lecture.

Je t'invite à modifier ton premier message en conséquence.

Bonne chance Smiley smile

EDIT : grillé Smiley cligne
Modifié par Raphael (05 Nov 2005 - 10:17)
Administrateur
Bonjour,

pourrais-tu STP utiliser le bouton Editer là haut sur cette page, en haut à droite de ton premier message pour faire cette correction ET rajouter les balises [ code]? Si tu ne comprends pas les explications écrites dans les Règles et comment les appliquer en pratique, demande par Message Privé (en bas à gauche d'un message de moi-même ou Raphael ou n'importe quel autre modérateur) ou au pire ici ...
Bonjour roro2005,

Je ne voudrais pas te décourager, mais il me semble que la structure de ton code xsl n'est pas du tout adapter à a philosophie XSL. Tu as probablement l'habitude des langages procéduraux et tu as conservé cet esprit pour coder ta transformation XSLT.
Tu vas probablement rencontrer d'autres problèmes délicats lorsque ton source XML va évoluer (plusieurs éléments record, ...). Faire évoluer un tel code est un jeu d'équilibre particulièrement instable.

Si tu t'intéresses à XSLT, mieux vaut reprendre tout à zéro. Les points me parraissant essentiels avec XSLT sont les suivants :
- créer des templates (pour chaque paternes, sous paternes ...)
- appliquer des templates
- laisser faire la récursivité
Si tu t'efforces d'aller dans ce sens, les if vont disparaître, des bouts de code simples, autonomes et porteur de sens vont apparaître pour former un tout modulaire. xsl:for-each n'est pas mauvais en soi, mais dans ton cas évite les à tout prix.

Pour terminer j'indique malgré tout un correctif dans le contexte du code que tu as fourni, et pour le bug soulevé uniquement. Remplace simplement :
<xsl:value-of select="normalize-space(.)" />
par
<xsl:if test="name()!='AUTHORS'">
<xsl:value-of select="normalize-space(.)" />
</xsl:if>
Mais sincèrement il est plus que navrant d'avoir à écrire ce if, parce que c'est un if, mais bien pire encore parce qu'il teste un noeud. Les bonnes pratiques sont à l'opposé : laisser parcourir les listes de noeuds, ignorer les noeuds qui ne nous intéressent pas, et appliquer des templates pour les autres.
Modifié par Xavier (06 Nov 2005 - 20:58)
Merci Xavier Smiley smile
ça marche avec la correction que tu m'as indiqué.
Pour le moment ça suffit pour ce que j'ai à faire : en conscience que je suis très éloigné d'une solution en phase avec la philosophie XSL et que pour traiter des fichiers source plus complexes il faut reprendre le problème à zéro.
roro2005 a écrit :
ça marche avec la correction que tu m'as indiqué.
Oui bien sur mais à quel prix ! Tout se passe comme s'il y avait 2 boucles imbriquées qui toutes les 2 traitent le même noeud. Du coup il faut tester dans la boucle mère si la boucle fille va le traiter aussi pour dans ce cas ne pas le traiter dans la mère.

C'est un défi à toutes les bonnes pratiques, et je regrette presque d'avoir publié ces lignes Smiley confus
Bonjour a Tous,

A propos des "bonnes pratiques",

Je ne sais pas quelle stratégie appliquée dans mes fichiers XSL.

Utiliser des notations absolues ou pas dans les <xsl:template>?

Et puis, je ne sais pas si je dois systématiquement appeler <xsl:apply-templates/> a l' intérieure de mes règles...

Ca a pour conséquence, d' appeler les règles par défaut et j' ai des affichages impromptus....

J' utilise les DTD pour valider a priori la structure de mes fichiers XML mais je suis un parano de la détection d' erreur....

Bien sur je débute en XSL....
Bonjour Datz,

Ta question de la définition des bonnes pratiques est intéressante, mériterait d'être posée dans un sujet à part entière et de recueillir plusieurs avis.

Personnellement, comme pour toute problématique se traitant sur un plan conceptuel, je recherche les invariants et je les classe des plus génériques aux plus spécifiques. Souvent ces invariants n'existent pas en eux-mêmes, il faut les définir ou les construire. Dans cet exercice il faut toujours factoriser le maximum de choses du coté le plus générique : se concentrer sur la recherche du maximum d'abstraction.

Pour XSLT du plus générique au plus spécifique :
- définition et appel d’un template avec attribut match générique
- idem avec utilisation de modes
- idem avec variables
- définition et appel d’un template nommé

L’emploi de templates nommés est rarement utile, son excès indique que l'on en en train de "programmer" et de quitter l'esprit template.

La récursivité naturelle est un bon point. Avec la récursivité, c'est le moteur qui travaille à la place du programmeur. Ce dernier doit effet éviter de déterminer un cheminement causal dans l’arbre XML.
La récursivité est facilitée par la définition de templates génériques. Elle est également facilitée lorsque l’appel d’un template fils concernant un sous arbre du template appelant. Lorsque l'appel ne concerne pas un sous arbre du template appelant, la maîtrise de la transformation devient difficile (risque de boucle infinie, ou de résultat très différent du résultat attendu). L'utilisation de clefs permets souvent d'éviter l'appel sur une autre branche de l'arbre.
datz a écrit :
je ne sais pas si je dois systématiquement appeler <xsl:apply-templates/> a l' intérieure de mes règles
Systématiquement, certainement pas.

Pour terminer je suis tenté de donner 2 contre exemples à ce que je disais plus haut :

1/ Dimitre Novatchev a réussi un brillant exercice de style en définissant une abstraction basée sur des appels ultra spécifique. Cela permet de transformer XSLT d'un langage déclaratif en un langage de programmation fonctionnel. Une très belle construction, à regarder par curiosité, mais à ne pas imiter (sauf à avoir une très bonne maîtrise de la norme) : http://fxsl.sourceforge.net/

2/ La récursivité que la norme XSLT proposée par défaut, est celle que tout le monde connaît : parcours de l’arbre par passage récursif d’un nœud vers l’ensemble de ses fils. J'ai découvert que cette façon de parcourir les arbres n’était pas la plus générique. Ce parcours naturel des arbres ne permet pas de résoudre certaines classes de problèmes. Sans entrer dans le détail, cette méthode de descente des arbres introduit une dissymétrie inutile entre la largeur de l’arbre et sa profondeur et de ce fait n’autorise pas un bon découplage entre l’algorithme de cheminement dans l’arbre et le traitement sur des nœuds faisant l’objet du parcours de l’arbre. La norme XSLT est donc faible dans son processus récursif par défaut. Heureusement il est possible de rectifier le tir pour les cas (rares) qui le nécessitent ; le procédé est cependant déroutant et je ne vais pas emmêler plus les esprits maintenant.