Title: Chapitre 4 : Manipulation des structures de donnes XML
1Chapitre 4 Manipulation des structures de
données XML
- DOM et SAX vue d'ensemble
2Objectif
- XML peut gérer des structures variables, pouvant
évoluer dynamiquement. - Le traitement de structures de données XML permet
d'extraire ou de traiter une information
pertinente, grâce à la séparation entre la
structure de données et sa sémantique.
3Modèles de manipulation (3 étapes)
- Traitement de l'entrée XML
- "Parsing" et validation du document source
- Reconnaissance/recherche des informations
associées en se basant sur leur localisation ou
leurs balises - Extraction des informations associées localisées
- Optionnel "mapping"/"binding" des informations
trouvées avec les objets métier - Traitement de la logique métier Optionnel
production d'informations de sortie - Traitement de sortie XML
- Construire un modèle de document avec DOM, JDOM
- Appliquer les feuilles de style XSLT ou effectuer
directement la sérialisation en XML
4DOM et SAX
Simple API for XML
Document Object Model
- DOM et SAX sont les modèles de manipulation les
plus courants - DOM
- utilise un modèle objet pour représenter le
document - applique à l'arborescence de nuds du document
une hiérachie d'objets de différents types
Document, Element, Attribute, arbre
hiérarchique - SAX
- "parse" séquentiellement
- quand il reconnaît une construction syntaxique,
il le signale à l'application qui est en train de
l'exécuter
bien pour accès aléatoire
bien pour documents volumineux
5Manipulation des structures de données XML
- DOM Document Object Model
6L'API DOM
- Un parseur DOM prend en entrée un document XML et
construit - un arbre formé d'objets
- chaque objet appartient à une sous-classe de Node
- des opérations sur ces objets permettent de créer
de nouveaux nuds ou de naviguer dans le document
7Structure de l'arbre DOM
- Chaque nud comporte un des composants de la
structure XML - Types de nuds courants (tous sous-types de Node)
- Element, Text, CDATASection, ProcessingInstruction
, Comment, - La racine de l'arbre DOM est un nud spécial, de
type Document - La racine DOM contient un seul objet fils de type
Element qui est la racine du document
8Interfaces de programmation DOM
- DOM spécifie un jeu d'interface de programmation
pour les documents XML et HTML - Conçu pour être utilisé par tout langage de
programmation - Assure la portabilité des programmes écrits en
Java et Javascript sur tous les navigateurs Web. - On peut créer les nuds, les supprimer, changer
leur contenu et traverser les divers nuds de
l'arbre d'une manière hiérarchique. - le modèle objet du document complet est en
mémoire.
9Programmation DOM en java
- Dans l'arbre d'objets, chaque nud est un type
dérivé du type Node. Diverses méthodes de
parcours et de construction de l'arbre sont
définies. - La racine de l'arbre est de type Document
- Accès à la DTD du document
- getDocType
- Méthodes de création des différents types
d'éléments - createAttribute, createAttributeNS,
createCDATASection, createComment,
createDocumentFragment, createElement,
createElementNS, createEntityReference,
createProcessingInstruction, createTextNode. - Récupération du nud racine du document
- getDocumentElement()
- Récupérer des nuds selon leur ID ou le nom de
l'élément - getElementByID, getElementByTagName,
getElementByTagNameNS - Chaque élément est de type Element
- Accès au nom de l'élément
- getTagName
- Méthodes de traitement des attributs
- hasAttribute, getAttribute, setAttribute,
removeAttribute - Accès aux éléments fils par leur nom
- Une liste de nuds de type NodeList
- Récupération de la taille de la liste et accès à
chaque nud
10Programmation DOM en java
- Les attributs sont du type Attr, qui
n'appartiennent pas à l'arbre DOM, mais sont liés
aux éléments - Récupération du nom et de la valeur
- Il existe une interface d'accès à une collection
de nuds d'après un nom unique, c'est le type
NamedNodeMap - Méthodes de lecture, écriture et suppression
- Les autres types de nuds sont
- Entity pour une entité générale
- EntityReference pour une référence à une entité
dans une donnée XML - Processinglnstruction pour représenter les
instructions de traitement.
11Création d'un arbre DOM
- On commence par créer un document (vide) à partir
de rien - DocumentBuilderFactory factory
DocumentBuilderFactory.newInstance() - // récupérer une fabrique de constructeur de Dom
- DocumentBuilder builder factory.newDocumentBuil
der() - // récupérer un constructeur de Dom
- Document document builder.newDocument()
- Si on veut créer l'arbre DOM correspondant à des
données XML, on utilise la - méthode parse.
- exemple construction de l'arbre DOM à partir du
fichier "toto.xml" - Document document builder.parse(new
File("toto.xml")) -
12Création de nuds - ajouts
- Création d'un élément
- Node newNode document.createElement("monNoeud")
- Element root (Element) document.createElement("r
ootElement") -
- Ajout d'un élément dans l'arbre
- document.appendChild(root)
- root.appendChild(document.createTextNode("MonTexte
")) -
-
13Normalisation d'un arbre DOM
- Il peut être utile de normaliser un arbre DOM
après des ajouts multiples pour avoir un arbre
plus équilibré - document.getDocumentElement().normalize()
- // renvoie le nud racine du document
14Exercice
- Ecrire le programme java permettant de
- récupérer l'arbre DOM du fichier biblio.xml
- ajouter un livre en langue anglaise ayant
- un titre "Harry Potter and the half-blood prince"
- un auteur "J.K. Rowlings"
- Attention à respecter la structure de l'arbre DOM
!!
15Navigation dans l'arbre
- Démarrer de linstance de Document
- getDocumentElement() élément racine
- Pour chaque élément
- getName(), getLocalName(), getNamespaceURI() nom
et namespace de lélément - getChildNodes() liste des noeuds fils
- getFirstNode(), getLastNode(), getNextSibling()
navigation - getAttributes() hashtable dattributs
- Pour les attributs
- getName() nom de lattribut
- getValue() valeur de lattribut
- Pour les noeuds texte
- getNodeValue() valeur du noeud texte
16Exemple
- Programme qui
- construit l'arbre DOM d'un document XML
- parcourt récursivement l'arbre et numérote les
nuds de type Text par leur position dans l'arbre
17import java.io.,javax.xml.parsers.,
org.w3c.dom. class Preordre public
static void main (String args) //
Récupération du document File fdom new
File (args0) // Instanciation du
parseur Document BuilderFactory factory
DocumentBuilderFactory.newInstance()
DocumentBuilder builder factory.newDocumentBuild
er() //Analyse du document (création de
l'arbre) Document dom
builder.parse(fdom) //Début du parcours
avec le numéro 1 Node elementRacine
dom.getDocumentElement()
Parcours(elementRacine,1)
18 private static int Parcours (Node nud, int
numero) String str new String()
numero //numérotation du nud s'il est de
type texte if (nud.getNodeType()
Node.TEXT_NODE) str "(" numero
")" nud.getNodeValue()
nud.setNodeValue(str) if
(nud.hasChildNodes()) // si le nud a des
fils, parcours récursif //récupère
la liste des fils du nud courant liste de type
NodeList NodeList fils
nud.getChildNodes() //parcours de la
liste et appel récursif for (int i0 ilt
fils.getLength() i) numero
Parcours(fils.item(i), numero)
return numero
19Manipulation des structures de données XML
- SAX pour parser (analyser) un document XML
20L'interface SAX
- SAX est orientée événement. Lorsque le parseur
SAX atteint un élément spécifié dans le document
XML, il le traite comme un événement et appelle
le code approprié pour cet événement. - Méthodes de rappel pour spécifier qu'un élt a été
trouvé startDocument, endDocument,
startElement, endElement, getEntity, characters - Interfaces les plus courantes et utiles
ContentHandler, DTDHandler - voir package org.xml.sax
21Exemple de décomposition d'un document
- lt?xml version"1.0"?gt
- ltdocgt
- ltsalutationgtBonjour tout le monde !lt/salutationgt
- lt/docgt
- Décomposition
- start document
- start element doc
- start element salutation
- characters Bonjour tout le monde !
- end element salutation
- end element doc
- end document
22Parsing non validant d'un doc XML
- DefaultHandler handler new DefaultHandler()
- // le handler réalise les traitements pendant le
parsing - // ici rien (handler par défaut)
- SAXParserFactory factory SAXParserFactory.newIns
tance() - // une "factory" (configurateur) de parseur
- SAXParser saxParser factory.newSAXParser()
- // obtenir un parseur SAX
- saxParser.parse(new File("toto.xml"), handler)
23Parsing validant d'un doc XML
On redéfinit le handler !
- La classe doit étendre DefaultHandler
- public class monAnalyseur extends DefaultHandler
-
- On crée un nouveau handler par défaut
- DefaultHandler handler new monAnalyseur()
- SAXParserFactory factory SAXParserFactory.newIns
tance() - factory.setValidating(true)
- // la factory produira un parseur validant
- SAXParser saxParser factory.newSAXParser()
- saxParser.parse(new File("toto.xml"), handler )
- Encapsuler dans des try et récupérer les
exceptions
24Traitement
- Définir un traitement à effectuer en cas
d'évènement -
- void startDocument
-
- System.out.println (Début du document")
-
- Ici on fait afficher "Début du document" quand on
est sur la balise de début de document.
25Exemple
- Programme SAX qui affiche le nom des balises
- ouvrantes et fermantes lors de la lecture
- séquentielle dun document XML
- import java.io.
- import org.xml.sax.
- import org.xml.sax.helpers.DefaultHandler
- import javax.xml.parsers.SAXParserFactory
- import javax.xml.parsers.ParserConfigurationExcept
ion - import javax.xml.parsers.SAXParser
26public class Analyse extends DefaultHandler //
plusieurs méthodes de DefaultHandler redéfinies
static private FileWriter dest public static
void main (String argv) throws IOException
if (argv.length ! 2) System.err.println
("Usage Analyse fichierSource fichierCible")
System.exit (1) File fichierDest new
File(argv1) dest new FileWriter(fichierDe
st) DefaultHandler handler new Analyse()
// les "handlers" seront ceux de la classe
Analyse SAXParserFactory factory
SAXParserFactory.newInstance() try
SAXParser saxParser factory.newSAXParser()
saxParser.parse( new File(argv0), handler )
// parser et lancer les traitements du handler
catch (Exception e )
System.err.println(e) System.exit
(2) System.exit (0)
27- public void startDocument ()
- System.out.println("Début Document")
-
- public void endDocument ()
- System.out.println("Fin Document")
-
- void startElement (String name, AttributeList
atts) - System.out.println (Début name)
-
- public void endElement (String name)
- System.out.println (Fin name)
-
28- public void characters (char ch, int start, int
length) - System.out.print("Characters \"")
- for (int i start i lt start length i)
- switch (chi)
- case '\\' System.out.print("\\\\") break
- case '"' System.out.print("\\\"") break
- case '\n' System.out.print("\\n") break
- case '\r' System.out.print("\\r") break
- case '\t' System.out.print("\\t") break
- default System.out.print(chi) break
-
- System.out.print("\"\n")
-
-
- / characters permet de définir le traitement
lorsqu'on est sur le texte d'un - élément (entre les deux balises ouvrante et
fermante) /
29Traitement des attributs
- public void startElement (String namespaceURI,
String simpleName, - String qualifiedName, Attributes attrs) throws
SAXException - String elementName simpleName
- if (elementName.equals(""))
- elementName qualifiedName
- System.out.println("startElement "
elementName) - // le nom de l'élément selon que le namespace est
pris ou non en charge - if (attrs ! null)
- // récuperation des attributs de l'élément -
nombre getLength, valeur getValue, nom
getLocalName ou getQName selon namespace ou pas - for (int i 0 i lt attrs.getLength() i)
- System.out.println("attributs ")
- String attName attrs.getLocalName(i)
- if (attName.equals("")) attName
attrs.getQName(i) - System.out.println(attName"\""attrs.getValue(i
)"\"") nl() -
-
30De XML à HTML avec SAX (1)
- Il suffit à chaque start ou end d'écrire dans le
bon fichier (méthodes "ecrit()" et "nl()" à
coder) les balises d'ouverture ou de fermeture
correspondant et les noms des éléments - public void startDocument ()
- ecrit("lt!doctype html public \"-//W3C//DTD
HTML 3.2 Final//EN\"gt") nl() - ecrit("lthtmlgt") nl()
- ecrit("ltheadgtlt/headgt") nl()
- ecrit("ltbodygt") nl()
-
- public void endDocument ()
- ecrit("lt/bodygt") nl()
- ecrit("lt/htmlgt") nl()
31De XML à HTML avec SAX (2)
- public void startElement (String namespaceURI,
String simpleName, String qualifiedName,
Attributes attrs) - String namesimpleName
- if ( name.equals("livre") )
- ecrit("lth5gt"name"lt/h5gt") nl()
- ecrit("ltpgtltigt")
-
-
- public void endElement (String namespaceURI,
String simpleName, String qualifiedName,
Attributes attrs) -
- String namesimpleName
- if ( name.equals("livre") )
- ecrit("lt/igtlt/pgt")
32Programmer avec XPATH
- XPATH est integré à Java depuis Java 5.0.
- Avant le classique JAXP n'incluait que DOM, SAX
et XSLT - Jaxp 1.3 téléchargeable en séparé
33Fonctionnement de javax.xml.xpath
- On récupère une instance de XPath à partir d'une
fabrique (XPathFactory). - On construit une XPathExpression à partir du
XPath. Cette XPathExpression va retourner (grâce
à sa méthode evaluate()) un Object qui peut
correspondre à un NodeSet, un Node, un String, un
Number ou un Boolean.
34(No Transcript)
35Utiliser XPATH avec DOM
- public static void evaluerDOM(Document document,
String expression, QName retour) -
- try
- //création du XPath
- XPathFactory fabrique XPathFactory.newInst
ance() - XPath xpath fabrique.newXPath()
- //évaluation de l'expression XPath
- XPathExpression exp xpath.compile(expressi
on) - Object resultat exp.evaluate(document,reto
ur) - System.out.println(resultat)
- catch(XPathExpressionException xpee)
xpee.printStackTrace() -
36Utiliser XPATH avec SAX
- public static void evaluerSAX(File fichier,
String expression, QName retour) -
- try
- //création de la source
- InputSource source new InputSource(new
FileInputStream(fichier)) - //création du XPath
- XPathFactory fabrique XPathFactory.newInstan
ce() - XPath xpath fabrique.newXPath()
- //évaluation de l'expression XPath
- XPathExpression exp xpath.compile(expression
) - Object resultat exp.evaluate(source,retour)
- System.out.println(resultat)
- catch(XPathExpressionException xpee)
- xpee.printStackTrace() catch(IOExcepti
on ioe) ioe.printStackTrace() -
37Le main( ) correspondant
- public static void main(String args)
- try
- DocumentBuilderFactory fabrique
DocumentBuilderFactory.newInstance() - DocumentBuilder constructeur
fabrique.newDocumentBuilder() -
- File xml new File("fichier.xml")
- Document document constructeur.parse(xml)
- evaluerDOM(document, "//membre/mail",
XPathConstants.STRING) - catch(Exception e)e.printStackTrace()
-
- try
- File xml new File("fichier.xml")
- evaluerSAX(xml, "//membre_at_pseudo'Ricky81'",
XPathConstants.STRING) - catch(Exception e)e.printStackTrace()
-
38Exemple récupérer un node
- dans la méthode evaluer()
- XPathExpression exp xpath.compile(expression)
- node (Node)exp.evaluate(source,XPathConstants.NO
DE) - return node
- dans le main()
- récupérer le titre du premier article publié sur
le blog de developpez.com (RSS 2.0).
URL url new URL("http//blog.developpez.com/xmls
rv/rss2.php?blog12") String expression
"rss/channel/item/title" Node node
evaluer(url.openStream(),expression) System.out.p
rintln(node.getTextContent())
39Exercice
- Remarque on peut "caster" le résultat d'un
evaluate en booléen, en chaîne de caractères, en
nombre ou en liste de nuds. - Comment faire pour récupérer le nombre de news de
la catégorie 'J2EE' dans l'adresse du site de
l'exemple précédent (on testera
categorytext()'J2EE').
40Exercice correction
- dans la méthode evaluer()
- XPathExpression exp xpath.compile(expression)
- number (Double)exp.evaluate(source,XPathConstan
ts.NUMBER) - return number
- dans le main()
- URL url newURL("http//blog.developpez.com/xmls
rv/rss2.php?blog12") String expression
"count(rss/channel/item/categorytext()'J2EE')"
- Double number evaluer(url.openStream(),expressi
on) - System.out.println("Il y a "number" news J2EE
sur le blog de la rubrique Java")