TD XML 1 Cuisine Soit le document recette.xml suivant : <?xml version="1.0" encoding="iso-8859-1"?> <recettes> <recette nomcourt="chiffonnade" nom="chiffonnade de jambon et d asperges à la Flamande" type="salée"> <materiel> <ingredient quantite="8">asperge</ingredient> <ingredient quantite="150g">jambon fumé</ingredient> <ingredient quantite="2">oeuf</ingredient> <ingredient quantite="6 cl">huile d olive</ingredient> <ingredient quantite="1 c. à soupe">persil haché</ingredient> <ingredient>poivre</ingredient> <ingredient>sel</ingredient> <ingredient>noix de muscade</ingredient> </materiel> <methode> A l aide du hache-légumes, r^aper les asperges en lanières d environ 1,5 mm d épaisseur et les cuire dans l eau salée. Couper également les tranches de jambon en longues lanières et les mélanger aux asperges cuites et tiédies. </méthode> </recette> <recette nomcourt="pain à l huile" nom="pressé d olive sur lit de blé" type="salée"> <materiel> <ingredient quantite="1 baguette">pain</ingredient> <ingredient quantite="3 c. à soupe">huile d olive</ingredient> </materiel> <methode> A l aide d un couteau éffilé, trancher la baguette sur toute sa longueur. Badigeonner délicatement chaque tranche avec l huile, et servir immédiatement. Attention, ce plat consitue un repas complet, tout dessert est inutile. </methode> </recette> </recettes> Questions générales Proposez une DTD pour laquelle ce document est valide. Cette DTD devra définir en particulier les éléments recettes, recette, materiel, methode et ingredient. Les attributs nom, nomcourt et type sont obligatoires, l attribut quantite est optionnel. Une recette est de type salée ou sucrée, et possède au moins un ingrédient. <!ELEMENT recettes (recette)*> <!ELEMENT recette (materiel,methode)> <!ATTLIST recette nomcourt CDATA #REQUIRED, nom CDATA #REQUIRED, type (salée sucrée) #REQUIRED> <!ELEMENT materiel (ingredient)+> <!ELEMENT ingredient #PCDATA> <!ATTLIST ingredient quantite CDATA #IMPLIED> <!ELEMENT methode #PCDATA> 1
Questions XPath : Donnez les expressions XPath correspondant aux requêtes suivantes : 1. Le nom complet de toutes les recettes ; /recettes/recette/@nom, ou //@nom. 2. Les ingrédients de la recette dont le nom court est Chiffonnade ; /recettes/recette[@nomcourt="chiffonnade"]/materiel/ingredient. 3. Le nom complet des recettes utilisant du persil haché ; /recettes/recette[materiel/ingredient="persil haché"]/@nom. //ingredient[.="persil haché"]/ancestor::*[2]/@nom. 4. Le nom complet des recettes ayant plus de deux ingrédients, et contenant de l huile d olive. /recettes/recette[count(materiel/ingredient)>2 and materiel/ingredient="huile d olive"]/@nom. /recettes/recette[materiel[count(ingredient)>2 and ingredient="huile d olive"]]/@nom. 2 Stockage XML Soit la représentation canonique d un document XML par une table relationnelle, respectant les conventions suivantes : id est l identifiant d un noeud, parid est l identifiant de son parent, position est sa position dans le sous-arbre du parent en suivant l ordre du document, element est le nom de l élément et type indique son type. Structure id parid position element type 1 0 1 jeu ref 5 1 1 sort ref 7 5 1 nom cdata 8 5 2 validite cdata 9 5 3 pouvoir cdata 10 1 2 competence ref 11 10 1 nom cdata 12 10 2 experience cdata Valeur id val 7 Malédiction du Borak 8 12 9 18 11 Tir à l arc 12 22 1. Dessinez l arbre XML correspondant à cette table (on ne fera figurer que les éléments et attributs). <jeu> <sort> <nom>malédiction du Borak</nom> <validite>12</validite> <pouvoir>18</pouvoir> </sort> <competence> <nom>tir à l arc</nom> <experience>22</experience> </competence> </jeu> 2
2. Donnez la requête XPath donnant le nom de toutes les compétences (mais pas le nom des sorts). /jeu/competence/nom. 3. Traduisez cette requête en SQL selon le schéma précédent. select val from Valeur, Structure s1,s2,s3 where s1.element="jeu" and s2.parid=s1.id and s2.element="competence" and s3.parid=s2.id and s3.element="nom" and s4.parid=valeur.id; 4. Faites de même, pour les compétences strictement supérieures à 100. /jeu/competence[.>100]/nom. select v1.val from Valeur v1, Valeur v2, Structure s1,s2,s3 where s1.element="jeu" and s2.parid and s2.element="competence" and s3.parid=s2.id and s3.element="nom" and s4.parid=v1.id and v2.id=s2.id and v2.val>100; 5. Quelle est la relation entre le nombre de jointure SQL et la structure de la requête XPath? Pour une requête de profondeur n avec k conditions, il faut n + k + 2 jointures. 6. Le schéma d encodage Monet associe à chaque chemin possible du document XML une table binaire (identifiant, parent). Traduisez le document précédent selon le schéma Monet. Les chemins sont jeu, jeu/sort, jeu/sort/nom, jeu/sort/validité, jeu/competence, jeu/competence/nom, jeu/competence/experience. 7. Exprimez la requête SQL précédente sur ce nouveau schéma. Quel est l intérêt de cette approche? Le nombre de tables augmente, mais une requête sans condition ne nécéssite qu une jointure, et dans le cas général une jointure par condition. 3 Train Soit le document XML suivant, représentant des informations ferroviaires : la contitution de trains en voitures, la présence éventuelle d une voiture-bar, les réservations effectuées, et les usagers correspondants. <?xml version="1.0" encoding="iso-8859-1"?> <gare> <train numero="t5560" type="tgv"> <voiture numero="v1"> <resa numero="r17" id="u55"/> <resa numero="r18" id="u52"/> </voiture> <voiture numero="v2"/> <voiture numero="v3"/> <voiture numero="v4"> <bar service="froid uniquement"/> </voiture> </train> <train numero="t6731"> <voiture numero="v1"/> <voiture numero="v2"> <resa numero="r15" id="u55"> </voiture> </train> <usager id="u55" nom="jean" prenom="dufour"/> <usager id="u52" nom="brigitte" prenom="lefebvre"/> <usager id="u56" nom="patrick" prenom="subiran"/> 3
</gare> Donnez une expression XPath pour chacune des requêtes suivantes : 1. Le numéro des trains possédant une voiture-bar ; /gare/train[voiture/bar]/@numero. 2. Le nom des usages ayant au moins une réservation ; /gare/usager[/gare/train/voiture/resa/@id=@id]/@nom. 3. Le numéro des trains dont au moins 2 places sont réservées : /gare/train[count(voiture/resa)>1]/@numero. 4. Le nom des personnes ayant reservé exactement deux fois. /usager[count(/gare/train/voiture/resa[@id=current().@id])=2]/@nom 4 XML Soient les deux documents XML de la figure??. XPath 3. Expliquez en quelques phrases la structure d une requête XPath. 4. Expliquez en quelques phrases une façon d évaluer une expression XPath (il n est pas nécessaire de détailler chaque axe). 5. Pour les documents respectant la même DTD que doc2.xml, donnez la requête XPath permettant d extraire le nom de chaque auteur. Cette requête est dénommée R 1 dans la suite. /document/livre/auteur/nom 6. Idem, extraire les numéros de chapitre (quand ils existent). //chapitre/@num 7. Idem, extraire le numéro des auteurs des livres ayant exactement un chapitre. //livre[count(chapitre)=1]/auteur/@num et pas //livre[count(chapitre)=1]//@num Stockage relationnel 9. Donnez une façon systématique de stocker les documents du type de doc2.xml dans une base de données relationnelle (indiquez la ou les tables nécessaires, le schéma de chaque table, et donnez la signification de chaque attribut. Il n est pas nécessaire de traduire le document doc2.xml dans ce format). 10. Précisez les avantages et inconvénients de cette représentation. 11. Traduire la requête XPath R 1 en une requête SQL. Une traduction possible est de respecter le schéma Monet (cf. cours). La requête serait alors : select val from Valeur,T where T.id=Valeur.id; où T est la table associée au chemin /document/livre/auteur/nom. 4
doc1.xml <?xml version= 1.0?> <!DOCTYPE document SYSTEM "doc12.dtd"> <document> <livre> <titre>titre 1</titre> <auteur> <nom>doe</nom> <prenom>john</prenom> </auteur> <chapitre nom= chapitre premier > Ceci est un <b>chapitre</b>. </chapitre> </livre> </document> Figure 1 doc2.xml <?xml version= 1.0?> <!DOCTYPE document SYSTEM "doc12.dtd"> <document> <livre> <titre>titre 1</titre> <titre lang= en >This is the title</titre> <auteur num= a1 > <nom>doe</nom> <prenom>john</prenom> <age>36</age> </auteur> <auteur num= a2 > <nom>onyme</nom> <prenom>anne</prenom> <age>41</age> </auteur> <chapitre> Ceci est un <b>chapitre</b>. </chapitre> </livre> <livre> <titre>titre 2</titre> <auteur> <nom>paki</nom> <prenom>ohncep</prenom> </auteur> <chapitre num= chap1 auth= a1 > premier chapitre </chapitre> <chapitre num= chap2 auth= a1 > second chapitre </chapitre> </livre> </document> 5
5 XQuery Soit les documents suivants, contenus dans le fichier doc/bib.xml, reviews.xml : <?xml version="1.0" encoding="iso-8859-1"?> <bib> <book year="1994"> <title>tcp/ip Illustrated</title> <author><last>stevens</last><first>w.</first></author> <publisher>addison-wesley</publisher> <book year="1992"> <title>advanced Programming in the Unix environment</title> <author><last>stevens</last><first>w.</first></author> <publisher>addison-wesley</publisher> <book year="2000"> <title>data on the Web</title> <author><last>abiteboul</last><first>serge</first></author> <author><last>buneman</last><first>peter</first></author> <author><last>suciu</last><first>dan</first></author> <publisher>morgan Kaufmann Publishers</publisher> <price>39.95</price> <book year="1999"> <title>the Economics of Technology and Content for Digital TV</title> <editor> <last>gerbarg</last><first>darcy</first> <affiliation>citi</affiliation> </editor> <publisher>kluwer Academic Publishers</publisher> <price>129.95</price> </bib> <?xml version="1.0" encoding="iso-8859-1"?> <reviews> <entry> <title>data on the Web</title> <price>34.95</price> <review> A very good discussion of semi-structured database systems and XML. </review> </entry> <entry> <title>advanced Programming in the Unix environment</title> <review> A clear and detailed discussion of UNIX programming. </review> </entry> <entry> <title>tcp/ip Illustrated</title> 6
<review> One of the best books on TCP/IP. </review> </entry> </reviews> <?xml version="1.0" encoding="iso-8859-1"?> <prices> <title>advanced Programming in the Unix environment</title> <source>www.amazon.com</source> <title>advanced Programming in the Unix environment</title> <source>www.bn.com</source> <title>tcp/ip Illustrated</title> <source>www.amazon.com</source> <title>tcp/ip Illustrated</title> <source>www.bn.com</source> <title>data on the Web</title> <source>www.amazon.com</source> <price>34.95</price> <title>data on the Web</title> <source>www.bn.com</source> <price>39.95</price> </prices> <chapter> <title>data Model</title> <section> <title>syntax For Data Model</title> </section> <section> <title>xml</title> <section> <title>basic Syntax</title> </section> <section> <title>xml and Semistructured Data</title> </section> </section> </chapter> 7
Donnez les requêtes correspondant aux expressions suivantes : 1. Créez une liste (plate) de toutes les paires titre-auteur, avec chaque paire contenue dans un element result. <results> (for $b in $bib/bib/book, $t in $b/title, $a in $b/author return <result>$t, $a</result>) </results> 2. Pour chaque livre de la bibliographie, listez son titre et ses auteurs, groupés dans un élément result. <results> (for $b in $bib/bib/book return <result>($b/title), ($b/author)</result>) </results> 3. Pour chaque auteur dans la bibliographie, listez le nom de l auteur et les titres de tous les livres de l auteur, groupés dans un élément result. <results> (let $a := $bib//author for $last in distinct-values($a/last), $first in distinct-values($a[last = $last]/first) order by $last ascending, $first ascending return <result> <author><last>$last</last><first>$first</first></author>, (for $b in $bib/bib/book where some $ba in $b/author satisfies $ba/last = $last and $ba/first = $first return $b/title) </result>) </results> 4. Pour chaque livre trouvé simultanément dans bn.com et amazon.com, listez le titre du livre et ses prix selon chaque source. 8
<books-with-prices> (for $b in $bib/bib//book, $a in $reviews//entry where $b/title = $a/title return <book-with-prices> ($b/title), <price-bstore2>($a/price/text())</price-bstore2>, <price-bstore1>($b/price/text())</price-bstore1> </book-with-prices>) </books-with-prices> 5. Pour chaque livre ayant au moins un auteur, listez son titre et ses deux premiers auteurs, et un élément vide et-al si le livre a d autres auteurs. <bib> (for $b in $bib/bib//book where count($b/author) > 0 return ($b/title), (for $a in $b/author[position() <= 2] return $a), (if (count($b/author) > 2) then <et-al/> else ()) ) </bib> 6. Listez les titres et années des livres publiés par Addison-Wesley après 1991, en ordre alphabétique. <bib> (for $b in $bib/bib//book where $b/publisher = "Addison-Wesley" and $b/@year > 1991 order by $b/title ascending return ($b/@year), ($b/title)) </bib> 7. Listez les livres dans lesquels un élément se termine par or et contient la chaîne Suciu (a n importe quelle profondeur). Pour chacun de ces livres, indiquez son titre et l élément en question. 9
for $b in $bib/bib//book let $e := $b/*[contains(string(.), "Suciu") and ends-with(local-name(.), "or")] where exists($e) return ($b/title), $e 8. Trouvez tous les titres de sections ou chapitres contenant le mot XML, quelle que soit la profondeur. <results> (for $t in $books//(chapter section)/title where contains($t/text(), "XML") return $t) </results> 9. Dans le document prices.xml, trouvez le prix minimal de chaque livre, sous la forme d un élément minprice avec le titre du livre comme valeur d un attribut title. <results> (let $doc := $prices for $t in distinct-values($doc//book/title) let $p := $doc//book[title = $t]/price return <minprice title="$t"><price>min($p)</price></minprice>) </results> 10. Pour chaque livre ayant un auteur, retournez le libre avec son titre et ses auteurs. Pour chaque livre avec un editeur, retournez un element reference avec le titre du livre et l affiliation de l éditeur. <bib> (for $b in $bib/bib//book[author] return ($b/title), ($b/author)), (for $b in $bib/bib//book[editor] return <reference>($b/title), ($b/editor/affiliation)</reference>) </bib> 11. Trouvez les paires de livres qui ont des titres différents mais le même ensemble d auteurs (éventuellement dans un ordre différent). 10
<bib> (for $book1 in $bib/bib//book, $book2 in $bib/bib//book let $aut1 := for $a in $book1/author order by $a/last ascending, $a/first ascending return $a, $aut2 := for $a in $book2/author order by $a/last ascending, $a/first ascending return $a where $book1 << $book2 and not($book1/title = $book2/title) and deep-equal($aut1, $aut2) return <book-pair>($book1/title), ($book2/title)</book-pair>) </bib> 12. Déclarez la fonction auteur, qui, étant donné un titre de libre, retourne tous les auteurs de ce livre. declare function local:author($title as xs:string) as element()* let $c := $bib//book[title = $title] return $c//author ; 11