Accueil > > > XPATH : LE LANGUAGE
XPATH : LE LANGUAGE
Information sur le tutoriel
Note :
10,00 / 10
Description
Présentation du language XPath pour faire des requêtes sur un fichier XML
Tutorial
XPath
| Pré-requis: |
- Connaissance d'XML |
|
- Connaissance de base de System.Xml |
IntroductionIl y a quelques années encore, l'XML (eXtensible Markup Language)
avait une importance assez marginale en informatique. Les fichiers de configurations et autres
structures représentant des données étaient décrites avec des moyens rudimentaires comme
les fichiers INI, par exemple.
Aujourd'hui, l'XML occupe une place prépondérante dans le monde de l'informatique et a
remplacé bon nombre d'autres solutions. XPath est un langage qui permet de récupérer une partie
d'un document XML qui nous intéresse, en faisant une requête sur le document.
Ce tutorial sur XPath va donc montrer comment créer une telle requête pour avoir accès aux
informations voulue. Prenez bien note que le but n'est pas de présenter System.Xml.XPath mais bel
et bien la façon dont ont construit une requête (en donnant beaucoup d'exemples).
Pour finir, sachez qu'XPath est extrêmement complet et qu'il ne s'agit pas non plus de présenter
tous les aspects du langage dans cet article, mais seulement les bases. Le reste pouvant être
approfondis par vous-même selon les besoins.
Avant de commencer
Pour tester nos différentes requêtes, on va avoir besoin d'un fichier XML. J'ai choisi de représenter
une petite partie du réseau CodeS-SourceS, en décrivant la hiérarchie des différents éléments, de
manière assez simple. Voici ce qu'on obtient
<CodeS-SourceS>
<csharpfr code = "1080">
<Sources>
<Source name = "XML, XPath" url = "x.aspx">
<Rating> 8 </Rating>
<Author> Bidou </Author>
<Visit>8 343 </Visit>
<Updates>
<Update Date= "15.02.2005"> Correction
d'un bug </Update>
</Updates>
</Source>
<Source name = "Tuto XNA" url = "y.aspx">
<Rating> 8.5 </Rating>
<Author>Mx </Author>
<Visit> 5241 </Visit>
</Source>
<Source name = "Interop"
url = "z.aspx">
<Rating> 10
</Rating>
<Author> Lutinore </Author>
<Visit> 12541 </Visit>
</Source>
</Sources>
<Tutos>
<Source name = "CrossThreading"
url = "a.aspx">
<Rating>9
</Rating>
<Author>Mx
</Author>
<Visit>15241
</Visit>
<Updates>
<Update Date = "22.05.2006">
Mise en forme </Update>
<Update Date = "23.05.2006">
Re Mise en forme </Update>
<Update Date = "24.05.2006">
Re re Mise en forme ! </Update>
</Updates>
</Source>
</Tutos>
</csharpfr>
<vbfrance code = "10345">
<Sources>
<Source name = "RegEx"
url = "s.aspx">
<Rating> 8.4
</Rating>
<Author>Seb
</Author>
<Visit>8821
</Visit>
<Updates>
<Update Date = "02.02.2004">
Ajout d'une option </Update>
<Update Date = "02.03.2004">
Et le Coq alors !? </Update>
<Update Date = "02.03.2004">
Cocorico ! </Update>
</Updates>
</Source>
<Source name = "Thread"
url = "f.aspx">
<Rating>5
</Rating>
<Author>Mx
</Author>
<Visit>1241
</Visit>
<Updates>
<Update Date="22.05.2006">
Euh, oui ? </Update>
</Updates>
</Source>
</Sources>
<Tutos>
<Source name = "VS 2005"
url = "r.aspx">
<Rating> 9.3
</Rating>
<Author> Coq
</Author>
<Visit> 16321
</Visit>
<Updates>
<Update Date = "17.04.2004">
Ajout commentaire </Update>
</Updates>
</Source>
<Source name = "Codyx"
url = "l.aspx">
<Rating> 8.9
</Rating>
<Author>Nix
</Author>
<Visit>10005
</Visit>
</Source>
</Tutos>
</vbfrance>
</CodeS-SourceS>
Maintenant qu'on a la structure du fichier XML, on peut sans autre le représenter sous forme graphique
pour se rendre compte un peu mieux de la forme de notre fichier. Chaque cercle
avec une lettre représente ici un Node.

Voici une table de relation que l'on peut établir si on part du principe que le noeud courant est H. Les valeurs peuvent
être directement utilisée dans la requête XPath.
| Value |
Node |
| self |
H |
| parent |
B |
| child |
I |
| descendant |
I, J, K, L |
| descendant-or-self |
H, I, J, K, L |
| ancestor |
B, A |
| ancestor-or-self |
H, B, A |
| preceding |
E, D, C, F, G |
| preceding-sibling |
C |
| following |
M, N, O, P, Q, R, S, T, U, V, W, X |
| following-sibling |
- |
Les requêtes
Remarques : tous les exemples qui suivent se réfèrent au fichier XML que j'ai décris plus haut.
Pour faire les différentes requêtes, je vais commencer par créer un XmlDocument. C'est une des façons de faire
une requête sur un fichier.
|
// Load the xml file |
|
XmlDocument xDoc = new XmlDocument(); |
|
xDoc.Load("CS.xml"); |
[Rappel: XmlDocument est une sous-classe de XmlNode]
Afin d'alléger le document, je ne propose que la requête pour les exemples. A chaque fois, il faut
donc appeler les méthodes SelectNodes (liste de Nodes) et/ou SelectSingleNode (un Node) qui appartiennent
au XmlDocument.
|
XmlNode xNode = xDoc.SelectSingleNode(xPathExp); |
|
XmlNodeList xNodes = xDoc.SelectNodes(xPathExp); |
Les requêtes de base, sans utiliser de fonctions
Sélection simple
Pour se rendre sur un Node spécifique, il suffit de spécifier son path, voici deux exemples
|
// Retourne l'arborescence à partir de l'élément Sources de csharpfr |
|
"CodeS-SourceS/csharpfr/Sources" |
|
// Retourne une collection de noeuds représentant chaque source de csharpfr |
|
"CodeS-SourceS/csharpfr/Sources/Source" |
Remarque :
L'élément child est omis pour des questions de simplifications. On peut donc faire la modification
suivante :
|
"child::CodeS-SourceS/child::csharpfr/child::Sources" par |
|
"CodeS-SourceS/csharpfr/Sources" |
Sélection avec booléens et égalités
Les crochets permettent de saisir des expressions (conditions , prédicats).
On s'intéresse à toutes les sources qui ont une note plus grande ou égale à 8.5
|
// Les descendants de CodeS-SourceS avec un élément Source qui a un attribut |
|
// plus grand où égal à 8.5 |
|
// Retourne 5 noeuds (les 5 sources ayant la note qui répond au critère) |
|
"CodeS-SourceS/descendant::Source[Rating>=8.5]" |
L'étoile permets de remplacer n'importe quel élément, dans ce cas on obtient pas le même résultat que le précédent
car on cherche uniquement dans les sources, et pas les tutoriaux
|
// Recherche sur tous les sites les Sources (pas les Tutos) qui ont
une source avec |
|
// une note plus grande ou égal à 8.5 |
|
"CodeS-SourceS/*/Sources/Source[Rating>=8.5]" |
On peut combiner des critères avec les opérateurs and et or
|
// Note plus grande que 8 et visite plus grande que 10'000 |
|
"CodeS-SourceS/descendant::Source[Rating>8 and Visit>10000]" |
Cela fonctionne également sur les strings (toutes les sources de Mx)
|
// Les sources de l'auteurs s'appelant Mx |
|
"CodeS-SourceS/descendant::Source[Author='Mx']" |
Ou toutes les sources qui ne sont pas de Bidou
|
// Les sources n'appartenant pas à Bidou |
|
"CodeS-SourceS/descendant::Source[Author!='Bidou']" |
Not peut également être utilisé (toutes les sources qui n'ont pas de note inférieure à six)
|
// Les sources avec une note plus grande ou égal à 6 |
|
"CodeS-SourceS/descendant::Source[not(Rating<6)]" |
Si on s'intéresse aux auteurs distinct, on peut faire quelque chose comme ceci
|
// Tous les auteurs de source (sans doublon) |
|
"//Source[not(Author = preceding::Source/Author)]/Author" |
Vérifie si le Rating courant est plus grand que le rating qui le précède. Dans ce cas, les noeuds suivant nous sont retournés : F, G, I, O, V, X
|
// Rien de très intéressant dans notre exemple: vérifie si le node courant |
|
// est plus grand que celui qui le précède |
|
"//Source[(Rating>preceding::Rating)]" |
Accéder aux Attributs
Les sources avec l'attribut url qui vaut "x.aspx"
|
// Les sources qui ont une url qui vaut x.aspx |
|
"CodeS-SourceS/descendant-or-self::Source[attribute::url='x.aspx']" |
Remarque :
L'élément descendant-or-self est remplacé par // et attribute par @ des questions de simplifications. On peut donc faire la
modification suivante :
|
"CodeS-SourceS/descendant-or-self::Source[attribute::url='x.aspx']" par |
|
"CodeS-SourceS//Source[@url='x.aspx']" |
Expression numérique
Retourne les sites qui ont un nombre de code étant un multiple de 4
|
// Les sites ayant un nombre de
code source étant multiple de quatre |
|
"CodeS-SourceS/*[(@code mod 4) = 0]" |
Les requêtes avec quelques fonctions
En fait, XPath peut aller encore beaucoup plus loin : il contient des fonctions au seins
de son langage. On peut donc faire des sommes et autres manipulations très
pratiques. Dans le cas d'une somme par exemple, il est clair que l'ont doit plus
retourner un set de Nodes comme on le faisait auparavant, mais juste une valeur
numérique.
Il faut donc utiliser un autre objet, le XPathNavigator, qui contient une méthode
d'évaluation. Voici comment on le construit:
|
XPathDocument xPathDoc = new XPathDocument("CS.xml"); |
|
XPathNavigator xPathNav = xPathDoc.CreateNavigator(); |
Comme avant, afin d'alléger le document, je ne propose que la requête pour les
exemples. A chaque fois, il faut donc appeler la méthode Evaluate.
|
object o = xPathNav.Evaluate(xPathExp); |
Sum et Count
Ici, on aimerait trouver le nombre de code disponible sur CodeS-SourceS
|
// Le nombre de code disponible en tout. @ représente toujours un attribut |
|
"sum(CodeS-SourceS/*/@code)" |
On peut aussi très facilement avoir le nombre de site sur CodeS-SourceS
|
// Il s'agit dans notre exemple de vbfrance et csharpfr |
|
"count(CodeS-SourceS/*)" |
Et donc, la moyenne des code par site
|
// On effectue la division (expression numérique) |
|
"sum(CodeS-SourceS/*/@code) div count(CodeS-SourceS/*)" |
Pas mal, non?
Sans XPath en tout cas, il faut pas mal plus de code pour faire la même
fonction. Un grand gain de temps donc, si on sait manipuler la chose.
XPath propose plein d'autres fonctions mais le but n'est pas de toutes les présenter. Sachez simplement qu'on peut effectuer
des opérations sur des strings (substring par exemple), des entiers, etc. Mieux vaut lire la doc et chercher la fonction dont on a besoin sur le
coup, plutôt que de les apprendre toutes par coeur! ;-)
Comparaison
But de l'exercice:
Créer une fonction, une fois avec XPath et une fois sans, qui retourne les
auteurs de codes ayant posté une source avec au moins deux mises à jour dont la
dernière en 2005 ou après ainsi qu'un minimum de 10'000 visites ou une note
plus grande ou égal à 9.
Solution XPath:
|
XPathDocument xPathDoc = new XPathDocument("CS.xml"); |
|
XPathNavigator xPathNav = xPathDoc.CreateNavigator(); |
|
string visitsOrRating = "((Visit>10000) or (Rating>=9))"; |
|
string lastUpdate = "(*/Update[last()][(substring(@Date, 7) > 2004)])"; |
|
string nbUpdate = "(count(*/Update) > 1)"; |
|
string xPathExp = string.Format("//Source[{0}
and {1} and {2}]/Author", visitsOrRating, lastUpdate, nbUpdate); |
| |
// L'appel de compile permet de compiler l'expression
ce qui permet une exécution (beaucoup) plus rapide |
|
XPathNodeIterator authors = xPathNav.Select(xPathNav.Compile(xPathExp)); |
Solution « Standard »:
XmlDocument xDoc = new XmlDocument();
xDoc.Load("CS.xml");
List<string>
result = new List<string>();
foreach (XmlElement
xElementSite in xDoc.DocumentElement)
{
foreach
(XmlNode xNodeSources in xElementSite.ChildNodes)
{
foreach (XmlNode
xNodeSource in xNodeSources.ChildNodes)
{
int
visit = 0;
Int32.TryParse(xNodeSource["Visit"].InnerText,
out visit);
double
rating = 0;
Double.TryParse(xNodeSource["Rating"].InnerText,
out rating);
if
(visit > 10000 || rating >= 9)
{
XmlElement updates =
xNodeSource["Updates"];
if
(updates != null && updates.ChildNodes.Count > 1)
{
string yearStr = updates.LastChild.Attributes["Date"].Value;
int year = 0;
Int32.TryParse(yearStr.Split('.')[2],
out year);
if (year > 2004) result.Add(xNodeSource["Author"].InnerText);
}
}
}
}
}
Résultat et Conclusion
La StopWatch pour mesurer le temps est enclenchée juste avant le Select pour le premier cas, et juste avant le
premier foreach pour le second. Les chiffres dans le tableau plus bas sont une moyenne de plusieurs testes, ils
représentent le nombre de Ticks écoulés.
| File size - nb de match |
Xpath |
Standard |
Coef |
| 3Ko - 1 |
42'408 |
76'488 |
1.8 |
| 157Ko - 1 |
46'864 |
3'667'252 |
78 |
| 242Ko - 90 |
47'796 |
5'257'592 |
110 |
| 425Ko - 90 |
46'964 |
9'356'804 |
203 |
| 6170Ko - 15'228 |
50'988 |
134'623'548 |
2640 ! |
XPath est un langage à part entière tout comme les expressions régulières. La différence étant que la technologie XML est utilisée
presque partout: apprendre comment manipuler les expressions régulières est certainement fort utile, mais dans la pratique on ne
l'utilisera qu'assez rarement.
Apprendre XPath est un très bon investissement qui sera très vite rentabilisé: non seulement le nombre de ligne de codes est moindre, mais en plus les temps de
réponses sont sans appels.
Article XPath sur mon blog
Historique
- 20 octobre 2006 09:29:54 :
- Mise en page
- 20 octobre 2006 09:42:43 :
- Re mise en page
- 20 octobre 2006 09:56:24 :
- Ajout de la couleur dans le code
- 20 octobre 2006 13:06:30 :
- Mise en page de la partie XML
- 20 octobre 2006 13:49:04 :
- Mise en forme du document
- 22 octobre 2006 13:20:25 :
- Mise en page
- 22 octobre 2006 21:30:53 :
- Mise en page(hé oui, encore...)
- 22 octobre 2006 22:05:54 :
- Test
Commentaires
|
Derniers Blogs
[SHAREPOINT] LES SESSIONS TECHDAYS 2012.[SHAREPOINT] LES SESSIONS TECHDAYS 2012. par Patrick Guimonet
Voici donc pour ceux qui n'ont pas pu venir, ou ceux qui n'ont pas pu toutes les suivre la liste des sessions SharePoint aux TechDays 2012, que je mettrais à jour dès que les liens des vidéo seront disponibles. Ou ici : http...
Cliquez pour lire la suite de l'article par Patrick Guimonet TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3TECHDAYS PARIS 2012 : SESSION PLEINIèRE JOUR 3 par ROMELARD Fabrice
Speaker: Bernard Ourghanlian Cette session est comme chaque jour transmise en live par BrainSonic, et j'ai donc suivi cette troisième pleinière par ce moyen sur mon iPad . Elle est dédiée comme chaque année à la mise en perspective de l'é...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE !MISHRA READER : UN LECTEUR RSS TRèS ZUNE STYLE EN OPEN SOURCE ! par Vko
Hier durant une session dédiée aux Techdays 2012, j'ai eu le plaisir d'annoncer la sortie de la Béta 2 de Mishra Reader. C'est quoi ? Pour les utilisateurs, c'est une vraie expérience de lecture de flux RSS sur Windows. Rien à voir avec les produit...
Cliquez pour lire la suite de l'article par Vko [FRAMEWORK 4] LES TASKS ET LE THREAD UI[FRAMEWORK 4] LES TASKS ET LE THREAD UI par fathi
Je viens de passer quelques temps au TechDay's et j'ai pu voir pas mal de session intéressante. Par contre une chose m'a un peu étonné lors de certaines de ces sessions qui abordaient les améliorations du framework .NET (donc le 4.5) : en gros, bea...
Cliquez pour lire la suite de l'article par fathi WORKFLOW FOUNDATION 3 A UN PIED DANS LA TOMBEWORKFLOW FOUNDATION 3 A UN PIED DANS LA TOMBE par JeremyJeanson
Depuis déjà un an, je conseille vivement les utilisateurs de Workflow Foundation 3 à migrer vers la version 4. L'information qui va suivre ne devrait donc pas trop prendre au dépourvu les personnes qui m'ont suivi. Je profite de ce poste, pour faire le re...
Cliquez pour lire la suite de l'article par JeremyJeanson
Logiciels
Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System Easy-Planning (1.0.0.1)EASY-PLANNING (1.0.0.1)Basé sur les mêmes principes que MyPlanning, Easy-Planning permet de créer des plannings sous la ... Cliquez pour télécharger Easy-Planning COLLECTOR PLUS (3.00B)COLLECTOR PLUS (3.00B)COLLECTOR PLUS version 3.00B est un logiciel utilisant une base de données alimentée par :
- L... Cliquez pour télécharger COLLECTOR PLUS PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V7.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO LettresFaciles 2011 (8.0.0.1)LETTRESFACILES 2011 (8.0.0.1)LettresFaciles est un logiciel facilitant la création et la rédaction de lettres types.
Son inte... Cliquez pour télécharger LettresFaciles 2011
|