Redgate Hub

  • Accesso ai dati XML in PowerShell
    • Accesso a XML con XPath.
    • Accedere a XML come oggetti.
    • Confronto tra XPath e approcci a oggetti
  • Modificare o creare dati XML
    • Aggiungere dati XML
    • Utilizzare XML per la serializzazione di oggetti

Introduzione

Come ogni linguaggio di alto livello, the dataè al centro di PowerShell. Nel caso di PowerShell, si tratta di convertire dati esterni in oggetti PowerShell e viceversa. Questo è il secondo di una serie di articoli che ti mostra come importare quasi tutti i formati di dati comuni che è probabile incontrare, e come esportare in alcuni di essi. Il primo articolo della serie, PowerShell Data Basics: File-Based Data, copre una varietà di formati di testo, dai file a larghezza fissa, a larghezza variabile e a destra stracciata a CSV, elenchi di proprietà, file INI e dati JSON, e si conclude con un trattamento di importazione ed esportazione in Excel. Qui ci concentriamo su come ottenere il massimo da XML.

Accedere ai dati XML in PowerShell

Ci sono due tecniche integrate per lavorare con i dati XML in PowerShell; l’approccio XPath e l’approccio dot-notation degli oggetti. Descriveremo e confronteremo questi due approcci, e li proveremo su alcuni esempi di XML. Per comodità, tutti gli esempi di codice usano questo file XML di esempio da MSDN. La Figura 1 mostra una rappresentazione dello schema sottostante il file in un formato conciso (in particolare rispetto alla lettura del file XSD grezzo!), per gentile concessione di XML Schema Explorer di Visual Studio. Dalla figura, noterete che il file XML è un catalogo che contiene una collezione di libri. Ogni libro ha sette caratteristiche, sei delle quali sono elementi figli e una che è un attributo figlio.

Figura 1 Schema per il file XML di esempio di Microsofto:p>

Per caricare questo file XML di esempio, potete usare uno di questi:

se preferite sperimentare con dati XML immediati piuttosto che caricare un file XML in un XmlDocument, è semplice da fare. Definisci semplicemente il tuo XML come una stringa e fallo diventare di tipo XML come abbiamo appena fatto con il cmdlet Get-Content per i file. Ecco una porzione del file XML di esempio con solo due libri:

Accedere a XML con XPath

Con il file caricato in un oggetto XmlDocument, è possibile navigare nell’albero XML con XPath. Per selezionare un insieme di nodi usa il metodo SelectNodes:

$xdoc.SelectNodes(“//author”)

#text

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

Oppure usa SelectSingleNode per restituire solo un nodo:

$xdoc.SelectSingleNode(“//book”)

id : bk102

autore : Ralls, Kim

titolo : Midnight Rain

genere : Fantasy

prezzo : 5.95

publish_date : 2000-12-16

description : Un ex architetto combatte gli zombie aziendali,

una maga malvagia, e la sua stessa infanzia per diventare regina

del mondo.

Nota nel primo esempio che ci sono duplicati. Supponiamo invece che vogliate una lista di autori unici nel catalogo. Potreste pensare che qualcosa come …

1
$xdoc.SelectNodes(“//autore”) | select -Unique

…funzionerebbe, ma in realtà restituisce solo il nome del primo autore. Per capire perché ha fallito, dovreste capire di più sulla struttura dei documenti XML. Il primo esempio ha effettivamente restituito una lista di nodi di testo (cioè non una lista di testo) e il filtro unico sta operando su quella lista, cercando l’unicità del tipo di elemento. Poiché tutti gli elementi della collezione sono nodi di testo, e quindi sono tutti dello stesso tipo di elemento, tutti i nodi oltre il primo sono quindi considerati duplicati. Il risultato è che solo il primo viene restituito.

Quello che state veramente cercando è il valore della stringa di ogni nodo autore. Dal nodo autore devi prima accedere al suo nodo testo (il suo primo e unico figlio), poi al valore di quel nodo testo (linea A nel prossimo esempio). In alternativa, puoi usare un’espressione leggermente più breve con la proprietà InnerText (linea B). Un’altra variazione usa il cmdlet Select-Xml che evita una chiamata di metodo e quindi è, in un certo senso, un approccio più distintamente PowerShell (linea C). Tutte e tre le linee restituiscono lo stesso risultato.

SelectNodes e SelectSingleNode insieme ti danno una funzionalità equivalente a Select-Xml. Entrambi supportano i namespace, che non ho ancora menzionato. I due metodi prendono entrambi un XmlNamespaceManager come secondo parametro opzionale, mentre il cmdlet Select-Xml prende un parametro opzionale Namespace che specifica i vostri namespace in una tabella hash.

SelectSingleNode restituisce un XmlNode e SelectNodes restituisce un XmlNodeList. Select-Xml, d’altra parte, restituisce un oggetto SelectXmlInfo (o un array di essi) e la sua proprietà Node fornisce l’accesso al nodo sottostante. L’esempio appena sopra illustra queste differenze.

Accedere a XML come oggetti

Con lo stesso oggetto XmlDocument della sezione precedente, PowerShell fornisce anche un supporto dinamico agli oggetti per i dati XML: Questo vi permette di accedere ai dati XML come oggetti PowerShell di prima classe, non richiedendo né un selettore XPath né familiarità con i dettagli di cose come nodi XML, valori o nodi di testo. Inoltre, ottieni un Intellisense istantaneo e dinamico del tuo schema XML quando carichi i tuoi dati XML! La figura 2 illustra questo per l’ISE di PowerShell, dove si ottengono sia scelte di selezione che completamento di parole, proprio come con i token nativi di PowerShell. Notate in particolare nell’espansione inferiore che cerca ciò che avete digitato in qualsiasi punto del nome della proprietà, non solo a partire dal primo carattere: Intellisense vi troverebbe una proprietà data qui, sia che si chiami published_date o releaseDate o date_of_publication. Nota che hai il completamento delle parole disponibile in PowerShell V2 o V3, e in PowerShell ISE o PowerShell console. Ma le scelte di selezione sono disponibili solo in PowerShell ISE in V3.

Figura 2 Intellisense automatico al caricamento di un documento XML

Ecco alcuni esempi per mostrare che l’XML è effettivamente convertito automaticamente in oggetti PowerShell:

$xdoc

xml catalog

– —

version=”1.0″ catalog

$xdoc.catalog

book

{book, book, book, book…}

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

id autore titolo genere prezzo publish_date descrizione

– — — — —- —-

bk101 Gambardella, Matthew XML Developer’s Guide Computer 44.95 2000-10-01 Uno sguardo approfondito …

bk102 Ralls, Kim Midnight Rain Fantasy 5.95 2000-12-16 Un ex architetto…

bk103 Corets, Eva Maeve Ascendant Fantasy 5.95 2000-11-17 Dopo il crollo…

bk104 Corets, Eva Oberon’s Legacy Fantasy 5.95 2001-03-10 Nel post-apocalisse…

bk105 Corets, Eva The Sundered Grail Fantasy 5.95 2001-09-10 Le due figlie…

bk106 Randall, Cynthia Lover Birds Romance 4.95 2000-09-02 Quando Carla incontra …

bk107 Thurman, Paula Splish Splash Romance 4.95 2000-11-02 Un subacqueo di mare profondo …

bk108 Knorr, Stefan Creepy Crawlies Horror 4.95 2000-12-06 Un’antologia di h…

bk109 Kress, Peter Paradox Lost Science Fiction 6.95 2000-11-02 Dopo un inavvertito…

bk110 O’Brien, Tim Microsoft .NET: Il 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

autore : Corets, Eva

titolo : Maeve Ascendant

genere : Fantasy

prezzo : 5.95

publish_date : 2000-11-17

description : Dopo il crollo di una società nanotecnologica

in Inghilterra, i giovani sopravvissuti gettano le

fondamenta per una nuova società

$xdoc.catalog.book.author

Randall, Cynthia

$xdoc.catalog.book.id

bk106

Si noti che tutti i nodi XML nel documento sono convertiti in proprietà standard PowerShell, sia che un nodo abbia figli (ad esempio catalogo) o sia un nodo foglia (ad esempio prezzo), o che un nodo foglia sia un elemento (ad esempio autore) o un attributo (ad esempio id). In particolare (come illustrano gli ultimi due esempi sopra), i valori degli elementi e degli attributi sono trattati esattamente allo stesso modo con la notazione standard “punto”.

Confronto tra gli approcci XPath e Object

Quale approccio è migliore per accedere ai dati XML? La tabella 1 aiuta a rispondere a questa domanda. L’approccio a oggetti è di solito più conciso (per esempio, riga 3), ma non sempre (riga 4). XPath, tuttavia, è più espressivo, in quanto permette di specificare alcuni selettori che non sono possibili con la notazione a oggetti (riga 7). Tuttavia, le capacità proprie di PowerShell possono facilmente colmare questa lacuna quando si usa la notazione a oggetti (riga 8).

Tabella 1 Confronto degli approcci XPath e dei selettori a oggetti per l’accesso a XML.

Modificare o creare dati XML

Data una comprensione dei selettori XML dalle sezioni precedenti, modificare un documento XML è abbastanza semplice perché i selettori XML (sia XPath che a oggetti) sono valori L, cioè si può scrivere su di essi così come leggere da essi! Così uno di questi modificherà l’autore del sesto libro:

1
2

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

Quasi spesso, potreste avere un file XML esistente dove volete cambiare uno o più valori di nodo. Probabilmente vorrete leggere il file, modificare i dati e salvare il file con lo stesso nome. Avete visto i primi due passi; il terzo passo è fatto con il metodo Save su XmlDocument. Mettendo tutto insieme, quindi, si ottiene questo codice di base:

Questo codice funziona bene – tranne che la maggior parte delle volte sembrerà essere fallito! Questo semplice pezzo di codice illustra una nozione apparentemente minore ma importante di PowerShell; l’ignoranza di questo ha portato a molti post di blog che sostengono che sia un bug in PowerShell. Il problema è che la tua directory di lavoro e la tua posizione in PowerShell non sono la stessa cosa. Il codice di cui sopra legge bene il file, modifica bene i dati, ma non necessariamente salva il nuovo file dove ci si aspetta. Get-Content, essendo una cmdlet PowerShell, vede un percorso del file relativo alla posizione PowerShell. Il metodo XmlDocument.Save, invece, vede un percorso di file relativo alla directory di lavoro del processo PowerShell, perché quella chiamata di metodo è al di fuori di PowerShell. Se non avete eseguito Set-Location (o il suo alias cd) nella vostra attuale sessione PowerShell, entrambi puntano alla stessa directory. Per confermarlo, esegui queste due istruzioni:

1
2

Get-Location # visualizza la posizione PowerShell
::CurrentDirectory # visualizza la directory di lavoro

L’approccio più sicuro, quindi, è quello di utilizzare percorsi assoluti per evitare del tutto questo problema. Vedi l’articolo di Alex Angelopoulos Why the PowerShell Working Directory and the PowerShell Location Aren’t One in the Same per saperne di più.

Adding XML Data

Aggiungere nuovi nodi al tuo documento XML richiede un po’ più lavoro che modificare il valore di un nodo esistente. Un approccio che mi piace è quello di Tobias Weltner nel suo blog Write, Add and Change XML Data: prendi un nodo esistente del tipo che vuoi creare, fai una copia di quel nodo e modifica la copia con i tuoi nuovi dati, e infine inserisci il nodo copiato nel tuo XML come un fratello dell’originale. Applicando questo al nostro esempio di catalogo di libri, questo pezzo di codice crea un nuovo nodo libro e lo aggiunge alla fine della collezione:

Se volete aggiungere il nuovo libro in una posizione diversa, ad esempio dopo il terzo libro, usate InsertAfter invece di AppendChild:

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

(Il nome del metodo InsertAfter smentisce il fatto che non aggiunge solo nodi; può anche spostarli! Il metodo controlla se il nodo che si chiede di aggiungere è già presente nel documento. Se è così, lo sposta nella nuova posizione specificata. Quindi, quando vuoi copiare i nodi, devi iniziare con il metodo Clone come illustrato sopra.)

Per ulteriori approfondimenti sulla manipolazione dei dati XML con i metodi .NET, vedi Process XML Data Using the DOM Model su MSDN.

Using XML for Object Serialization

PowerShell fornisce un modo semplice per persistere gli oggetti usando Export-Clixml per serializzare qualsiasi oggetto e memorizzarlo in un file XML e Import-Clixml per ripristinare l’oggetto da XML. Con XML, a differenza della maggior parte delle altre tecniche di serializzazione, l’integrità dell’oggetto è preservata: al ripristino di un oggetto da XML tutte le proprietà sono correttamente tipizzate così come l’oggetto padre stesso, quindi tutti i metodi sull’oggetto originale sono disponibili anche sull’oggetto rigenerato. Per usare Export-Clixml, è sufficiente fare un pipe con qualsiasi collezione di oggetti e specificare un file di destinazione. Ecco un semplice esempio che mostra che l’output di Get-ChildItem, una collezione di oggetti FileSystemInfo, viene rigenerato:

.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.