Redgate Hub

  • Přístup k XML pomocí XPath.
  • Přístup k XML jako k objektům.
  • Srovnání přístupů XPath a objektů
  • Modifikace nebo vytváření dat XML
    • Přidávání dat XML
    • Použití XML pro serializaci objektů
  • Úvod

    Jako u každého vysokoúrovňového jazyka je the datajádrem PowerShellu. V případě prostředí PowerShell se jedná o převod externích dat na objekty prostředí PowerShell a naopak. Toto je druhý ze série článků, který vám ukáže, jak importovat téměř všechny běžné datové formáty, se kterými se pravděpodobně setkáte, a jak do některých z nich také exportovat. První článek této série, Základy práce s daty v prostředí PowerShell: se věnuje různým textovým formátům, od souborů s pevnou šířkou, proměnlivou šířkou a oříznutou pravou stranou až po CSV, seznamy vlastností, soubory INI a data JSON, a v závěru se zabývá importem a exportem do aplikace Excel. Zde se soustředíme na to, jak z XML vytěžit maximum.

    Přístup k datům XML v prostředí PowerShell

    Pro práci s daty XML v prostředí PowerShell existují dvě vestavěné techniky: přístup XPath a přístup s bodovými poznámkami objektů. Popíšeme a porovnáme tyto dva přístupy a vyzkoušíme je na několika ukázkách XML. Pro usnadnění budou všechny příklady kódu používat tento vzorový soubor XML z MSDN. Obrázek 1 ukazuje reprezentaci schématu, na němž je soubor založen, ve stručném formátu (zejména ve srovnání se čtením surového souboru XSD!), a to díky nástroji Visual Studio XML Schema Explorer. Z obrázku zjistíte, že soubor XML je katalogem, který obsahuje kolekci knih. Každá kniha má sedm charakteristik, z nichž šest je podřízených elementů a jedna je podřízený atribut.

    Obrázek 1 Schéma pro ukázkový soubor XML společnosti Microsofto:p>

    Pro načtení tohoto ukázkového souboru XML můžete použít některý z těchto způsobů:

    pokud byste raději experimentovali s okamžitými daty XML než načítali soubor XML do dokumentu XmlDocument, je to jednoduché. Stačí definovat váš XML jako řetězec a převést jej na typ XML, jak jsme to právě udělali s rutinou Get-Content pro soubory. Zde je část ukázkového souboru XML s pouhými dvěma knihami:

    Přístup k souboru XML pomocí příkazu XPath

    Po načtení souboru do objektu XmlDocument pak můžete procházet stromem XML pomocí příkazu XPath. Pro výběr množiny uzlů použijte metodu SelectNodes:

    $xdoc.SelectNodes(„//autor“)

    #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

    Nebo použijte SelectSingleNode pro vrácení pouze jednoho uzlu:

    $xdoc.SelectSingleNode(„//book“)

    id : bk102

    autor : Ralls, Kim

    název : Půlnoční déšť

    žánr : Fantasy

    cena : 5.95

    datum vydání : 2000-12-16

    popis : Bývalá architektka bojuje proti korporátním zombie,

    zlé čarodějnici a vlastnímu dětství, aby se stala královnou

    světa.

    Všimněte si, že v první ukázce jsou duplikáty. Předpokládejme, že místo toho chcete mít v katalogu seznam jedinečných autorů. Mohlo by vás napadnout něco jako …

    1
    $xdoc.SelectNodes(„//autor“) | select -Unique

    …by fungovalo, ale ve skutečnosti vrací jen jméno prvního autora. Abyste pochopili, proč se to nepodařilo, museli byste více rozumět struktuře dokumentů XML. První příklad ve skutečnosti vrátil seznam textových uzlů (tj. nikoli seznam textu) a unikátní filtr pracuje s tímto seznamem a hledá jedinečnost typu prvku. Protože všechny položky v kolekci jsou textové uzly, a tudíž jsou všechny stejného typu prvku, jsou proto všechny uzly za prvním považovány za duplicitní. Výsledkem je, že je vrácen pouze první z nich.

    To, co ve skutečnosti hledáte, je řetězcová hodnota každého autorského uzlu. Z uzlu autor musíte nejprve přistupovat k jeho textovému uzlu (jeho prvnímu a jedinému potomkovi) a poté k hodnotě tohoto textového uzlu (řádek A v dalším příkladu). Alternativně můžete použít o něco kratší výraz s vlastností InnerText (řádek B). Jedna z dalších variant využívá rutinu Select-Xml, která se vyhýbá volání metody, a je tak v jistém smyslu výraznějším přístupem prostředí PowerShell (řádek C). Všechny tři řádky vracejí stejný výsledek.

    SelectNodes a SelectSingleNode dohromady poskytují ekvivalentní funkci jako Select-Xml. Obě podporují jmenné prostory, o kterých jsem se zatím nezmínil. Obě metody přijímají jako druhý nepovinný parametr XmlNamespaceManager, zatímco rutina Select-Xml přijímá nepovinný parametr Namespace, který určuje vaše jmenné prostory v hashovací tabulce.

    SelectSingleNode vrací XmlNode a SelectNodes vrací XmlNodeList. Naproti tomu Select-Xml vrací objekt SelectXmlInfo (nebo jejich pole) a jeho vlastnost Node poskytuje přístup k základnímu uzlu. Tyto rozdíly ilustruje právě uvedený příklad.

    Přístup k XML jako k objektům

    Pomocí stejného objektu XmlDocument z minulé části poskytuje prostředí PowerShell také dynamickou objektovou podporu pro data XML: To umožňuje přistupovat k datům XML jako k objektům první třídy prostředí PowerShell, což nevyžaduje ani selektor XPath, ani znalost detailů takových věcí, jako jsou uzly XML, hodnoty nebo textové uzly. Navíc při načítání dat XML získáte okamžitou dynamickou intellisense schématu XML! Obrázek 2 to ilustruje pro PowerShell ISE, kde získáte jak volby výběru, tak doplňování slov, stejně jako u nativních tokenů PowerShell. Všimněte si zejména v dolní části rozšíření, že hledá, co jste zadali kdekoli v názvu vlastnosti, nejen od prvního znaku: Intellisense by vám zde našla vlastnost datum, ať už se jmenuje published_date nebo releaseDate nebo date_of_publication. Všimněte si, že doplňování slov máte k dispozici v prostředí PowerShell V2 nebo V3 a v konzole PowerShell ISE nebo PowerShell. Volby výběru jsou však k dispozici pouze v PowerShell ISE ve verzi V3.

    Obrázek 2 Automatická intellisense při načtení dokumentu XML

    Zde je několik příkladů, které ukazují, že XML je skutečně automaticky převedeno na objekty PowerShell:

    $xdoc

    xml catalog

    – —

    version=“1.0″ catalog

    $xdoc.catalog

    book

    {book, book, book, book…}

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

    id autor název žánr cena datum vydání popis

    – — — — — —- —-

    bk101 Gambardella, Matthew XML Developer’s Guide Computer 44.95 2000-10-01 Podrobný pohled na …

    bk102 Ralls, Kim Půlnoční déšť Fantasy 5.95 2000-12-16 Bývalá architektka, která se v minulosti věnovala …

    bk103 Corets, Eva Maeve Ascendant Fantasy 5.95 2000-11-17 Po kolapsu …

    bk104 Corets, Eva Oberonův odkaz Fantasy 5.95 2001-03-10 V postapokalypse…

    bk105 Corets, Eva Zapadlý grál Fantasy 5.95 2001-09-10 Dvě dcery…

    bk106 Randall, Cynthia Milenci ptáci Romance 4.95 2000-09-02 Když Carla potká …

    bk107 Thurman, Paula Splash Splash Romance 4.95 2000-11-02 Hlubokomořský potápěč …

    bk108 Knorr, Stefan Creepy Crawlies Horror 4.95 2000-12-06 Antologie h…

    bk109 Kress, Peter Paradox Lost Science Fiction 6.95 2000-11-02 Po nechtěném …

    bk110 O’Brien, Tim Microsoft .NET: Počítač 36.95 2000-12-09 Microsoft .NET …

    bk111 O’Brien, Tim MSXML3: A Comprehensive … Počítač 36.95 2000-12-01 The Microsoft MSX…

    bk112 Galos, Mike Visual Studio 7: A Compr… Počítač 49. Vychází v češtině.95 2001-04-16 Microsoft Visual …

    $xdoc.catalog.book

    id : bk103

    autor : Corets, Eva

    název : Maeve Ascendant

    žánr : Fantasy

    cena : 5.95

    datum vydání : 2000-11-17

    popis : Po zhroucení nanotechnologické

    společnosti v Anglii kladou mladí přeživší

    základy nové společnosti

    $xdoc.catalog.book.author

    Randall, Cynthia

    $xdoc.catalog.book.id

    bk106

    Všimněte si, že všechny uzly XML v dokumentu jsou převedeny na standardní vlastnosti PowerShellu, ať už má uzel potomky (např. catalog) nebo je listovým uzlem (např. price), nebo je listovým uzlem element (např. author) nebo atribut (např. id). Zejména (jak ukazují poslední dva výše uvedené příklady), s hodnotami prvků a atributů se zachází naprosto stejně pomocí standardního „tečkového“ zápisu.

    Srovnání XPath a objektového přístupu

    Který přístup je lepší pro přístup k datům XML? Na tuto otázku vám pomůže odpovědět tabulka 1. Objektový přístup je obvykle stručnější (např. řádek 3), ale ne vždy (řádek 4). XPath je však expresivnější v tom smyslu, že umožňuje specifikovat některé selektory, které objektový zápis neumožňuje (řádek 7). Vlastní možnosti prostředí PowerShell však mohou tuto mezeru snadno zaplnit při použití objektové notace (řádek 8).

    Tabulka 1 Porovnání přístupů k přístupu k XML pomocí selektorů XPath a objektových selektorů.

    Úprava nebo vytváření dat XML

    Podle znalosti selektorů XML z předchozích částí je úprava dokumentu XML poměrně jednoduchá, protože selektory XML (ať už XPath nebo objektové) jsou L-hodnoty, tj. lze do nich zapisovat i z nich číst! Tedy kterýkoli z těchto případů upraví autora 6. knihy:

    1
    2

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

    Dosti často se může stát, že máte existující soubor XML, ve kterém chcete změnit jednu hodnotu nebo hodnotu uzlu. Pravděpodobně budete chtít soubor načíst, upravit data a uložit soubor zpět pod stejným názvem. První dva kroky jste viděli; třetí krok se provádí pomocí metody Save na XmlDocument. Dáte-li je tedy všechny dohromady, získáte tento základní kód:

    Tento kód běží dobře – až na to, že se většinou bude zdát, že selhal! Tento jednoduchý kousek kódu ilustruje zdánlivě drobný, ale důležitý poznatek prostředí PowerShell; jeho neznalost vedla k mnoha příspěvkům na blogu, podle nichž se jedná o chybu v prostředí PowerShell. Problém spočívá v tom, že pracovní adresář a umístění PowerShellu nejsou totéž. Výše uvedený kód v pořádku načte soubor, v pořádku upraví data, ale nemusí nutně uložit nový soubor tam, kde ho očekáváte. Get-Content, jakožto rutina prostředí PowerShell, vidí cestu k souboru relativně k umístění prostředí PowerShell. Naproti tomu metoda XmlDocument.Save vidí cestu k souboru relativně k pracovnímu adresáři procesu PowerShell, protože volání této metody je mimo prostředí PowerShell. Pokud jste v aktuální relaci prostředí PowerShell neprovedli funkci Set-Location (nebo její alias cd), obě ukazují na stejný adresář. Chcete-li to potvrdit, proveďte tyto dva příkazy:

    1
    2

    Get-Location # zobrazí umístění PowerShell
    ::CurrentDirectory # zobrazí pracovní adresář

    Nejbezpečnější je tedy používat absolutní cesty, abychom se tomuto problému zcela vyhnuli. Více informací najdete v článku Alexe Angelopoulose Why the PowerShell Working Directory and the PowerShell Location Aren’t One in the Same.

    Přidávání dat XML

    Přidání nových uzlů do dokumentu XML vyžaduje jen o něco více práce než úprava hodnoty existujícího uzlu. Jeden z přístupů, který se mi líbí, pochází z příspěvku Tobiase Weltnera na blogu Zápis, přidání a změna dat XML: vezměte existující uzel typu, který chcete vytvořit, vytvořte kopii tohoto uzlu a upravte kopii svými novými daty a nakonec vložte zkopírovaný uzel do svého XML jako sourozence původního. Pokud to aplikujeme na náš příklad katalogu knih, tento kousek kódu vytvoří nový uzel knihy a přidá jej na konec kolekce:

    Pokud si přejete přidat novou knihu na jiné místo, například za třetí knihu, použijte InsertAfter místo AppendChild:

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

    (Název metody InsertAfter popírá skutečnost, že metoda nejen přidává uzly, ale může uzly i přesouvat! Metoda kontroluje, zda se uzel, který žádáte přidat, již v dokumentu nachází. Pokud ano, přesune jej na zadané nové místo. Pokud tedy chcete uzly kopírovat, musíte začít metodou Clone, jak je znázorněno výše.)

    Další výklad o manipulaci s daty XML pomocí metod .NET najdete v článku Zpracování dat XML pomocí modelu DOM na MSDN.

    Použití XML pro serializaci objektů

    PowerShell poskytuje snadný způsob persistence objektů pomocí Export-Clixml pro serializaci libovolného objektu a jeho uložení do souboru XML a Import-Clixml pro obnovení objektu z XML. Při použití XML je na rozdíl od většiny ostatních serializačních technik zachována integrita objektu: při obnovení objektu z XML jsou všechny vlastnosti správně typovány, stejně jako samotný nadřazený objekt, takže všechny metody původního objektu jsou dostupné i na obnoveném objektu. Chcete-li použít Export-Clixml, jednoduše k němu připojte libovolnou kolekci objektů a zadejte cílový soubor. Zde je jednoduchý příklad, který ukazuje, že výstup z Get-ChildItem, kolekce objektů FileSystemInfo, je regenerován:

    Napsat komentář

    Vaše e-mailová adresa nebude zveřejněna.