Hé, vous le scripteur !La chasse au voitures... et le XML

Les scripteurs Microsoft

Télécharger le code de cet article: HeyScriptingGuy2007_02,exe (150KB)

« JE NE SAIS PAS pourquoi mon chien court après les voitures, » dit la vieille blague. « Après tout, qu'en ferait-il s'il finissait par en rattraper une » ?

Bonne question, à laquelle les scripteurs n'ont pas réponse. Enfin, sauf s'il s'agit de Lucy, la chienne de notre rue, qui rattrape les voitures. Nous ne doutons pas le moins du monde qu'elle serait parfaitement capable de cambrioler un marchand de vin et d'utiliser ensuite la voiture pour s'enfuir. Et vu l'état du gazon, nous sommes convaincu qu'elle ne s'arrêterait pas aux aires de repos en cours de route, si vous voyez ce que nous voulons dire.

Si nous devions mettre à jour cette vieille blague pour l'ère ultratechnologique actuelle, elle pourrait ressembler à ce qui suit : « Je ne sais pas pourquoi que mon administrateur système continue d'essayer à apprendre le XML. Après tout, qu'en ferait-elle s'elle finissait par l'apprendre » ?

Remarque : pour notre défense, nous avons seulement dit que nous allions mettre à jour cette vieille plaisanterie fatiguée, nous n'avons jamais dit que nous la rendrions drôle.

Pour être honnête, on fait peut-être un peu trop de battage autour de la technologie XML, du moins pour ce qui est de l'administration système. La vérité est que beaucoup d'administrateurs système ont mené une vie longue et heureuse sans jamais écrire de script entrant en interaction avec un fichier XML, et nous ne nous attendons pas à ce que cela change dans un avenir proche.

Ceci dit, il est également vrai que de plus en plus d'applications adoptent le XML comme norme pour le stockage de données. Et pourquoi pas ? Ces fichiers de données XML, qui ne sont rien de plus que des fichiers texte en plus raffiné, sont faciles et rapides à créer, sont transférables d'une plate-forme à une autre, et ne nécessitent aucun programme de base de données complexe (et coûteux). Vous possédez un système d'exploitation et un éditeur de texte ? Alors vous pouvez créer une base de données XML.

Ce qui veut dire, bien sûr, qu'il y a au moins une chose qu'un administrateur système peut faire avec XML : écrire des scripts qui interrogent un fichier XML comme s'il s'agissait d'une véritable base de données. Et qui mieux que les Scripteurs pour vous donner quelques astuces pour cela ?

Très bien, d'accord. Mais nous sommes convaincus que Lucy est probablement bien trop occupée à déterrer un parterre de fleurs pour écrire une chronique sur le XML.

Pour commencer, jetons un coup d'œil sur un fichier XML simple (voir la figure 1) : il s'agit d'un fichier de base de données présentant quatre scripts trouvés dans la chronique quotidienne Hé, vous le Scripteur !

Figure 1 Hé, vous le Scripteur ! Les scripts dans XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<Repository>
  <Script>
    <Category>Microsoft Office</Category>
    <Subcategory>Microsoft Access</Subcategory>
    <Keyword>databases</Keyword>
    <Title>How Can I Print a Microsoft Access Report?</Title>
    <URL>https://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1020.mspx</URL>
  </Script>
  <Script>
    <Category>Microsoft Office</Category>
    <Subcategory>Microsoft Access</Subcategory>
    <Keyword>databases</Keyword>
    <Title>How Can I Compact a Microsoft Access Database?</Title>
    <URL>https://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1009.mspx</URL>
  </Script>
  <Script>
    <Category>Microsoft Office</Category>
    <Subcategory>Microsoft Word</Subcategory>
    <Keyword>hyperlinks</Keyword>
    <Title>How Can I Change an Existing Hyperlink in a Microsoft Word Document?</Title>
    <URL>https://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1016.mspx</URL>
  </Script>
  <Script>
    <Category>Enterprise Servers</Category>
    <Subcategory>Microsoft SQL Server</Subcategory>
    <Keyword>databases</Keyword>
    <Title>How Can I Create a Table in a SQL Server Database?</Title>
    <URL>https://www.microsoft.com/technet/scriptcenter/resources/qanda/oct06/hey1016.mspx</URL>
  </Script>
</Repository>

Comme vous pouvez le constater, c'est un petit fichier très simple. Chaque script individuel est classé sous une balise <Script>. A partir de maintenant, nous appellerons ces scripts « enregistrements ». Oui, vous avez raison, les passionnés de XML n'appelleraient jamais ces éléments des enregistrements. Mais ce n'est pas un problème. Notre objectif ici est de vous montrer comment appliquer quelque chose que vous connaissez déjà (les techniques d'interrogation de base de données) à un nouveau type de source de données différent. Nous avons décidé de nous concentrer tout d'abord sur la réalisation des opérations, puis de revenir ensuite sur ce sujet et de vous fournir alors la terminologie correcte.

Bien, revenons à nos enregistrements. Chaque enregistrement contient les champs suivants : <Catégorie>, <Sous-catégorie>, <Mot-clé>, <Titre> et <URL>.

Mouais, vous n'êtes pas aussi impressionné que nous l'imaginions. Il vaudrait peut-être mieux que nous vous montrions un script capable d'ouvrir ce fichier XML et d'en renvoyer le contenu :

Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.Async = "False"
xmlDoc.Load("C:\Scripts\Scripts.xml")

Set colNodes = xmlDoc.selectNodes _
("/Repository/Script/*")

For Each objNode in colNodes
   Wscript.Echo objNode.Text
Next

Remarque : Faites attention : ces noms de balise sont sensibles à la casse. Il s'agit de « "/Repository/Script" », et non de « "/repository/script" » ou de « "/REPOSITORY/SCRIPT" ».

D'accord, ce n'est pas non plus particulièrement impressionnant. Mais c'est exactement ce que nous souhaitons vous prouver : c'est loin d'être aussi difficile que vous pourriez le croire.

Comme vous pouvez le voir dans le code, nous commençons par créer une instance de l'objet Microsoft.XMLDOM, l'objet COM utilisé pour travailler avec les fichiers XML. Nous définissons ensuite la propriété Async sur False. Ceci permet d'assurer que l'ensemble du fichier est lu en mémoire avant que le contrôle ne soit renvoyé au script. La méthode Load est ensuite utilisée pour lire le fichier C:\Scripts\Scripts.xml:

xmlDoc.Load("C:\Scripts\Scripts.xml")

Dès que le fichier a été chargé en mémoire, nous pouvons utiliser la méthode selectNodes pour sélectionner les enregistrements spécifiés de la base de données :

Set colNodes = xmlDoc.selectNodes _
("/Repository/Script/*")

Examinez de plus près le paramètre transmis à selectNodes. Il représente le chemin dans le fichier XML. Le fichier XML a la structure suivante :

<Repository>
    <Script>
        <Category></Category>
        <Subcategory></Subcategory>
        <Keyword></Keyword>
        <Title></Title>
        <URL></URL>
    </Script>
</Repository>

Devez-vous vous en soucier ? Absolument ! Lorsque vous traitez des fichiers XML, la structure est très importante. Par exemple, comment obtenons-nous les propriétés individuelles d'un enregistrement ? Rien de plus simple : nous accédons à la balise <Repository> suivie de la balise <Script>, suivie des balises de propriété individuelles. Et devinez quoi ? Il s'agit du même chemin que celui que nous avons spécifié comme paramètre pour selectNodes. Il suffit d'ajouter /* après le chemin. Cela signifie « Sélectionner toutes les propriétés pour ces enregistrements ». En d'autres termes, l'ensemble renvoyé comprend toutes les propriétés pour tous les enregistrements de la base de données. Cette requête est comparable à la requête « Sélectionner * dans » dans Windows® Management Instrumentation (WMI).

Remarque : testez ce modèle de script pour voir exactement comment il fonctionne.

Le reste du script est simple : il suffit de configurer une boucle For Each pour examiner l'ensemble et renvoyer la valeur de la propriété Text de chaque élément de chaque propriété.

For Each objNode in colNodes
   Wscript.Echo objNode.Text
Next

C'est nettement plus facile que de courir après les voitures !

Mais vous avez raison : si nous souhaitions simplement renvoyer l'ensemble du contenu du fichier, nous pourrions nous passer de tout ce fatras XML et simplement utiliser le FileSystemObject. (Ce serait peut-être un peu plus compliqué, mais à peine). Si notre intention était de vous éblouir et de vous faire vous exclamer « Ca alors ! Ce XML est bien pratique après tout », nous sommes sans doute encore loin du compte.

Voyons donc ce que nous pouvons faire pour y parvenir. Dans le premier script, nous avons obtenu toutes les valeurs de propriétés pour tous les enregistrements. Très bien, mais supposons que nous ne voulions obtenir que le titre du script ? Est-ce possible ? Mmmhh, une petite minute...

Bon, d'après Lucy, il suffit de modifier la commande selectNodes en ajoutant la propriété qui nous intéresse à la fin du chemin. En d'autres termes :

    Set colNodes=xmlDoc.selectNodes _    ("/Repository/Script/Title")

il s'avère que la seule raison pour laquelle nous avons obtenu toutes les propriétés la première fois est que nous avons utilisé le caractère générique *. Maintenant, nous n'obtenons plus que la propriété Titre. Pourquoi ? Parce que c'est la seule valeur de propriété que nous avons demandé à obtenir.

Remarque : n'est-ce pas fabuleux : XML vous donne exactement que vous demandez. Désolé, Lucy, mais nous pensons que le XML est le nouveau meilleur ami de l'homme !

Et bien sûr, il est possible d'obtenir plus d'une propriété. Par exemple, cette commande modifiée renvoie des valeurs pour les propriétés Titre et URL :

    Set colNodes=xmlDoc.selectNodes _    ("/Repository/Script/(Title | URL)")

Il est vrai que la syntaxe paraît un peu maladroite, mais une fois que vous vous y êtes fait, ce n'est pas si mal. Pour commencer, spécifions la partie parent du chemin, comme nous l'avons déjà fait :

    /Repository/Script/

Il suffit ensuite d'ajouter des parenthèses et, entre ces parenthèses, de spécifier les propriétés à renvoyer. (Veuillez noter que nous utilisons le caractère | pour séparer les différentes propriétés). En d'autres termes :

    (Title | URL)

comme nous l'avons déjà dit, c'est peut-être un peu gauche, mais ça marche.

Et non, vous n'êtes pas limité à deux propriétés. Tant que vous ajoutez des caractères de séparation |, vous pouvez renvoyer autant d'informations que vous le souhaitez. Par exemple, la commande suivante renvoie trois propriétés (titre, URL et mot-clé) :

    Set colNodes=xmlDoc.selectNodes _    ("/Repository/Script/(Title | URL |          Keyword)")

Pas mal, hein ?

Nous pensions que c'était pas mal pourtant. Vous êtes difficile à satisfaire. Mais vous n'avez pas tout à fait tort : tout ce que nous avons fait jusqu'à présent est de récupérer des informations sur les enregistrements dans notre base de données. Cependant, il n'y a pas de mal à cela. C'est souvent ce que vous souhaitez accomplir. D'un autre côté, il arrive aussi (souvent) que vous souhaitiez obtenir des informations seulement sur un sous-ensemble de ces enregistrements. Par exemple, vous ne souhaitez peut-être obtenir des informations que sur les scripts qui ont un mot-clé égal à databases (bases de données). He bien, il suffit d'utiliser une requête telle que celle-ci :

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword = ‘databases’]")

Là encore, la syntaxe est un peu bizarre. D'un autre côté, elle est aussi simple et facile à utiliser. Après avoir spécifié le chemin parent, nous plaçons notre clause « Where » (par exemple, where x equals y) entre crochets, comme suit :

/Repository/Script [Keyword = ‘databases’]

Comme vous vous en êtes sans doute déjà aperçu, notre équivalent de la clause Where indique au script de « Renvoyer uniquement les éléments où l'attribut de mot-clé est égal à databases ». Veuillez noter que le terme databases est placé entre des guillemets simples. C'est non seulement parfaitement correct, c'est même obligatoire. Si le terme de filtre est placé entre des guillemets doubles, vous obtiendrez une erreur de syntaxe lorsque vous tenterez d'exécuter le script.

Remarque : pourquoi ? Parce que la chaîne de requête complète "/Repository/Script [Keyword = 'databases']" est placée entre des guillemets doubles.

Bien sûr, vous n'êtes pas limité à l'utilisation du signe égal (=) lorsque vous filtrez les données. Vous pouvez utiliser les symboles supérieur à (>) ou inférieur à (<), de même que ces chouchous universels, les symboles inférieur ou égal à (<=) et supérieur ou égal à (>=). Vous pouvez également annuler tous ces symboles en les faisant précéder d'un point d'exclamation. Par exemple, la commande suivante interroge tous les scripts où le mot-clé n'est pas égal à databases (notez le symbole  !=) :

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword != ‘databases’]")

Quoi ? Qui a dit « D'accord, vous pouvez configurer un filtre, mais je vous parie que vous ne pouvez pas configurer un filtre et spécifier les propriétés que vous souhaitez renvoyer » ? Bien sûr que c'est possible :

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword = ‘databases’]/Title")

si tout se passe bien, cette commande ne renverra que la propriété Titre pour tous les scripts qui ont le mot-clé databases. Voyons si cela fonctionne :

    How Can I Print a Microsoft Access Report?
    How Can I Compact a Microsoft Access Database?
    How Can I Create a Table in a SQL Server     Database?

Examinons une dernière commande avant de prendre un repos bien mérité. Nous avons bien avancé, mais nous renvoyons peut-être encore plus d'enregistrements que nous ne le souhaitons vraiment. Après tout, notre commande précédente renvoyait un mélange de scripts Microsoft® Access® et de scripts Microsoft SQL Server™. (Pourquoi ? Parce que tous ces scripts utilisent le mot-clé databases). Que se passe-t-il si nous souhaitons limiter les données renvoyées aux scripts qui ont le mot-clé databases et la sous-catégorie Microsoft SQL Server ? Est-il possible d'effectuer le filtrage sur plusieurs critères ?

La question ne se pose même pas.

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Keyword = ‘databases’ and " & _
    "Subcategory = ‘Microsoft SQL Server’]")

La syntaxe de base est la même. Il suffit d'utiliser deux critères distincts (soit mot-clé = 'databases' et sous-catégorie = 'Microsoft SQL Server') et de connecter les deux à l'aide de l'opérateur AND.

Remarque : vous avez tout à fait raison : avec ce petit fichier XML simple, nous aurions pu simplement interroger tous les scripts dont la sous-catégorie était égale à Microsoft SQL Server. Mais ça n'aurait été ni amusant, ni éducatif.

Il est également possible d'utiliser les clauses OR. Par exemple, supposons que nous avons tout un tas de scripts Microsoft Office, y compris ceux dont la sous-catégorie est égale à Microsoft Excel®,Microsoft PowerPoint®,Microsoft Outlook®, etc. Est-il possible de limiter les données renvoyées aux scripts des sous-catégories Microsoft Word ou Microsoft Access uniquement ? Absolument.

    Set colNodes=xmlDoc.selectNodes _
    ("/Repository/Script " & _
    "[Subcategory = ‘Microsoft Word’ " & _
    "or Subcategory = ‘Microsoft Access’]")

Cela vous convient-il mieux ? D'accord, cette chronique ne va peut-être pas vous changer la vie, mais il est fort probable que, tôt ou tard, vous trouviez utile de pouvoir interroger un fichier XML de la sorte. Mais la décision vous revient : vous pouvez apprendre quelques techniques XML de base, ou vous pouvez courir après les voitures. C'est vous qui voyez. (Si vous choisissez la seconde option et que vous rencontrez Lucy, la chienne de notre rue, passez-lui le bonjour du Scripteur. Et dites-lui de laisser notre jardin tranquille !)

Hé, vous le Scripteur ! - Tous les jours

Vous venez de lire la chronique Hé, vous le Scripteur de ce mois-ci, et vous pensez que c'est le meilleur article technique que vous ayez jamais lu. Vous iriez même jusqu'à dire que c'est le meilleur article jamais écrit. Qui plus est, vous ne quittez pas votre boîte de réception des yeux, dans l'attente du prochain numéro de Technet Magazine, dans lequel vous espérez trouver d'autres articles du même style.

Qu'attendez-vous ? Vous voulez en savoir plus sur Lucy, la chienne de notre rue, ou vous avez envie de lire les derniers exploits du Fils du scripteur ? Avez-vous entendu les résultats du Turducken Bowl de l'année dernière ? Restez informé de tous ces événements cruciaux en lisant la chronique quotidienne (oui, nous avons bien dit quotidienne) Hé, vous le Scripteur ! Du lundi au vendredi (sauf durant les jours fériés et pendant les vacances du Scripteur), vous pouvez lire tous les résultats de l'équipe de base-ball au lycée et des équipes de football et de basketball de l'université, et, de temps à autre, un bulletin météorologique local. (D'accord, ce n'est vrai que si pour vous, « local » veut dire Redmond, mais qui ne souhaiterait pas en savoir plus sur la météo de Redmond) ?

Non seulement cela, mais vous découvrirez chaque jour quelque chose de nouveau sur la rédaction des scripts. Oui, parmi tout ce contenu passionnant, vous trouverez aussi de véritables informations sur les scripts. Dans chaque chronique, les Scripteurs répondent à de vraies questions envoyées par ce qu'ils supposent être de vrais utilisateurs. Vous pouvez lire la chronique quotidienne en ligne à l'adresse microsoft.com/technet/scriptcenter/resources/qanda. Par ailleurs, puisque les scripteurs ont déjà répondu à des centaines de questions, les archives sont vastes et représentent une large source d'informations sur la rédaction de scripts (voir microsoft.com/technet/scriptcenter/resources/qanda/hsgarch.mspx).

Avez-vous une question pour les Scripteurs ? Vous avez une petite chance d'obtenir une réponse à votre question si vous la soumettez à scripter@microsoft.com. (Vous n'avez par contre aucune chance d'obtenir une réponse si vous n'envoyez pas votre question, alors qu'avez-vous à perdre ? Contrairement à un billet de loto, c'est gratuit, et vos chances sont légèrement supérieure).

Les scripteurs Microsofttravaillent pour (enfin, sont employés par) Microsoft. Lorsqu'ils ne sont pas en train de jouer au base-ball, d'entraîner une équipe ou de regarder un match (ou de se livrer à de multiples autres activités), ils dirigent le Script Center TechNet. Vous pouvez le vérifier vous-même sur www.scriptingguys.com.

© 2008 Microsoft Corporation et CMP Media, LLC. Tous droits réservés. Toute reproduction, totale ou partielle, est interdite sans autorisation préalable.