begin process at 2008 05 16 21:48:54
1 173 770 membres
577 nouveaux aujourd'hui
13 973 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

XPATH : LE LANGUAGE


Information sur le tutorial

Catégorie :Tutoriaux Tutorial .NET ( DotNet ) Date de création : 20/10/2006 09:19:28 Vu : 7 803 fois

Note :
10 / 10 - par 7 personnes
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (10)
Ajouter un commentaire et/ou une note


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


Introduction

Il 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.

XPathSmall.JPG


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

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
  • signaler à un administrateur
    Commentaire de MorpionMx le 21/10/2006 13:17:36 administrateur CS

    Très très bon tutorial !

  • signaler à un administrateur
    Commentaire de Bidou le 21/10/2006 17:30:17 administrateur CS

    Oui mais la mise en page c'est pas encore ça...
    Quelle galère !

    Merci pour la note ;-)

  • signaler à un administrateur
    Commentaire de Nurgle le 22/10/2006 10:22:27 administrateur CS

    Excellent tutorial !
    Moi qui manipulait toujours les XML "à la main" (sans XPath), j'ai raté beaucoup de choses... :o)

    10/10

  • signaler à un administrateur
    Commentaire de MorpionMx le 24/10/2006 10:05:54 administrateur CS

    C'est dur hein, la mise en page des tutos ... :D

  • signaler à un administrateur
    Commentaire de iow4 le 29/10/2006 01:18:45

    Good job 10/10

  • signaler à un administrateur
    Commentaire de MorpionMx le 03/11/2006 09:17:13 administrateur CS

    Tuto dans la newsletter MSDN, bravo ;)

  • signaler à un administrateur
    Commentaire de Bidou le 06/11/2006 11:56:24 administrateur CS

    Tiens oui, merci de l'avoir signalé car je ne l'aurais même pas remarqué !
    :-)

  • signaler à un administrateur
    Commentaire de jimmy69 le 24/12/2006 17:57:57

    salut salut,

    Genial ce tuto tout ce qu'il me fallait pour terminer cette annee en beaute !

    Merci et bonnes fetes de fin d'annee
    Christophe
    Un bouillonnais

  • signaler à un administrateur
    Commentaire de coq le 18/05/2007 09:12:08 administrateur CS

    Au fait, pour ceux qui veulent approfondir un peu le sujet, pensez à passer par des requêtes paramétrées :-) : http://blogs.codes-sources.com/coq/archive/2007/03/18/xpath-utilisez-des-requ-tes-param-tr-es.aspx

  • signaler à un administrateur
    Commentaire de taupe4 le 30/12/2007 02:15:39

    Excellent tuto! 10/10 !

    Par contre, j'aimerais signifier que le mot signifiant «1.Faculté propre à l'homme d'exprimer et de communiquer sa pensée au moyen de signes vocaux ou graphiques; ce système. 2. Système structuré de signes non verbaux remplissant une fonction de communication. Ex:langage gestuel. 3. Manière de parler propre à un groupe social ou professionnel, à une discipline, etc. Ex:le langage administratif. 4. Ensemble des procédés utilisés par un artiste dans l'expression de ses sentiments et de sa conception du monde. Ex:le langage de la peinture. 5. Mode d'expression propre à un sentiment, à une attitude. Ex:le langage de la raison. 6. INFORM. Ensemble de caractères, de symboles et de règles utilisé pour donner des instructions à un ordinateur. <> Langage machine: langage directement exécutable par l'unité centrale d'un ordinateur, dans lequel les instructions sont exprimées en code binaire.» (Larousse 2005, page 621) est langage (n.m.) et non language (qui est la traduction anglaise.

Ajouter un commentaire

Appels d'offres

Pub



CalendriCode

Mai 2008
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Boutique

Boutique de goodies CodeS-SourceS