Redgate Hub

  • Accéder aux données XML dans PowerShell
    • Accéder à XML avec XPath.
    • Accéder à XML en tant qu’objets.
    • Comparaison des approches XPath et objet
  • Modifier ou créer des données XML
    • Ajouter des données XML
    • Utiliser XML pour la sérialisation d’objets

Introduction

Comme tout langage de haut niveau, the data est au cœur de PowerShell. Dans le cas de PowerShell, cela se résume à la conversion de données externes en objets PowerShell et vice versa. Cet article est le deuxième d’une série d’articles qui vous montre comment importer presque tous les formats de données courants que vous êtes susceptible de rencontrer, et comment exporter vers certains d’entre eux également. Le premier article de la série, PowerShell Data Basics : File-Based Data, couvre une grande variété de formats de texte, des fichiers à largeur fixe, à largeur variable, aux fichiers CSV, aux listes de propriétés, aux fichiers INI et aux données JSON, et se termine par un traitement de l’importation et de l’exportation vers Excel. Ici, nous nous concentrons sur l’obtention du maximum de XML.

Accéder aux données XML dans PowerShell

Il existe deux techniques intégrées pour travailler avec des données XML dans PowerShell ; l’approche XPath et l’approche point-notation d’objet. Nous allons décrire et comparer ces deux approches, et les essayer sur quelques échantillons de XML. Pour des raisons de commodité, tous les exemples de code utilisent cet exemple de fichier XML provenant de MSDN. La figure 1 montre une représentation du schéma sous-jacent au fichier dans un format concis (notamment par rapport à la lecture du fichier XSD brut !), grâce à l’explorateur de schéma XML de Visual Studio. Sur la figure, vous remarquerez que le fichier XML est un catalogue qui contient une collection de livres. Chaque livre possède sept caractéristiques, dont six sont des éléments enfants et une qui est un attribut enfant.

Figure 1 Schéma pour l’échantillon de fichier XML de Microsofto:p>

Pour charger cet échantillon de fichier XML, vous pouvez utiliser l’une de ces possibilités:

si vous préférez expérimenter avec des données XML immédiates plutôt que de charger un fichier XML dans un XmlDocument, c’est simple à faire. Il suffit de définir votre XML comme une chaîne et de la convertir en type XML comme nous venons de le faire avec la cmdlet Get-Content pour les fichiers. Voici une partie de l’échantillon de fichier XML avec seulement deux livres:

Accéder à XML avec XPath

Avec le fichier chargé dans un objet XmlDocument, vous pouvez ensuite naviguer dans l’arbre XML avec XPath. Pour sélectionner un ensemble de nœuds, utilisez la méthode SelectNodes:

$xdoc.SelectNodes(« //auteur »)

#texte

Gambardella, Matthew

Ralls, Kim

Corets, Eva

Corets, Eva

Corets, Eva

Randall, Cynthia

Thurman, Paula

Knorr, Stefan

Kress, Peter

O’Brien, Tim

O’Brien, Tim

Galos, Mike

Ou utilisez SelectSingleNode pour retourner un seul noeud :

$xdoc.SelectSingleNode(« //book »)

id : bk102

auteur : Ralls, Kim

titre : Midnight Rain

genre : Fantasy

Prix : 5.95

date de publication : 2000-12-16

description : Une ancienne architecte combat des zombies d’entreprise,

une sorcière maléfique, et sa propre enfance pour devenir reine

du monde.

Notez dans le premier exemple qu’il y a des doublons. Supposons plutôt que vous voulez une liste d’auteurs uniques dans le catalogue. Vous pourriez penser que quelque chose comme …

1
$xdoc.SelectNodes(« //author ») | select -Unique

…fonctionnerait, mais il ne renvoie en fait que le nom du premier auteur. Pour comprendre pourquoi cela a échoué, il faudrait que vous compreniez mieux la structure des documents XML. Le premier exemple renvoie en fait une liste de nœuds de texte (c’est-à-dire pas une liste de texte) et le filtre unique opère sur cette liste, en recherchant l’unicité du type d’élément. Puisque tous les éléments de la collection sont des noeuds de texte, et sont donc tous du même type d’élément, tous les noeuds au-delà du premier sont donc considérés comme des doublons. Le résultat est que seul le premier est retourné.

Ce que vous recherchez réellement est la valeur de la chaîne de caractères de chaque nœud auteur. À partir du nœud auteur, vous devez d’abord accéder à son nœud texte (son premier et seul enfant), puis à la valeur de ce nœud texte (ligne A dans l’exemple suivant). Vous pouvez également utiliser une expression légèrement plus courte avec la propriété InnerText (ligne B). Une autre variante utilise la cmdlet Select-Xml, qui évite l’appel à une méthode et constitue donc, dans un certain sens, une approche plus distinctive de PowerShell (ligne C). Les trois lignes renvoient le même résultat.

SelectNodes et SelectSingleNode vous donnent ensemble une fonctionnalité équivalente à Select-Xml. Les deux supportent les espaces de noms, que je n’ai pas encore mentionnés. Les deux méthodes prennent un XmlNamespaceManager comme second paramètre facultatif, tandis que le cmdlet Select-Xml prend un paramètre Namespace facultatif qui spécifie vos espaces de noms dans une table de hachage.

SelectSingleNode renvoie un XmlNode et SelectNodes renvoie une XmlNodeList. Select-Xml, en revanche, renvoie un objet SelectXmlInfo (ou un tableau de ceux-ci) et sa propriété Node permet d’accéder au nœud sous-jacent. L’exemple juste au-dessus illustre ces différences.

Accéder à XML en tant qu’objets

Avec le même objet XmlDocument de la dernière section, PowerShell fournit également un support d’objet dynamique pour les données XML : Cela vous permet d’accéder aux données XML en tant qu’objets PowerShell de première classe, ne nécessitant ni sélecteur XPath ni familiarité avec les détails de choses telles que les nœuds XML, les valeurs ou les nœuds de texte. De plus, vous bénéficiez d’un Intellisense dynamique et instantané de votre schéma XML lorsque vous chargez vos données XML ! La figure 2 illustre cette situation pour l’ISE de PowerShell, où vous disposez à la fois de choix de sélection et de complétion de mots, tout comme avec les jetons natifs de PowerShell. Remarquez en particulier dans l’expansion du bas qu’elle recherche ce que vous avez tapé n’importe où dans le nom de la propriété, et pas seulement à partir du premier caractère : Intellisense vous trouverait une propriété de date ici, qu’elle soit nommée published_date ou releaseDate ou date_of_publication. Notez que la complétion de mot est disponible dans PowerShell V2 ou V3, et dans PowerShell ISE ou PowerShell console. Mais les choix de sélection ne sont disponibles que dans PowerShell ISE en V3.

Figure 2 Intellisense automatique au chargement d’un document XML

Voici quelques exemples pour montrer que le XML est bien auto-converti en objets PowerShell:

$xdoc

xml catalog

– —

version= »1.0″ catalog

$xdoc.catalog

book

{livre, livre, livre, livre…}

$xdoc.catalog.book | Format-Table -AutoSize

id auteur titre genre prix date_publication description

– — — — — —-

bk101 Gambardella, Matthew XML Developer’s Guide Computer 44.95 2000-10-01 Un regard en profondeur …

bk102 Ralls, Kim Midnight Rain Fantasy 5.95 2000-12-16 Un ancien architecte …

bk103 Corets, Eva Maeve Ascendant Fantasy 5.95 2000-11-17 Après l’effondrement …

bk104 Corets, Eva Oberon’s Legacy Fantasy 5.95 2001-03-10 Dans un contexte post-apocalyps…

bk105 Corets, Eva The Sundered Grail Fantasy 5.95 2001-09-10 Les deux filles…

bk106 Randall, Cynthia Lover Birds Romance 4.95 2000-09-02 Quand Carla rencontre …

bk107 Thurman, Paula Splish Splash Romance 4.95 2000-11-02 Un plongeur en haute mer …

bk108 Knorr, Stefan Creepy Crawlies Horror 4.95 2000-12-06 Une anthologie de h…

bk109 Kress, Peter Paradox Lost Science Fiction 6.95 2000-11-02 Après une inadvertance …

bk110 O’Brien, Tim Microsoft .NET : The Prog… Computer 36.95 2000-12-09 Microsoft .NET …

bk111 O’Brien, Tim MSXML3 : A Comprehensive … Computer 36.95 2000-12-01 The Microsoft MSX…

bk112 Galos, Mike Visual Studio 7 : A Compr… Computer 49.95 2001-04-16 Microsoft Visual …

$xdoc.catalog.book

id : bk103

auteur : Corets, Eva

titre : Maeve Ascendant

genre : Fantasy

Prix : 5.95

date de publication : 2000-11-17

description : Après l’effondrement d’une société de nanotechnologie

en Angleterre, les jeunes survivants posent les

fondements d’une nouvelle société

$xdoc.catalog.book.author

Randall, Cynthia

$xdoc.catalog.book.id

bk106

Remarquez que tous les nœuds XML du document sont convertis en propriétés PowerShell standard, qu’un nœud ait des enfants (par exemple, catalogue) ou soit un nœud feuille (par exemple, prix), ou qu’un nœud feuille soit un élément (par exemple, auteur) ou un attribut (par exemple, id). En particulier (comme l’illustrent les deux derniers exemples ci-dessus), les valeurs d’élément et les valeurs d’attribut sont traitées exactement de la même manière avec la notation standard « point ».

Comparaison des approches XPath et objet

Quelle approche est la meilleure pour accéder aux données XML ? Le tableau 1 vous aide à répondre à cette question. L’approche objet est généralement plus concise (par exemple, la ligne 3), mais pas toujours (ligne 4). XPath est toutefois plus expressif, dans la mesure où il vous permet de spécifier certains sélecteurs qui ne sont pas possibles avec la notation objet (ligne 7). Cependant, les capacités propres de PowerShell peuvent facilement combler cette lacune lors de l’utilisation de la notation objet (ligne 8).

Tableau 1 Comparaison des approches de sélecteurs XPath et objet pour l’accès au XML.

Modification ou création de données XML

Sous réserve d’une appréciation des sélecteurs XML à partir des sections précédentes, la modification d’un document XML est assez simple car les sélecteurs XML (qu’ils soient XPath ou objet) sont des valeurs L, c’est-à-dire que vous pouvez écrire sur eux ainsi que lire à partir d’eux ! Ainsi, l’un ou l’autre de ces éléments modifiera l’auteur du 6ème livre :

1
2

$xdoc.SelectSingleNode(« //book/author »).InnerText = ‘jones’
$xdoc.catalog.book.author = ‘smith’

Plus souvent, vous pourriez avoir un fichier XML existant dans lequel vous voulez changer une ou des valeurs de nœuds. Vous voudriez probablement lire le fichier, modifier les données, et enregistrer à nouveau le fichier sous le même nom. Vous avez vu les deux premières étapes ; la troisième étape est réalisée avec la méthode Save sur le XmlDocument. En assemblant tout cela, on obtient donc ce code de base :

Ce code fonctionne bien – sauf que la plupart du temps, il semblera avoir échoué ! Ce simple bout de code illustre une notion apparemment mineure mais importante de PowerShell ; l’ignorance de cette notion a conduit à de nombreux articles de blog affirmant qu’il s’agit d’un bug dans PowerShell. Le problème est que votre répertoire de travail et votre emplacement PowerShell ne sont pas la même chose. Le code ci-dessus lit bien le fichier, il modifie bien les données, mais il n’enregistre pas nécessairement le nouveau fichier à l’endroit prévu. Get-Content, étant une cmdlet PowerShell, voit un chemin de fichier relatif à l’emplacement PowerShell. La méthode XmlDocument.Save, en revanche, voit un chemin de fichier relatif au répertoire de travail du processus PowerShell, car cet appel de méthode est extérieur à PowerShell. Si vous n’avez pas exécuté Set-Location (ou son alias cd) dans votre session PowerShell actuelle, les deux méthodes pointent vers le même répertoire. Pour le confirmer, exécutez ces deux instructions :

1
2

Get-Location # affiche l’emplacement PowerShell
::CurrentDirectory # affiche le répertoire de travail

L’approche la plus sûre, alors, est d’utiliser des chemins absolus pour éviter complètement ce problème. Voir l’article d’Alex Angelopoulos intitulé Why the PowerShell Working Directory and the PowerShell Location Aren’t One in the Same pour en savoir plus.

Ajout de données XML

Ajouter de nouveaux nœuds à votre document XML demande juste un peu plus de travail que de modifier la valeur d’un nœud existant. Une approche que j’apprécie est tirée de l’article de blog de Tobias Weltner intitulé Write, Add and Change XML Data : prenez un nœud existant du type que vous souhaitez créer, faites une copie de ce nœud et modifiez la copie avec vos nouvelles données, et enfin insérez le nœud copié dans votre XML en tant que frère ou sœur de l’original. En appliquant cela à notre exemple de catalogue de livres, ce bout de code crée un nouveau nœud de livre et l’ajoute à la fin de la collection :

Si vous souhaitez ajouter le nouveau livre à un endroit différent, disons après le 3ème livre, utilisez InsertAfter au lieu de AppendChild:

1
$xdoc.catalog.InsertAfter($book,$xdoc.catalog.book)

(Le nom de la méthode InsertAfter dément le fait qu’elle ne se contente pas d’ajouter des nœuds ; elle peut aussi déplacer des nœuds ! La méthode vérifie si le nœud que vous demandez d’ajouter se trouve déjà dans le document. Si c’est le cas, elle le déplace vers le nouvel emplacement que vous avez spécifié. Ainsi, lorsque vous voulez effectivement copier des nœuds, vous devez commencer par la méthode Clone, comme illustré ci-dessus.)

Pour une exploration plus approfondie sur la manipulation des données XML avec les méthodes .NET, voir Traiter les données XML en utilisant le modèle DOM sur MSDN.

Utiliser XML pour la sérialisation des objets

PowerShell fournit un moyen facile de faire persister les objets en utilisant Export-Clixml pour sérialiser n’importe quel objet et le stocker dans un fichier XML et Import-Clixml pour restaurer l’objet à partir de XML. Avec XML, contrairement à la plupart des autres techniques de sérialisation, l’intégrité des objets est préservée : lors de la restauration d’un objet à partir de XML, toutes les propriétés sont correctement typées, tout comme l’objet parent lui-même, de sorte que toutes les méthodes de l’objet original sont également disponibles sur l’objet régénéré. Pour utiliser Export-Clixml, il suffit de lui envoyer une collection d’objets et de spécifier un fichier de destination. Voici un exemple simple montrant que la sortie de Get-ChildItem, une collection d’objets FileSystemInfo, est régénérée :

.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.