Redgate Hub

  • XML-adatok elérése PowerShellben
    • Az XML elérése XPath segítségével.
    • Az XML objektumként való elérése.
    • Az XPath és az objektumos megközelítések összehasonlítása
  • XML-adatok módosítása vagy létrehozása
    • XML-adatok hozzáadása
    • Az XML használata objektumszerializáláshoz

Előszó

Mint minden magas szintű nyelvnél, a PowerShell the data központi eleme. A PowerShell esetében ez a külső adatok PowerShell-objektumokká való konvertálásában és fordítva merül ki. Ez a második része egy cikksorozatnak, amely bemutatja, hogyan lehet szinte az összes olyan gyakori adatformátumot importálni, amellyel valószínűleg találkozni fog, és hogyan lehet néhányat közülük exportálni is. A sorozat első cikke, a PowerShell adatalapjai: Fájlalapú adatok, számos szöveges formátumot tárgyal, a fix szélességű, változó szélességű és jobbra szaggatott fájloktól a CSV, a tulajdonságlisták, az INI-fájlok és a JSON-adatokig, majd az Excelbe történő importálás és exportálás kezelésével zárul. Itt arra koncentrálunk, hogy a legtöbbet hozzuk ki az XML-ből.

Az XML-adatok elérése a PowerShellben

A PowerShellben az XML-adatokkal való munkához két beépített technika áll rendelkezésre: az XPath megközelítés és az objektum pontjelöléses megközelítés. Leírjuk és összehasonlítjuk ezt a két megközelítést, és kipróbáljuk őket néhány XML-mintán. Az egyszerűség kedvéért minden kódpélda ezt az MSDN-ből származó minta XML-fájlt használja. Az 1. ábra a Visual Studio XML Schema Explorerének jóvoltából tömör formában mutatja be a fájl alapjául szolgáló sémát (különösen a nyers XSD-fájl olvasásához képest!). Az ábrán látható, hogy az XML-fájl egy katalógus, amely könyvek gyűjteményét tartalmazza. Minden könyvnek hét jellemzője van, amelyek közül hat gyermek elem, egy pedig gyermek attribútum.

1. ábra A Microsoft minta XML-fájljának sémájao:p>

A minta XML-fájljának betöltéséhez bármelyiket használhatja:

ha inkább azonnali XML-adatokkal szeretne kísérletezni, mint egy XML-fájlt betölteni egy XmlDokumentumba, ez egyszerűen megoldható. Pusztán definiálja az XML-t karakterláncként, és alakítsa át XML-típussá, ahogyan az imént tettük a Get-Content cmdletet a fájlok esetében. Íme a minta XML-fájl egy része, amelyben csak két könyv van:

Az XML elérése XPath-tal

Mivel a fájl be van töltve egy XmlDocument objektumba, ezután XPath-tal navigálhatunk az XML-fában. Egy csomóponthalmaz kiválasztásához használja a SelectNodes metódust:

$xdoc.SelectNodes(“//author”)

#text

Gambardella, Matthew

Ralls, Kim

Corets, Eva

Corets, Eva

Randall, Cynthia

Thurman, Paula

Knorr, Stefan

Kress, Peter

O’Brien, Tim

O’Brien, Tim

Galos, Mike

Vagy a SelectSingleNode használatával csak egy csomópontot adhatunk vissza:

$xdoc.SelectSingleNode(“//book”)

id : bk102

author : Ralls, Kim

title : Midnight Rain

genre : Fantasy

ár : 5.95

kiadás dátuma : 2000-12-16

leírás : Egy volt építésznő vállalati zombikkal,

egy gonosz varázslónővel és saját gyermekkorával küzd, hogy a világ királynője

legyen.

Az első példában észrevehető, hogy vannak duplikációk. Tegyük fel, hogy ehelyett a katalógusban szereplő egyedi szerzők listáját szeretnénk. Azt gondolhatnánk, hogy valami olyasmi …

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

…működne, de valójában csak az első szerző nevét adja vissza. Ahhoz, hogy megértse, miért nem sikerült, jobban meg kellene értenie az XML-dokumentumok szerkezetét. Az első példa valójában egy szövegcsomópontok listáját adta vissza (azaz nem egy szöveglistát), és az egyedi szűrő ezen a listán dolgozik, az elemtípus egyediségét keresve. Mivel a gyűjtemény összes eleme szövegcsomópont, és így mind azonos elemtípusú, ezért az elsőn túli összes csomópont duplikátumnak minősül. Az eredmény az, hogy csak az elsőt kapjuk vissza.

Az, amit valójában keresünk, az az egyes szerzői csomópontok string értéke. A szerző csomópontból először a szöveg csomópontját (az első és egyetlen gyermekét) kell elérnie, majd ennek a szöveg csomópontnak az értékét (a következő példában az A sor). Alternatívaként használhat egy valamivel rövidebb kifejezést az InnerText tulajdonsággal (B sor). Egy további variáció a Select-Xml cmdletet használja, amely elkerüli a metódushívást, és így bizonyos értelemben jellegzetesen PowerShell-megközelítés (C sor). Mindhárom sor ugyanazt az eredményt adja vissza.

A SelectNodes és a SelectSingleNode együttesen a Select-Xml paranccsal egyenértékű funkcionalitást biztosít. Mindkettő támogatja a névtereket, amelyeket még nem említettem. A két módszer mindkettő egy XmlNamespaceManager-t fogad el opcionális második paraméterként, míg a Select-Xml cmdlet egy opcionális Namespace paramétert fogad el, amely egy hash-táblában adja meg a névtereket.

A SelectSingleNode egy XmlNode-ot, a SelectNodes pedig egy XmlNodeList-et ad vissza. A Select-Xml viszont egy SelectXmlInfo objektumot (vagy ezek tömbjét) adja vissza, a Node tulajdonsága pedig hozzáférést biztosít a mögöttes csomóponthoz. Az imént bemutatott példa szemlélteti ezeket a különbségeket.

Az XML objektumként való elérése

A PowerShell az előző szakaszban bemutatott XmlDocument objektummal megegyezően dinamikus objektumtámogatást is nyújt az XML-adatokhoz: Ez lehetővé teszi, hogy az XML-adatokat első osztályú PowerShell-objektumokként érje el, amihez nem szükséges sem XPath-szelektor, sem az olyan dolgok részleteinek ismerete, mint az XML-csomópontok, értékek vagy szövegcsomópontok. Ráadásul az XML-séma azonnali, dinamikus Intellisense funkciót kap az XML-adatok betöltésekor! A 2. ábra ezt szemlélteti a PowerShell ISE esetében, ahol a PowerShell natív tokenjeihez hasonlóan kiválasztási lehetőségeket és szókiegészítést is kap. Figyelje meg különösen az alsó bővítésnél, hogy azt keresi, amit a tulajdonságnévben bárhol beírt, nem csak az első karaktertől kezdve: Az Intellisense itt egy dátum tulajdonságot találna, függetlenül attól, hogy a neve published_date vagy releaseDate vagy date_of_publication. Vegye figyelembe, hogy a PowerShell V2-ben vagy V3-ban, valamint a PowerShell ISE-ben vagy a PowerShell konzolon elérhető a word completion. A kiválasztási lehetőségek azonban csak a PowerShell ISE-ben állnak rendelkezésre a V3-ban.

2. ábra Automatikus intellisense egy XML-dokumentum betöltésekor

Íme néhány példa arra, hogy az XML valóban automatikusan átalakul PowerShell-objektummá:

$xdoc

xml catalog

– —

version=”1.0″ catalog

$xdoc.catalog

book

{book, book, book, book, book, book…}

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

id author title title genre price publish_date description

– — — — — — —- —- —-

bk101 Gambardella, Matthew XML Developer’s Guide Computer 44.95 2000-10-01 Egy alapos áttekintés …

bk102 Ralls, Kim Midnight Rain Fantasy 5.95 2000-12-16 Egy korábbi építész…

bk103 Corets, Eva Maeve Ascendant Fantasy 5.95 2000-11-17 Az összeomlás után…

bk104 Corets, Eva Oberon’s Legacy Fantasy 5.95 2001-03-10 A posztapokalipszis utáni…

bk105 Corets, Eva Az elsötétített Grál fantasy 5.95 2001-09-10 A két lány…

bk106 Randall, Cynthia Szerelmes madarak romantika 4.95 2000-09-02 Amikor Carla találkozik …

bk107 Thurman, Paula Splish Splash romantika 4.95 2000-11-02 Egy mélytengeri búvár …

bk108 Knorr, Stefan Creepy Crawlies Horror 4.95 2000-12-06 Egy antológia h…

bk109 Kress, Peter Paradox Lost Science Fiction 6.95 2000-11-02 Egy véletlen baleset után…

bk110 O’Brien, Tim Microsoft .NET: The Prog… Computer 36.95 2000-12-09 Microsoft’s .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

szerző : Corets, Eva

title : Maeve Ascendant

genre : Fantasy

ár : 5.95

publish_date : 2000-11-17

description : A nanotechnológiai

társadalom összeomlása után Angliában a fiatal túlélők megalapozzák

egy új társadalom

$xdoc.catalog.book.author

Randall, Cynthia

$xdoc.catalog.book.id

bk106

Vegyük észre, hogy a dokumentum összes XML-csomópontját szabványos PowerShell-tulajdonságokká alakítjuk, függetlenül attól, hogy egy csomópontnak vannak-e gyermekei (pl. catalog) vagy egy levélcsomópont (pl. price), illetve hogy egy levélcsomópont egy elem (pl. author) vagy egy attribútum (pl. id). Különösen (ahogy a fenti két utolsó példa is mutatja), az elemértékeket és az attribútumértékeket pontosan ugyanúgy kezeljük a szabványos “pont” jelöléssel.

Az XPath és az objektum megközelítések összehasonlítása

Melyik megközelítés a jobb az XML-adatok eléréséhez? Az 1. táblázat segít megválaszolni ezt a kérdést. Az objektumos megközelítés általában tömörebb (pl. 3. sor), de nem mindig (4. sor). Az XPath azonban kifejezőbb, mivel lehetővé teszi néhány olyan szelektor megadását, amely az objektumjelöléssel nem lehetséges (7. sor). A PowerShell saját képességei azonban könnyen betölthetik ezt a hiányt, ha objektumjelölést használunk (8. sor).

1. táblázat Az XPath és az objektumszelekciós megközelítések összehasonlítása az XML-hozzáféréshez.

XML-adatok módosítása vagy létrehozása

Az XML-szelektorok előző részekből származó megismerése alapján egy XML-dokumentum módosítása meglehetősen egyszerű, mivel az XML-szelektorok (akár XPath, akár objektum) L-értékek, azaz írhatunk rájuk, és olvashatunk is belőlük! Így ezek bármelyike módosítja a 6. könyv szerzőjét:

1
2

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

Nagyon gyakran előfordulhat, hogy van egy meglévő XML fájlunk, ahol egy vagy több csomópont értékét szeretnénk megváltoztatni. Valószínűleg be szeretné olvasni a fájlt, módosítani az adatokat, majd visszamenteni a fájlt ugyanazon a néven. Az első két lépést már látta; a harmadik lépést az XmlDokumentum Save metódusával hajtja végre. Mindezeket összerakva tehát ezt az alapkódot kapjuk:

Ez a kód jól fut – kivéve, hogy legtöbbször úgy fog tűnni, mintha nem sikerült volna! Ez az egyszerű kódrészlet egy látszólag jelentéktelen, de fontos PowerShell-fogalmat szemléltet; ennek nem ismerete számos blogbejegyzéshez vezetett, amelyekben azt állították, hogy ez a PowerShell hibája. A probléma az, hogy a munkakönyvtár és a PowerShell helye nem ugyanaz. A fenti kód remekül beolvassa a fájlt, remekül módosítja az adatokat, de nem feltétlenül menti el az új fájlt oda, ahová várjuk. A Get-Content, mivel egy PowerShell cmdlet, a PowerShell-helyhez viszonyított fájl elérési útját látja. Az XmlDocument.Save módszer viszont a PowerShell-folyamat munkakönyvtárához viszonyított fájl elérési útvonalát látja, mivel ez a módszerhívás a PowerShell-en kívül van. Ha az aktuális PowerShell munkamenetben nem hajtotta végre a Set-Location (vagy annak alias cd) parancsot, akkor mindkettő ugyanarra a könyvtárra mutat. Ennek megerősítéséhez hajtsa végre ezt a két utasítást:

1
2

Get-Location # megjeleníti a PowerShell helyét
::CurrentDirectory # megjeleníti a munkakönyvtárat

A legbiztonságosabb megközelítés tehát az abszolút elérési utak használata, hogy teljesen elkerüljük ezt a problémát. További részletekért lásd Alex Angelopoulos Why the PowerShell Working Directory and the PowerShell Location Aren’t One in the Same című cikkét.

XML-adatok hozzáadása

Új csomópontok hozzáadása az XML-dokumentumhoz csak egy kicsit több munkát igényel, mint egy meglévő csomópont értékének módosítása. Az egyik általam kedvelt megközelítés Tobias Weltner Write, Add and Change XML Data című blogbejegyzéséből származik: vegyünk egy létező csomópontot a létrehozni kívánt típusból, készítsünk egy másolatot a csomópontról, és módosítsuk a másolatot az új adatokkal, végül a másolt csomópontot illesszük be az XML-be az eredeti testvéreként. Ezt a könyvkatalógus példánkra alkalmazva ez a kódrészlet létrehoz egy új könyv csomópontot, és hozzáadja a gyűjtemény végéhez:

Ha az új könyvet egy másik helyre, mondjuk a 3. könyv után szeretné hozzáadni, használja az InsertAfter-t az AppendChild helyett:

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

(Az InsertAfter metódus neve meghazudtolja, hogy nem csak csomópontokat ad hozzá, hanem csomópontokat is tud mozgatni! A metódus ellenőrzi, hogy a hozzáadni kívánt csomópont szerepel-e már a dokumentumban. Ha igen, akkor áthelyezi a megadott új helyre. Így amikor valóban csomópontokat akarunk másolni, a fentebb bemutatott Clone metódussal kell kezdenünk.)

Az XML-adatok .NET metódusokkal való kezelésének további feltárását lásd: XML-adatok feldolgozása a DOM-modell használatával az MSDN-en.

Az XML használata objektumok szerializálására

A PowerShell egyszerű módot biztosít az objektumok tartósítására az Export-Clixml használatával bármely objektum szerializálására és XML-fájlban való tárolására, valamint az Import-Clixml használatával az objektum XML-ből való visszaállítására. Az XML használatával a legtöbb más szerializációs technikával ellentétben az objektum integritása megmarad: egy objektum XML-ből történő visszaállításakor az összes tulajdonság megfelelően tipizált, ahogy maga a szülőobjektum is, így az eredeti objektum összes metódusa elérhető a regenerált objektumon is. Az Export-Clixml használatához egyszerűen csak csővezetékbe kell helyezni egy tetszőleges objektumgyűjteményt, és meg kell adni egy célfájlt. Íme egy egyszerű példa, amely megmutatja, hogy a Get-ChildItem kimenete, egy FileSystemInfo objektumok gyűjteménye regenerálódik:

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.