XML et XSL

Petit nouveau ! | 7 Messages

01 déc. 2007, 22:35

salut tout le monde
cvp je cherche a réaliser une requête avec XSL sur ce fichier XML

la requête :je cherche le mécanicien ayant effectué le plus d'heures de travail du 10/07/2007 au 12/07/2007, bornes comprises.
le fichier XML et la DTD est comme suite

le fichier :garage.xml

Code : Tout sélectionner

<?xml version="1.0" encoding="iso-8859-1"?> <?DOCTYPE garage SYSTEM "garage2.dtd"?> <?xml-stylesheet href="r1.xsl" type="text/xsl"?> <garage> <vehicule immatriculation="1234 CX 80" nom="Dupont" marque="Peugeot" type="406"/> <vehicule immatriculation="5678 DY 80" nom="Durand" marque="Dupont" type="Carpatia"/> <vehicule immatriculation="9012 EZ 80" nom="Duchemini" marque=" Alpha Roméo " type="ZP"/> <proprietaire nom="Dupont" prenom="Georges"/> <proprietaire nom="Durand" prenom="Joseph"/> <proprietaire nom="Duchemini" prenom="Alfredo"/> <reparation numo="123" immatriculation="1234 CX 80" date_entree="10/07/2007" date_sortie="11/07/2007" /> <reparation numo="124" immatriculation="5678 DY 80" date_entree="12/07/2007"/> <reparation numo="125" immatriculation="9012 EZ 80" date_entree="11/07/2007" date_sortie="12/07/2007" /> <mecanicien numeca="12" nom="Terieur" prenom="Alain"/> <mecanicien numeca="13" nom="Terieur" prenom="Alex"/> <mecanicien numeca="14" nom="Brindavoine" prenom="Wilfrid"/> <mecanicien numeca="15" nom="Chauvaux" prenom="Bernard"/> <mecanicien numeca="16" nom="Veaufroid" prenom="jules"/> <mec_rep numo="123" numeca="12" nbh="2"/> <mec_rep numo="123" numeca="13" nbh="3.5"/> <mec_rep numo="124" numeca="12" nbh="4"/> <mec_rep numo="124" numeca="14" nbh="6"/> <mec_rep numo="125" numeca="13" nbh="1"/> <mec_rep numo="125" numeca="15" nbh="2.5"/> <mec_rep numo="125" numeca="16" nbh="1"/> </garage>
le fichier garage2.dtd


Code : Tout sélectionner

<!ELEMENT garage (vehicule+, proprietaire+, reparatio+, mecanicien+, mec_rep+)> <!ELEMENT vehicule EMPTY> <!ATTLIST vehicule immatriculation ID #REQUIRED> <!ATTLIST vehicule nom IDREF #REQUIRED> <!ATTLIST vehicule marque CDATA #REQUIRED> <!ATTLIST vehicule type CDATA #REQUIRED> <!ELEMENT proprietaire EMPTY> <!ATTLIST proprietaire nom ID #REQUIRED> <!ATTLIST proprietaire prenom CDATA #REQUIRED> <!ELEMENT reparation EMPTY> <!ATTLIST reparation numo ID #REQUIRED> <!ATTLIST reparation immatriculation IDREF #REQUIRED> <!ATTLIST reparation date_entree CDATA #REQUIRED> <!ATTLIST reparation date_sortie CDATA #IMPLIED > <!ELEMENT mecanicien EMPTY> <!ATTLIST mecanicien numeca ID #REQUIRED> <!ATTLIST mecanicien nom ID #REQUIRED> <!ATTLIST mecanicien prenom CDATA #REQUIRED> <!ELEMENT mec_rep EMPTY> <!ATTLIST mec_rep numeca IDREF #REQUIRED> <!ATTLIST mec_rep numo IDREF #REQUIRED> <!ATTLIST mec_rep nbh CDATA #REQUIRED>

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

01 déc. 2007, 22:53

réaliser une requête avec XSL
...un requête XSL ? Je ne suis pas sûr de comprendre, XSL est un langage de mise en forme, XSLT un langage de transformation, tu n'effectues pas de requête. XPath permet de rechercher des nœuds, mais ne permet pas de les classer.

Tu pourrais peut-être trouver une solution à base de <xsl:sort> + <xsl:if test="position() = 1"> mais c'est relativement compliqué pour pas grand-chose. As-tu essayé de récupérer toutes tes valeurs via PHP et faire le classement par un sort() ou un truc du genre ?

Edit : j'ai dit "relativement compliqué" avant de me rendre compte qu'il fallait en plus de ça grouper les résultat par mécanicien, ce qui rend l'opération "très compliquée". Ce n'est pas impossible, mais c'est comme faire un Jenga avec des gants de boxe, regarde du côté de PHP plutôt.

Petit nouveau ! | 7 Messages

02 déc. 2007, 18:57

non ,pas tout a fait une requête mais en peut filtre les donnée avec xsl
par ex:
requête: Rechercher les mécaniciens ayant travaillé sur la réparation 123

le fichier xsl suivent va faire ce travaille

Code : Tout sélectionner

<?xml version="1.0" encoding="ISO-8859-1"?> <!-- La feuille de style associée --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="ISO-8859-1"/> <xsl:template match="/"> <HTML> <BODY> <TABLE WIDTH="50%" BORDER="1" ALIGN="center" cellspacing="0"> <TR align="center"> <TD width="40%">reparation</TD> <TD>Mecanicien</TD> </TR> <TR> <td colspan="2"> <table border="1" cellspacing="0"> <tr> <TD WIDTH="8%">numo</TD> <TD WIDTH="8%">date_entree</TD> <TD WIDTH="8%">date_sortie</TD> <td> <table border="1" cellspacing="0" width="100%"><tr> <TD WIDTH="25%">numeca</TD> <TD WIDTH="25%">nom</TD> <TD WIDTH="25%">prenom</TD> <TD WIDTH="25%">nbh</TD> </tr></table> </td> </tr> <xsl:for-each select="garage/reparation[@numo=123]"> <xsl:variable name="numr" select="@numo"/> <tr> <td><xsl:value-of select="@numo"/></td> <td><xsl:value-of select="@date_entree"/></td> <td><xsl:value-of select="@date_sortie"/></td> <td> <table border="1" cellspacing="0" width="100%"> <xsl:for-each select="../mec_rep[@numo=$numr]"> <xsl:variable name="nummic" select="@numeca"/> <xsl:variable name="hnb" select="@nbh"/> <xsl:for-each select="../mecanicien[@numeca=$nummic]"> <tr> <td width="24%"><xsl:value-of select="@numeca"/></td> <td width="23%"><xsl:value-of select="@nom"/></td> <td width="26"><xsl:value-of select="@prenom"/></td> <td width="23%"><xsl:value-of select="$hnb"/></td> </tr> </xsl:for-each> </xsl:for-each> </table> </td> </tr> </xsl:for-each> </table> </td> </TR> </TABLE> </BODY> </HTML> </xsl:template> </xsl:stylesheet>
alors moi j'arrive pas à réaliser la requête précèdente (cherche le mécanicien ayant effectué le plus d'heures de travail du 10/07/2007 au 12/07/2007, bornes comprises)

et il faut utiliser juste le html et le xsl pour présenter ces données

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

02 déc. 2007, 20:05

il faut utiliser juste le html et le xsl pour présenter ces données
Là le problème c'est que tu ne présentes pas des données, tu génères des données, et XSLT n'est pas fait pour ça.

J'ai jeté un œil sur une possible solution, mais j'ai abandonné au bout d'un quart d'heure à batailler avec mes variables. La solution (qui prendrait environ une centaine de lignes bien serrées) devrait se dérouler comme suit
  • créer une variable $ids contenant la liste unique des //mecanicien@numeca dans des éléments numeca
  • créer une variable $totaux
    • créer une boucle sur $ids/numeca, chaque itération récupère le nombre de nœuds count(//mec_rep[@numeca=./numeca)
    • utiliser une template recursive pour calculer la somme des heures de chaque mecanicien
  • créer une boucle sur $totaux classée par ordre descendant en filtrant tous les résultats dont position() > 1
Pour résumer, à moins de trouver un expert XSLT qui travaille à l'œil tu devrais plutôt regarder du côté du programme qui génère ces données pour qu'il génère ce dont tu as besoin.

Edit: après vérification, sum() est disponible en XSLT 1.0 donc tout espoir n'est pas perdu, ça facilite la création de $totaux

Je te laisse quand même ce que j'ai fait, si tu le finis merci de poster le résultat ici

Code : Tout sélectionner

<?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="iso-8859-1" /> <xsl:template match="/"> <xsl:variable name="meca_nbh"> <xsl:for-each select="//mecanicien"> <xsl:sort select="@numeca" data-type="number" order="ascending" /> <!-- Keep only the first occurence of each user_id --> <xsl:if test="generate-id(.) = generate-id(//mecanicien[@numeca=current()/@numeca][position() = 1])"> <xsl:element name="mecanicien"> <xsl:attribute name="numeca"> <xsl:value-of select="./@numeca" /> </xsl:attribute> <xsl:attribute name="nbh"> <xsl:value-of select="sum(//mec_rep[@numeca=current()/@numeca]/@nbh)" /> </xsl:attribute> </xsl:element> </xsl:if> </xsl:for-each> </xsl:variable> <xsl:for-each select="$meca_nbh/mecanicien"> <xsl:sort select="nbh" data-type="number" order="descending" /> </xsl:for-each> </xsl:template> </xsl:stylesheet>

Petit nouveau ! | 7 Messages

04 déc. 2007, 12:43

une personne ma envoyer ce code mais il y a un problème
mais l'idée est bonne

Code : Tout sélectionner

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <xsl:variable name="listmc"> <list> <xsl:for-each select="//mecanicien/@numeca"> <mec> <xsl:variable name="id" select="."/> <xsl:attribute name="numeca"><xsl:value-of select="$id"/></xsl:attribute> <xsl:value-of select="sum(//mec_rep[@numeca=$id]/@nbh)"/> </mec> </xsl:for-each> </list> </xsl:variable> <result> <xsl:for-each select="$listmc//mec"> <xsl:sort/> <xsl:if test="position()=last()"> <xsl:value-of select="@id"/> <xsl:value-of select="."/> </xsl:if> </xsl:for-each> </result> </xsl:template> </xsl:stylesheet>
a priori il y a un soucis avec le for-each