XML - DTD - XPath

Présentation

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

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

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]

Author: Emmanuel Coquery

Created: 2014-04-04 Fri 10:57

Emacs 24.3.50.2 (Org mode 8.2.5h)

Validate