- PowerShell で XML データにアクセスする
- XPath で XML にアクセスする。
- オブジェクトとして XML にアクセスする。
- XPath とオブジェクトのアプローチの比較
- XML データの変更または作成
- XML データの追加
- オブジェクトシリアライズに XML を使用
導入
他の高級言語同様、
the data
は PowerShell の中核をなしています。 PowerShell の場合、これは外部データを PowerShell オブジェクトに、またはその逆に変換することに集約されます。 この記事は、一般的なデータ形式のほとんどすべてをインポートする方法と、そのうちのいくつかにエクスポートする方法を紹介する連載の第2回目です。 最初の記事は、PowerShellのデータの基本です。 ファイルベースのデータ」では、固定幅、可変幅、右肩下がりのファイルから、CSV、プロパティリスト、INIファイル、JSONデータまで、さまざまなテキスト形式を取り上げ、最後にExcelへのインポートとエクスポートを扱っています。 PowerShell で XML データにアクセスするPowerShell で XML データを扱うには、XPath アプローチとオブジェクト ドット ノテーション アプローチという 2 つのビルトイン テクニックがあります。 ここでは、これら 2 つのアプローチを説明、比較し、いくつかのサンプル XML でそれらを試してみます。 便宜上、すべてのコード例では、MSDNにあるこのサンプルXMLファイルを使用します。 図 1 は、Visual Studio の XML Schema Explorer を使用して、このファイルの基礎となるスキーマを簡潔な形式で表したものです(特に生の XSD ファイルを読む場合と比較すると!)。 この図から、この XML ファイルが書籍のコレクションを含むカタログであることがわかります。 各書籍は 7 つの特性を持ち、そのうち 6 つは子要素、1 つは子属性です。
Figure 1 Schema for Microsoft’s sample XML fileo:p>
このサンプル XML ファイルの読み込みには、これらのいずれかを使用できます:
もしあなたが XML ファイルを XmlDocument に読み込むのではなく、即時 XML データで実験したい場合は、それは簡単に行なえます。 XML を文字列として定義し、ファイル用の Get-Content コマンドレットで行ったように XML タイプにキャストするだけです。 以下は、2 つのブックだけを含むサンプル XML ファイルの一部です。
Accessing XML with XPath
XmlDocument オブジェクトにファイルが読み込まれると、XPath で XML ツリーをナビゲートすることが可能になります。 ノード セットを選択するには、SelectNodes メソッドを使用します:
$xdoc.SelectNodes(“//author”)
#text
—
Gambardella, Matthew
Ralls, Kim
Corets, Eva
Corets, Eva
Randall.XML.XML.Text
Corts, Eva
Corets, Eva
Thurman, Paula
Knorr, Stefan
Kress, Peter
O’Brien, Tim
O’Brien, Tim
Galos, Mike
または SelectSingleNode で1ノードのみ返送します。
$xdoc.SelectSingleNode(“//book”)
id : bk102
author : Ralls, Kim
title : Midnight Rain
genre : ファンタジー
価格: 5.95
publish_date : 2000-12-16
description : 元建築家が世界の女王になるために企業のゾンビ、
悪い魔術師、そして自分の子供時代と戦う
最初の例で重複していることに注意してください。 代わりに、カタログにあるユニークな著者のリストが欲しいとします。 あなたは、次のようなものを考えるかもしれません…
1$xdoc.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.SelectNodes(“//author”) | select -Unique…とすると動作しますが、実際には最初の著者の名前だけが返されることになります。 なぜ失敗したかを理解するには、XML文書の構造についてもっと理解する必要があるでしょう。 最初の例は実際にはテキストノードのリスト(つまりテキストのリストではない)を返し、ユニークフィルタはそのリストに対して、要素タイプの一意性を探すために操作しています。 コレクション内のすべての項目はテキストノードであり、したがってすべて同じ要素タイプであるため、最初のノード以降のすべてのノードは重複しているとみなされます。 その結果、最初の 1 つだけが返されます。
本当に必要なのは、各著作者ノードの文字列の値です。 author ノードから、まずその text ノード (その最初で唯一の子) にアクセスし、次にその text ノードの値 (次の例の A 行) にアクセスする必要があります。 また、InnerTextプロパティを使って、もう少し短い式を使うこともできます(B行目)。 もう一つのバリエーションは、Select-Xmlコマンドレットを使用します。これは、メソッドの呼び出しを避けるため、ある意味で、よりPowerShellらしいアプローチです(C行)。 3 行とも同じ結果を返します。
SelectNodes と SelectSingleNode を組み合わせると、Select-Xml と同等の機能を使用できます。 両方とも、まだ言及していない名前空間をサポートします。 Select-Xml コマンドレットは、オプションの Namespace パラメータを受け取り、ハッシュ テーブルでネームスペースを指定します。 一方、Select-Xml は SelectXmlInfo オブジェクト (またはその配列) を返し、その Node プロパティは基になるノードへのアクセスを提供します。
Accessing XML as Objects
前のセクションと同じ XmlDocument オブジェクトにより、PowerShell は XML データに対する動的オブジェクト サポートも提供します。 これにより、XML データにファーストクラスの PowerShell オブジェクトとしてアクセスでき、XPath セレクタや、XML ノード、値、またはテキスト ノードなどの詳細に関する知識は必要ありません。 さらに、XMLデータを読み込むと、XMLスキーマの動的なIntellisenseが即座に表示されます。 図 2 は PowerShell ISE の例で、PowerShell ネイティブトークンのように、選択と単語補完の両方が得られます。 特に下の拡大図では、最初の文字からだけでなく、プロパティ名内のどこに何を入力したかを検索していることに注目してください。 Intellisenseは、published_date、releaseDate、date_of_publicationのいずれの名前でも、ここで日付プロパティを見つけるでしょう。 PowerShell V2やV3、PowerShell ISEやPowerShellコンソールでは、単語補完が利用できることに注意してください。 しかし、選択項目は V3 の PowerShell ISE でのみ利用できます。
Figure 2 XML ドキュメントの読み込み時の自動インテリセンス
XML が確かに PowerShell オブジェクトに自動変換されることを示す例をいくつか紹介します:
$xdoc
xml catalog
– —
バージョン = “1.0″ catalog
$xdoc.catalog
book
—
{book, book, book, book…}.
$xdoc.catalog.book | Format-Table -AutoSize
id author title genre price publish_date description
– — — —- —-
bk101 Gambardella, Matthew XML Developer’s Guide Computer 44.X.D.C. (共著)
Mathew X.D. (共著)95 2000-10-01 徹底的な調査により、…
bk102 Ralls, Kim Midnight Rain Fantasy 5.95 2000-12-16 元建築士で、…
bk103 Corets, Eva Maeve Ascendant Fantasy 5.95 2000-11-17 崩壊の後に…
bk104 Corets, Eva Oberon’s Legacy Fantasy 5.95。95 2001-03-10 ポスト・アポカリプスの中で…
bk105 Corets, Eva The Sundered Grail Fantasy 5.95 2001-09-10 二人の娘…
bk106 Randall, Cynthia Lover Birds Romance 4.95 2000-09-02 カーラが出会う…
bk107 Thurman, Paula Splish Splash Romance 4.95 2000-09-02 バーバラが出会った…
bk106 Cynthia Lover Birds Romance 5.95 2001-09-10 バーバラは…95 2000-11-02 深海潜水士が…
bk108 Knorr, Stefan Creepy Crawlies Horror 4.95 2000-12-06 An anthology of h…
bk109 Kress, Peter Paradox Lost Science Fiction 6.95 2000-11-02 誤って…
bk110 O’Brien, Tim Microsoft .NET.NET: コンピュータ 36.95 2000-12-09 Microsoft’s .NET …
bk111 O’Brien, Tim MSXML3: A Comprehensive … コンピュータ 36.95 2000-12-01 The Microsoft MSX…
bk112 Galos, Mike Visual Studio 7: A Compr… コンピュータ 49.95.95 2001-04-16 Microsoft Visual …
$xdoc.catalog.book
id : bk103
著者 : Corets, Eva
タイトル : Maeve Ascendant
ジャンル…
BOOK.JP>
BOOK.JP>
ジャンル..: ファンタジー
価格: 5.95
publish_date : 2000-11-17
description : イギリスのナノテクノロジー
社会が崩壊した後、若い生存者は新しい社会の
基礎を築く
$xdoc.catalog.book.author
Randall,Cynthia
$xdoc.Catalog.Book
bk106
ノードが子を持つか(例えば catalog)、葉ノードであるか(例えば price)、葉ノードが要素(例えば author)か属性(例えば id)か、ドキュメント内のすべての XML ノードは標準PowerShellプロパティへ変換されることに注意してください。 特に (上記の最後の 2 つの例が示すように)、要素値と属性値は標準の「ドット」表記でまったく同じように扱われます。
Comparison of XPath and Object Approaches
XML データにアクセスするにはどのアプローチが良いのでしょうか。 表 1 はこの質問に対する答えの一助となります。 オブジェクト アプローチは通常より簡潔ですが (例: 行 3)、常にそうとは限りません (行 4)。 しかし、XPathは、オブジェクト記法では不可能ないくつかのセレクタを指定できる点で、より表現力が豊かです(7行目)。 しかし、オブジェクト記法を使用する場合、PowerShell 自身の機能でこのギャップを簡単に埋めることができます (8行目)。
Table 1 XML アクセスにおける XPath とオブジェクト セレクタのアプローチの比較
XML データの変更または作成
これまでのセクションでの XML セレクタを理解すると、XML 文書を修正するのは非常に簡単です。 つまり、XML セレクタ (XPath またはオブジェクト) は L 値であるため、セレクタに書き込むことも、セレクタから読み取ることもできるのです!したがって、これらのいずれかが 6 番目の本の著者を変更します:
12$xdoc.SelectSingleNode(“//book/author”).InnerText = ‘jones’$xdoc.catalog.book.author = ‘smith’かなり頻繁に、既存の XML ファイルで値を変更することがあります。 おそらく、ファイルを読み取り、データを変更し、同じ名前でファイルを保存し直したいと思うことでしょう。 最初の2つのステップを見ていただきましたが、3番目のステップはXmlDocumentのSaveメソッドで行われます。 これらをすべてまとめると、次のような基本的なコードが得られます。
このコードは正常に実行できますが、ほとんどの場合、失敗しているように見えます! この単純なコードは、一見マイナーだが重要な PowerShell の概念を示しています。このことを知らないために、PowerShell のバグであると主張するブログ投稿が多くなっています。 問題は、作業ディレクトリとPowerShellのロケーションが同じではないことです。 上記のコードは、ファイルを読み、データを修正しますが、必ずしも期待する場所に新しいファイルを保存するとは限りません。 Get-Contentは、PowerShellコマンドレットであるため、PowerShellの場所からの相対的なファイルパスが表示されます。 一方、XmlDocument.Save メソッドは、PowerShell プロセスの作業ディレクトリからの相対的なファイルパスが表示されますが、これはこのメソッド呼び出しが PowerShell の外部にあるためです。 現在のPowerShellセッションでSet-Location(またはそのエイリアスであるcd)を実行していない場合、両方とも同じディレクトリを指します。 これを確認するには、次の 2 つのステートメントを実行します:
12Get-Location # 表示 PowerShell 位置::CurrentDirectory # 作業ディレクトリを表示もっとも安全な方法は、この問題を完全に避けるために絶対パスを使用することです。 詳細は、Alex Angelopoulos の記事 Why the PowerShell Working Directory and the PowerShell Location Aren’t One in the Same を参照してください。
Adding XML Data
XML ドキュメントに新しいノードを追加するには、既存のノードの値を変更するより少し多くの作業が必要です。 作成したいタイプの既存のノードを取得し、そのノードのコピーを作成し、そのコピーを新しいデータで変更し、最後にコピーしたノードを元のノードの兄弟として XML に挿入するのです。 これを書籍カタログの例に当てはめると、次のコードは新しい書籍ノードを作成し、それをコレクションの末尾に追加します。
別の場所、たとえば 3 冊目の本の後に新しい本を追加したい場合、AppendChild の代わりに InsertAfter を使用します。catalog.InsertAfter($book,$xdoc.catalog.book)
(InsertAfter という名前の通り、ノードを追加するだけでなく、ノードの移動も可能です!) (このメソッドは、”add” という名前の通り、ノードを追加するだけではありません。 このメソッドは、追加しようとしているノードがすでにドキュメント内にあるかどうかを確認します。 もしそうなら、指定された新しい場所に移動します。 したがって、ノードをコピーする場合は、上記のように Clone メソッドで開始する必要があります。
.NET のメソッドによる XML データの操作に関する詳細については、「MSDN の DOM モデルによる XML データの処理」を参照してください。 XML では、他の多くのシリアライズ技術とは異なり、オブジェクトの整合性が保たれます。XML からオブジェクトを復元する際、すべてのプロパティは親オブジェクトと同様に適切に型付けされ、元のオブジェクト上のすべてのメソッドは再生成されたオブジェクトでも利用可能です。 Export-Clixmlを使用するには、任意のオブジェクトコレクションをパイプで接続して、宛先ファイルを指定するだけです。 以下は、FileSystemInfo オブジェクトのコレクションである Get-ChildItem からの出力が再生成されることを示す簡単な例です:
。