XML - DTD - XPath

Emmanuel Coquery

emmanuel.coquery@univ-lyon1.fr

XML


eXtensible Markup Language


  • Standard du W3C
  • Objectif: stocker des données sous forme de texte
  • Modèle de données: arbre (graphe)

Un ensemble de technologies



Schemas


Interrogation


APIs

Schemas



DTD



XML Schema



RelaxNG

Interrogation



Désignation de parties de documents:
XPath



Transformation de documents
XSLT



Bases de données dédiées XML
XQuery



Programmation




DOM: Document Object Model
parcours, modification



SAX, StAX (Java)
parsing, traitement en flux

Modèle de données: arbre

\(\neq\) type de noeuds:

racine (document)
possède exactement 1 enfant de type élément
cet élément va contenir les données

élément

attribut

texte

commentaire

commandes (processing instructions)

Syntaxe

A base de balises, comme HTML

Déclarations

Prologue (optionnel): infos pour la lecture du document

<?xml version="1.0" encoding="utf-8"?>

Déclaration de DTD (optionnel): forme du document

<!DOCTYPE element-principal spec-DTD[ ... déclarations ...]>

Structure

Eléments et attributs:

<nom att1="val1" att2='val2'> Enfants </nom>

ou

<nom att1="val1" att2='val2'/>

L'ordre entre les enfants (éléments, texte) est significatif

L'ordre entre les attributs n'est pas significatif

Exemple - Texte

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE collection SYSTEM "collecbd.dtd">
<collection>
  <serie nom="Lanfeust de Troy">
    <tome numero="1">
      <scenariste>Arleston</scenariste>
      <dessinateur>Tarquin</dessinateur>
      <titre>L&apos;ivoire du Magohamoth</titre>
    </tome>
    <tome numero="2">
      <dessinateur>Tarquin</dessinateur>
      <titre>Thanos l&apos;incongru</titre>
    </tome>
    <editeur nom="Soleil"/>
  </serie>
</collection>

Exemple - Arbre

collection

Espaces de nommage

  • Ambiguïté sur les noms XML
    • Problème similaire aux modules/packages en programmation
  • Nom qualifié = Espace de nommage + nom local
  • Espace de nommage: une URI
  • Nom local: plus ou moins un identifiant dans un langage de programmation
    ([A-Z]|"\_"|[a-z]|...)([A-Z]|"\_"|[a-z]|"-"|"."|[0-9]|...)*
    
  • Syntaxiquement:
    • nomLocal
      utilise un espace de nommage par défaut
    • prefixe:nomLocal
      l'espace de nommage est celui rattaché à prefixe

Déclarations

  • Via des attributs spéciaux
    • valeur de l'attribut = espace de nommage concerné
  • Portée: élément contenant l'attribut spécial et tous ses descendants
  • Attribut xmlns
    définit l'espace de nommage par défaut pour les éléments
  • Attribut xmlns:pref
    attache un espace de nommage au préfixe pref

Exemple

<?xml version="1.0" encoding="utf-8"?>
<livres xmlns="http://www.livres-pas-chers.com">
  <livre xmlns:encyclo="http://toutsurleslivres.org"
         ISBN="123456">
    <auteur encyclo:nat="Américain">Stephen King</auteur>
    <titre>Le fléau</titre>
    <annee>2003</annee>
    <encyclo:annee>1978</encyclo:annee>
    <prix>5.3</prix>
  </livre>
</livres>

Espaces de nommage: http://www.livres-pas-chers.com http://toutsurleslivres.org aucun.

Schemas

  • Relationnel: Ensemble de contraintes que doit vérifier une instance d'une BD
    • Attributs des tuples d'une relation
    • Contraintes de type
    • Contraintes de clé
  • XML: Ensemble de contraintes structurelles que doit vérifier un document XML
    • Attributs/Enfants autorisés/requis dans un éléments
    • Type des valeurs pour les attributs et le texte

\(\Rightarrow\) DTD, XML Schema

Langages de schema pour XML

  • Les plus connus:
    • DTD: Document Type Definition
      • Pas de gestion des espaces de nommage
    • XML Schema
      • Syntaxe XML qui peut prêter à confusion
    • Relax NG
  • Certains schemas sont publics
    • Ex: XHTML, SVG, SOAP, MathML, OpenDocument, OpenXML, …

DTD: Éléments

<!ELEMENT nom contenu >

  • Décrit les suites d'enfants possibles pour un élément.
  • contenu peut être:
    • EMPTY: pas d'enfant
    • ANY: contenu arbitraire
    • (#PCDATA|nom_1|nom_2|...): mélange de texte d'éléments
  • ( expr ): expression rationnelle de nom d'éléments
  •  

    expr ::= expr1, expr2
        expr *
        expr ?
        expr +
        expr1 | expr2
        nom
        (expr)

    DTD: Attributs

    <!ATTLIST nom dec1 dec2 >

    • Décrit les attributs possibles pour un élément
    • dec peut être:
      • nom type "valeur"
      • nom type #REQUIRED
      • nom type #IMPLIED
    • type peut être:
      • CDATA, ID, IDREF ou IDREFS
      • (val1 | val2 | …)

    Exemple

    <!ELEMENT collection (serie*)>
    <!ELEMENT serie (tome+,editeur?)>
    <!ATTLIST serie nom CDATA #REQUIRED>
    <!ELEMENT tome (scenariste?,dessinateur?,titre)>
    <!ATTLIST tome numero CDATA #REQUIRED>
    <!ELEMENT scenariste (#PCDATA)>
    <!ELEMENT dessinateur (#PCDATA)>
    <!ELEMENT titre (#PCDATA)>
    <!ELEMENT editeur EMPTY>
    <!ATTLIST editeur nom CDATA #REQUIRED 
                      adresse CDATA #IMPLIED>
    

    Exemple DTD

    Collection

    XPath

    • Objectif: sélection de morceaux de documents XML
    • Utilisé dans d'autre langages
      • XQuery, XSLT, XPointer, WS-BPEL
      • Utilisable via des bibliothèques Java, Python, C, …
    • Principe: spécification de chemins dans l'arbre menant aux morceaux intéressants
      • expression XPath + noeud de départ
        \(\rightarrow\) ensemble de chemins dans l'arbre XML
        \(\rightarrow\) ensemble de noeuds sélectionnés

    Exemple

    "Aller sur un élément tome, puis sur un élément dessinateur"
    Evaluer à partir du 1er élément serie

    Valeurs

    Types de valeur possible:

    • suite de noeuds
    • chaînes de caractères
      • conversion depuis un élément: concaténation de tous les noeuds texte descendants de l'élément
      • conversion depuis un attribut: valeur de l'attribut
      • conversion depuis une suite de noeud: concaténation
    • nombres, dates, etc
      • conversion possible depuis une chaîne de caractères
    • booléens
      • conversion implicite plus complexe (c.f. prédicats XPath)

    Expressions de chemin

    • Suite d'étapes séparée par /
    • un / en début d'expression: départ forcé depuis la racine (document)
    • Une étape est de la forme axe::test[predicat]
      • [predicat] est optionnel
    • Pour chaque étape, pour chaque noeud \(n\) d'ensemble \(N_d\) de noeuds de départs:
      • Calculer \(N_n^a\) obtenu en suivant l'axe à partir de \(n\)
      • Calculer \(N_n^t\) en filtrant \(N_n^a\) via le test
      • Calculer \(N_n^p\) en filtrant \(N_n^t\) via le predicat
    • Résultat de l'évaluation de l'étape: \(\bigcup_{n\in N_d}N_n^p\)

    Axes

    forward backward
    child parent
    descendant ancestor
    attribute  
    self  
    descendant-or-self ancestor-or-self
    following-sibling preceding-sibling
    following preceding

    Tests & Prédicats

    Tests

    element() element(nom)
    attribute() attribute(nom)
    * nom
    text()  
    comment()  
    processing-instruction()  
    node()  

    Prédicats: expressions booléennes

    Expressions booléennes

    Expressions classiques:

    • and, or, not(...)
    • fonctions renvoyant un booléen

    Plus des conversions implicites

    Abréviations

    child::un-testun-test

    attribute::un-test@un-test

    xxx/descendant-or-self::node()/yyy
    xxx//yyy

    parent::node()/xxx../xxx

    axe::test[pr_1 and pr_2]axe::test[pr_1][pr_2]

    Conversions implicites dans les prédicats

    • Position
    • Existence
    • Valeurs dans des expressions

    Position

    Fonction pos()

    • renvoie la position du noeud
    • parmi les candidats
    • en avançant si l'axe est forward
    • en reculant si l'axe est backward


    Entier \(n\) \(\rightarrow\) booléen

    pos() = n



    serie/tome[3]
    child::element(serie)/child::element(tome)[pos() = 3]
    

    "Le troisième enfant tome pour chaque enfant serie"

    Chemin comme booléen

    Rappel

    expression + point de départ \(\rightarrow\) ensemble de noeuds


    Test

    • Evaluation d'une expression
    • A partir du noeud à tester

    \(\rightarrow \quad \neq \emptyset\) ?


    serie/tome[dessinateur]
    child::element(serie)/child::element(tome)[child::dessinateur]
    

    "Les enfants tome contenant un enfant dessinateur pour chaque enfant serie"

    Chemins comme arguments d'une fonction

    Généralisation de la construction précédente


    Intuitivement

    "Existe-il pour chaque chemin un noeud qui rende l'expression vraie ?"


    serie[tome/@numero >= 3]
    child::element(serie)[child::element(tome)/attribute::attribute(numero) >= 3]
    

    "Les enfants serie tels qu'il existe un attribut numero dans un enfant tome de cette serie dont la valeur est supérieure ou égale à 3"

    Plus formellement

    Fonction \(eval(noeud~n, chemin~c)\)

    \(\rightarrow\) ensemble des noeuds accessibles
    en suivant \(c\) à partir de \(n\)


    Remplacer chaque chemin \(c_i\) dans l'expression \(e\) par une variable \(x_i\) \(\rightarrow\) on obtient \(e'\)

    Ajouter \(\exists x_i, x_i \in eval(n,c_i)\) devant \(e'\) pour chaque \(c_i\)


    [tome/dessinateur = /tome/scenariste]

    devient

    \(\exists x_1, x_1 \in eval(n,\) tome/dessinateur \(),\)
    \(\exists x_2, x_2\in eval(n,\) tome/scenariste \(),\)
    \(x_1 = x_2\)

    Exercice

    Revoir la DTD collection.

    Donner une expression XPath pour obtenir:

    1. le premier tome de la collection dans chaque série
    2. l'ensemble des titres d'album (sans la balise titre)
    3. les séries dont on connaît l'éditeur
    4. les séries dont on possède le tome numéro 1
    5. le titre des albums dont
      le numéro est plus grand ou égal à 3

    Expressions avancées: parenthèses

    • Parenthèses
    • La partie axe::test peut être remplacée par une expression entre parenthèses
      • on peut appliquer un prédicat sur le résultat
      • important pour les prédicats type nième
    • Exemple: le troisième tome de la collection:
      /collection/(serie/tome)[3]

    Expressions avancées: fonctions

    Fonctions prenant et ou renvoyant des ensembles de noeuds

    • L'appel à la fonction est:
      • utilisé dans un prédicat
      • le point de départ d'un expression de chemin
        • remplace la première étape
        • voir l'expression complète
    • Exemple: Les séries également présentes dans
      collection2.xml:
    //serie[@nom=document('collection2.xml')//serie/@nom]
    

    XQuery

    • Langage de requête pour les documents XML
      • Utilisé en particulier dans les BD XML
    • Fabrique des (morceaux de) documents XML à partir de documents XML
    • Une expression XPath est une expression XQuery
    • Permet de construire des morceaux de document: syntaxe XML + expressions XQuery entre accolades

    Exemple

    <personnes>
      <scenaristes>
        {//scenariste}
      </scenaristes>
      <dessinateurs>
        {//dessinateur}
      </dessinateurs>
    </personnes>
    

    FLWOR

    for $v1 in e1, $v2 in e2, ...
    let $w1 := e1', $w2 := e2', ...
    where condition
    order by eo1, eo2, ...
    return expr
    
    • $vi, $wi: variables
      • ei, ei': expressions XPath (ou même XQuery)
    • eoi: expression XPath, suivie de ascending ou descending
    • expr: expression XQuery (en général avec des constructions XML)

    FLWOR: Evaluation

    • Evaluer les combinaisons de valeurs possibles pour les $vi
      • On obtient un ensemble de tuples de valeurs
    • Pour chaque tuple:
      • Evaluer les $wj
        • Si plusieurs valeurs pour une variable: elles sont concaténées
        • Les valeurs sont associées au tuple
    • Filtrer les tuples avec la condition
    • Pour chaque tuple, pris dans l'ordre de la clause order by, évaluer expr
      • Le résultat du FLWOR est la concaténation des résultats ainsi obtenus

    Exemple

    for $to in //tome
    let $ti := $to/titre
    where $to/@numero >= 3
    order by $ti descending
    return
      <album>
        {$to/@numero}
        {$ti}
        <serie>{$to/../@nom}</serie>
      </album>
    

    Déclarations

    Précède l'expression (i.e. mettre au début du programme)

    declare namespace nomprefixe="uri_espace_nommage";
    
    declare default element namespace "uri_espace_nommage";
    
    declare function nomQualifie ($arg1 as type1, $arg2 as type2, ...) 
                                 as type_retour
      { corps de la fonction };
    
    declare default function namespace "uri_espace_nommage";