Exemple 39. Création d’un document XML en DOM
public Document createDocument() { // création du document Document document = DocumentHelper.createDocument() ; // création d'un élément racine, et ajout d'un attribut id de valeur 15 Element root = document.addElement("marins").addAttribute("id", "15") ; // création d'un sous-élément de l'élément racine Element marin1 = root.addElement("marin") ; // création d'un sous-élément "nom" Element nom1 = marin.addElement("nom") ; // ajout du texte "Surcouf" à cet élément nom1.addText("Surcouf") ; // création d'un sous-élément contenant le texte "Robert" // l'appel est chaîné, car addElement retourne une instance de Element Element prenom1 = marin.addElement("prenom").addText("Robert"); return document; }
Document
, que l’on obtient par invocation d’un méthode factory
DocumentHelper.createDocument()
.
Ce document est vide, il ne possède pas d’élément racine. Pour lui en ajouter un, il faut invoquer la méthode
addElement(String)
de cet objet. Un document XML ne pouvant contenir qu’un seul élément racine, cette méthode nous retourne un objet de type
Element
, qui est la racine de ce document XML.
On peut ensuite enrichir cet élément :
Element.addElement(String))
;
Element.addAttribute(String, String)
, prenant en paramètre le nom de l’attribut que l’on souhaite ajouter, et sa valeur.
Element
, ce qui permet de les chaîner, commme nous l'avons fait dans cet exemple.
Exemple 40. Écriture d’un document XML DOM4J dans un fichier
public void serializetoXML(OutputStream out, String encoding) throws Exception { OutputFormat outformat = OutputFormat.createPrettyPrint() ; outformat.setEncoding(aEncodingScheme); XMLWriter writer = new XMLWriter(out, outformat); writer.write(document); writer.flush() ; }
OutputStream
et une chaîne de caractères précisant le type d’encodage du fichier. En général cet encodage sera UTF-8.
La première étape consiste à construire un formateur, de façon à écrire un fichier XML correctement indenté, et lisible facilement à l’œil nu. Ce formateur est adapté à une lecture du fichier par un humain, mais est légèrement plus consommatrice de ressources. Il n'est donc pas adapté à tous les cas. DOM4J nous fournit un tel formateur, que l’on obtient par appel à la méthode factory
OutputFormat.createPrettyPrint()
.
À l’aide de ces deux objets, il est possible de construire un objet de type
XMLWriter
, et d’appeler sa méthode
write(Document)
afin d’écrire le contenu de ce document dans un fichier.
Comme on peut le voir, il est possible, en quelques lignes de code, de créer des documents XML et de les écrire sur des flux de sortie, qui peuvent être des fichiers ou des flux HTTP.
Exemple 41. Lecture d’un fichier XML avec DOM4J
public void parseWithSAX(File file) throws DocumentException { SAXReader xmlReader = new SAXReader() ; Document doc = xmlReader.read(file) ; }
Document
, le même type que nous avons utilisé en création. Nous allons revoir cette interface en détails dans la suite de ce chapitre.
Node
: modélise l'intégralité des types de nœud que l'on peut trouver dans un document XML. Une istance de
Node
peut être enfant d'un élément XML.
Branch
: modélise les types de nœud XML qui peuvent posséder des enfants, à savoir
Document
et
Element
.
Text
,
Attribute
,
Comment
, etc... : modélisent les notions XML correspondantes. Ces interfaces étendent
Node
.
Document
et
Element
: modélisent le document tout entier et les éléments XML respectivement.
Namespace
, qui modélise les espaces de nom, et
QName
, qui modélise les noms complets (
fully qualified name
).
Namespace
. Cette classe permet de modéliser un espace de nom, et elle est utilisée en paramètres de nombreuses méthodes permettant de manipuler les éléments et attributs d’un document XML.
Une instance de cette classe est construite par l’utilisation de l’une des deux méthodes factory :
get(String prefix, String uri)
: retourne l’espace de nom associé à ce préfixe et à cette URI ;
get(String uri)
: retourne l’espace de noms associé à cette URI.
Exemple 42. Création d’un espace de noms en DOM4J
Namespace ns = Namespace.get( "galilee", "http://www.galilee.org/cours-xml") ;
marin
http://www.galilee.org/cours-xml
galilee
.
QName(String)
: prend en paramètre le nom complet sous forme d’une chaîne de caractères ;
QName(String, Namespace)
: prend en paramètre le nom complet et l’espace de nom associé ;
QName(String, Namespace, String)
: prend en paramètre le nom complet, l’espace de nom associé et le nom complet.
get(String)
: prend en paramètre le nom de l’élément ;
get(String, Namespace)
: prend en paramètre le nom et son espace de nom ;
get(String, Namespace, String)
: prend en paramètre le nom, l’espace de nom et le nom complet ;
get(String, String, String)
: prend en paramètres le nom, le préfixe du nom et l’URI de l’espace de nom.
name
: le nom de ce nœud ;
parent
: le parent de ce nœud ;
name
: le document XML dans lequel se trouve ce nœud ;
text
: le contenu textuel de ce nœud ;
parent
ne doit pas être modifiée de l'extérieur de l'élément qui possède ce nœud. Pour détacher un
node
de son parent, il faut utiliser la méthode
detach()
, qui détache le nœud de son parent et du document dans lequel il se trouve.
add(...)
,
addElement(...)
: permettent d'ajouter des enfants ;
remove(...)
: permettent de les retirer ;
nodeCount()
,
indexOf(Node)
,
node(int)
: permettent d'accéder aux nœuds enfant par son numéro d'ordre dans la liste des enfants ;
nodeIterator()
: retourne une instance d'
Iterator
construite sur la liste des enfants de nœud.
Document
est la première interface que l’on utilise en manipulant des documents XML. Elle étend l'interface
Branch
, et propose donc toutes les méthodes de manipulation de ses enfants. Elle propose de plus des méthodes pour paramétrer l’ensemble du document XML :
addProcessingInstruction()
: permet d'ajouter
processing instructions
à ce document ;
xmlEncoding
: propriété qui gère le type d’encodage du document (typiquement UTF-8) ;
docType
,
entityResolver
: gèrent l’éventuelle DTD ou XML Schema auxquels se document adhère, par l’utilisation d’un
EntityResolver
.
setRootElement(String)
et
getRootElement()
, qui permettent d’accéder à l’unique élément racine de ce document.
Element
modélise un élément XML. Elle étend l’interface
Branch
, possédant les méthodes de manipulation des sous-éléments.
Un élément peut appartenir à un espace de noms, peut avoir des attributs, des sous-éléments, et du contenu textuel. Cette interface permet donc de manipuler toutes ces notions, tant en écriture qu’en lecture.
Les méthodes
add(Namespace)
et
getNamespace()
permettent de manipuler l’espace de nom auquel appartient cet élément. Si cet élément possède plusieurs espaces de noms déclarés, on peut accéder aux autres par deux types de méthodes :
additionalNamespaces()
, qui retourne les espaces de noms autres que celui retourné par
getNamespace()
;
declaredNamespaces()
: retourne enfin l’ensemble des espaces de nom déclarés dans cet élément.
add(Attribute)
: permet d’ajouter un attribut construit par ailleurs ;
addAttribute(QName, String)
: permet de créer un attribut à partir de son nom complet et de sa valeur. Cette méthode retourne l’élément auquel cet attribut a été ajouté ;
addAttribute(String, String)
: permet de créer un attribut à partir de son nom et de sa valeur. De même, cette méthode retourne l’élément auquel cet attribut a été ajouté.
attributes()
: retourne une List des attributs de cette élément ;
attributeIterator()
: retourne directement un
Iterator
sur la liste des attributs de cet élément ;
attributeCount()
: retourne le nombre d’attributs de cet élément ;
attribute(int)
,
attribute(String)
et
attribute(QName)
retournent respectivement l’attribut en n-ième position, l’attribut portant le nom ou le
qname
passé en paramètre.
element(String)
,
element(QName)
: retourne le sous-élément dont le nom ou le nom complet est passé en paramètre ;
elements()
,
elements(String)
,
elements(QName)
: retourne une
List
des éléments, éventuellement portant le nom passé en paramètre ;
elementIterator()
,
elementIterator(String)
,
elementIterator(QName)
: retourne un itérateur sur les sous-éléments, éventuellement portant le nom passé en paramètre.
Branch
:
add(Element)
: ajoute l’élément passé en paramètre ;
addElement(QName)
,
addElement(String)
: ajoute un élément défini à partir de son
qname
ou de son nom ;
addElement(String, String)
: ajoute un élément à partir de son nom complet et de l’URI de l’espace de nom associé.
Attribute
modélise un attribut d’un élément XML. De la même façon que pour un élément, on peut accéder au
qname
et à l’espace de nom d’un attribut par les mêmes méthodes.
On peut accéder au nom et à la valeur d’un attribut simplement par les deux méthodes
getName()
et
getValue()
.
Node
NodeList
Element
Attr
CharacterData
Comment
CDATASection
Text
Entity
EntityReference
ProcessingInstruction
Document
DocumentFragment
DocumentType