TP 7, 17/11/2009

Par Benoît Valiron <benoit.valiron [at] monoidal.net> et Jean Baptiste FADOUL <jean-baptiste.faddoul [at] xrce.xerox.com>

Ce TP reprend en grande partie le TD 7.

  1. Téléchargez le Document 1. En TD nous avons trouvé des expressions XPath pour déterminer les points suivant :

    1. les éléments acteur ;

      /child::liste_acteurs/child::acteur
      /liste_acteurs/acteur
      /descendant::acteur
      //acteur
    2. le nombre d'acteur décrit dans le document XML ;

      ount(/child::liste_acteurs/child::acteur)
      count(/liste_acteurs/acteur)
      count(/descendant::acteur)
      count(//acteur)
    3. tous les noeuds "film"

      //film
    4. la liste des films nommés dans la biographie de Hilary Swant

      //acteur[@id="hilary"]//film
      /list_acteurs/acteur[nom="Swant"]//film
      /list_acteurs/acteur/nom[text()="Swant"]/..//film
    5. le premier noeud fils du premier noeud acteur ;

      /descendant::acteur[position()=1]/*[position()=1]
      //acteur[1]/*[1]
    6. le premier noeud fils du deuxième noeud acteur ;

      /descendant::acteur[position()=2]/*[position()=1]
      //acteur[2]/*[1]
    7. les deux premiers éléments fils de chaque acteur ;

      /descendant::acteur/*[position()=1 or position()=2]
            //acteur/*[position()<=2]
    8. le dernier élément fils de chaque acteur ;

      /descendant::acteur/*[position()=last()]
      //acteur/*[last()]
    9. l'acteur dont l'identifiant est clint ;

      /descendant::acteur[attribute::id='clint']
      //acteur[@id='clint']
    10. l'acteur dont le prénom est Clint ;

      /descendant::acteur[child::prenom/text()='Clint']  
      //acteur[prenom='Clint']
    11. les noms des acteurs dont la biographie contient exactement deux pgraphes ;

      //acteur/biographie/p[last()=2]/../../nom/text()
      //acteur/nom/text()[count(../../biographie/p)=2]
    Utilisez l'outil proposé sur le site du cours pour vérifier ce qui a été fait en TD. Vous avez pu trouver des réponses différentes : n'hésitez pas à les tester aussi !

  2. Téléchargez le Document 2. L'exercice 2 du TD (que nous avons sauté) demandait des expressions XPath déterminant

    1. le nombre de films disponibles ;

      count(//film)
    2. les acteurs du deuxième film ;

      //film[2]//acteur
    3. les titres des films dont la fiche est en anglais ;

      //film[@lang="en"]/titre/text()
    4. le nom du personnage dont l'identifiant est lukemonfils ;

      //acteur[@id="lukemonfils"]/@personnage
    5. le titre des films sortis en 1981 ;

      //film[annee/text()="1981"]/titre/text()
    6. le nombre de références faites au personnage dont l'identifiant est indy ;

      count(//perso[@ref="indy"])
    7. les films sans acteur ;

      //film[count(.//acteur)=0]
    8. les films avec plusieurs réalisateurs ;

      //film[contains('realisateur',',')]  
    9. les titres des films dont le synopsis contient le mot believe.

      //film[contains(synopsis,"believe")]/titre/text()
    Répondez au questions à l'aide de l'outil XPath proposé.

  3. Cet exercice ré-utilise le Document 2. Utilisez l'outil XSLT sur le site du cours pour faire les exercices.

    1. Continuez la feuille de style suivante :

      <stylesheet version="1.0" 
                  xmlns="http://www.w3.org/1999/XSL/Transform">
        <template match="/">
          .....
          .....
          .....
        </template>
      
      </stylesheet>

      Afin d'obtenir le résultat suivant :

      Sylvester Stallone joue rocky
      Talia Shire joue adrian
      ...

      <stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
        <template match="/films">
        
        <for-each select="film/casting/acteur">
          <value-of select="." /> joue <value-of select="@id" />
          <text>
      </text>
          
        </for-each>
        
        </template>
      </stylesheet>
      
    2. Que fait (et comment résoudre le problème) :

      <stylesheet version="1.0" 
                  xmlns="http://www.w3.org/1999/XSL/Transform">
        <template match="/films/film/casting/acteur">
            <value-of select="text()" /> joue <value-of select="@id" />
          <text>
      </text>
        
        </template>
      
      </stylesheet>

      Souvenez-vous qu'il y a des template par défaut qui sont toujours présent. Le comportement est le suivant : On par de la racine. Si on rencontre un noeud élément, on suit ses fils et on itère. Si on rencontre un noeud texte, on écrit le texte.

      Ce template affiche en plus du texte qui ne devrait pas être là. Pour résoudre le problème, il faut ajouter le template

      <template match="text()">
      </template>
            

      Le template qui gère les noeuds texte peut être réécrit en utilisant

      <template match="text()">
        NOUVEAU TEMPLATE
      </template>

      Remplacez NOUVEAU TEMPLATE par

      • *
      • (Noeud texte fils de <value-of select="name(..)"/>)

      et par rien, et voyez ce qui se passe. Pouvez-vous interpreter ?

    3. Écrire une feuille de style XSLT qui construit un document XML sous la forme suivante :

      <liste>
        <film>
          <acteur>NOM_ACTEUR</acteur>
          <titre>NOM_DU_FILM</titre>
        </film>
        <film>
          <acteur>NOM_ACTEUR</acteur>
          <titre>NOM_DU_FILM</titre>
        </film>
        ...
      </liste>

      Si vous voulez que ça fonctionne, il faut placer un préfixe sur les éléments du langage XSLT : remplacer le xmlns de l'élément stylesheet par xmlns:x et appliquez les préfixes aux bons endroits.

      <x:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
        <x:template match="/">
          <liste>
            <x:for-each select="/films/film/casting/acteur">
              <film>
              <acteur>
              <x:value-of select="." />
              </acteur>
              <titre>
              <x:value-of select="../../titre" />
              </titre>
              </film>
            </x:for-each>
          </liste>
        </x:template>
      </x:stylesheet>
    4. Que fait la feuille de style suivante ?

      <stylesheet version="1.0" 
                  xmlns="http://www.w3.org/1999/XSL/Transform">
        <template match="/films/film">
        
        <for-each select="synopsis/*|synopsis/text()">
          <if test="@ref">
            <variable name="x" select="@ref" />
            <value-of select="../../casting/acteur[@id=$x]/@personnage" />
          </if>
          <value-of select="." />
          
        </for-each>
        
        </template>
      </stylesheet>
    5. Écrivez une feuille de style XSLT qui produise le résultat suivant :

      rocky apparait 14 fois dans le synopsis
      adrian apparait 5 fois dans le synopsis
      paulie apparait 0 fois dans le synopsis
      creed apparait 3 fois dans le synopsis
      ...

      Le premier mot est le @id de chaque acteur et le chiffre est le nombre d'apparition de l'identifiant dans les balises <perso ...> du synopsis.

      <stylesheet version="1.0" 
                  xmlns="http://www.w3.org/1999/XSL/Transform">
        <template match="/films/film">
        
        <for-each select="synopsis/*|synopsis/text()">
          <if test="@ref">
            <variable name="x" select="@ref" />
            <value-of select="../../casting/acteur[@id=$x]/@personnage" />
          </if>
          <value-of select="." />
          
        </for-each>
        
        </template>
      </stylesheet>

      Question supplémentaire : vous verrez apparaitre une ligne

       apparait 0 fois dans le document

      sans premier mot. Quel est le problème, et pouvez-vous le résoudre ?

      <stylesheet version="1.0" 
                  xmlns="http://www.w3.org/1999/XSL/Transform">
        <template match="/films/film">
        
        <for-each select="casting/acteur">
           <variable name="x" select="@id" />
           <if test="$x">
           <value-of select="$x" /> apparait 
           <value-of select="count(//perso[@ref=$x])" /> fois dans le document
           </if>
        </for-each>
        </template>
      </stylesheet>
      

      ou

      <stylesheet version="1.0" 
                  xmlns="http://www.w3.org/1999/XSL/Transform">
        <template match="/films/film">
        
        <for-each select="casting/acteur[@id]">
           <variable name="x" select="@id" />
           <value-of select="$x" /> apparait 
           <value-of select="count(//perso[@ref=$x])" /> fois dans le document
        </for-each>
        </template>
      </stylesheet>