XML - DTD - XPath
PrésentationXML
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'ivoire du Magohamoth</titre> </tome> <tome numero="2"> <dessinateur>Tarquin</dessinateur> <titre>Thanos l'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éfautprefixe: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éfixepref
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
- DTD: Document Type Definition
- 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'enfantANY
: 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
ouIDREFS
- (
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
- expression XPath + noeud de départ
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-test
↔ un-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:
- le premier tome de la collection dans chaque série
- l'ensemble des titres d'album (sans la balise titre)
- les séries dont on connaît l'éditeur
- les séries dont on possède le tome numéro 1
- 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]