はじめに
前回に引き続き、XPathNavigatorを利用したXMLファイル操作方法について説明します。今回は特に、XMLデータ内の移動、データの編集、削除について説明します。
サンプルのコードを動作させるには、記事に添付されている「population.xml」を使用します。必要に応じて「population.zip」をダウンロードし、解凍してお使いください。
対象読者
- Windows PowerShellの基本操作が行える方。
- XMLについて基本知識を有する方。
サンプルファイルについて
サンプルの「population.xml」は、県別の人口データを格納したファイルとなっています(説明用に作成したものです)。
データには、ルート要素として<population_data>
、子として1つの県を表す<prefecture>
要素があります。<prefecture>
には属性district
があり、これは地方を表しています。
また<prefecture>
は子として県名を表す<name>
と人口を表す<population>
を持ちます。さらに、岩手県を表す要素には子要素として<municipality>
を持ち、市町村名を表す<name>
と人口を表す<population>
があります。
構成は下記の通りです。
<population_data> <!-- ルート要素 --> <prefecture district="地方名"> <!-- 1つの県を表す --> <name>県名</name> <population>人口</population> <municipality> <!-- 岩手県のところだけにある要素 --> <name>市町村名</name> <population>人口</population> </municipality> </prefecture> </population_data>
データの変更
データの変更が可能なXPathNavigatorを作成する
XPathNavigator
は、XmlDocument
またはXPathDocument
から作成することができます。しかし、データを変更できるのはXmlDocument
から作成されたXPathNavigator
オブジェクトに限定されています。よって、データの編集が可能なXPathNavigator
は、下記のようにXmlDocument
オブジェクトから作成します。
PS> $xmlDoc = [xml](Get-Content population.xml -Encoding UTF8) PS> $Navi = [Xml.Xpath.XPathNavigator] $XmlDoc.CreateNavigator()
現在のXPathNaigator
オブジェクトがデータの編集を可能としているかどうかは CanEdit
プロパティを調べることでわかります。この値は読み取り専用であり、変更することができません。またXmlDocument
から作成されたXPathNaigator
はTRUE
を返します。
PS> $Navi.CanEdit
値の変更
まずは要素の値を変更する方法について説明します。
全県の人口を表す値を0にする
県の人口を表すデータが格納されているのは XPath式で表すと
/population_data/prefecture/population
となります。前回の記事で説明したように、このXPath式をSelect
メソッドの引数に渡して1つずつ処理を行います。
また、値の変更はSetValue
メソッドで行います。引数には変更後の値をセットします。下記は、すべての県の人口データを$nodes
に格納した後、1件ずつ「0」をセットします。
$nodes = $Navi.Select("/population_data/prefecture/population") While ( $nodes.MoveNext() ) { $nodes.Current.SetValue("0") }
値が変更されたかどうかをInnerXml
プロパティで確認します。
PS> $Navi.InnerXml
結果から、すべての県の人口が0に変更されていることを確認できます。
特定の属性を持つ要素の値変更
ここでは特定の属性を持つ要素の値を変更する方法について説明します。
属性 district が"関東"の人口データを0にする
属性district
は地方を表しており、サンプルデータには「東北」と「関東」の2種類があります。
district
が「関東」になっているデータの人口を0にするには、XPath式で
"/population_data/prefecture[@district='関東']/population"
を指定し、While
ループで1件ずつ「0」をセットします。
$nodes = $Navi.Select("/population_data/prefecture[@district='関東']/population") while($nodes.MoveNext()) { $nodes.Current.SetValue("0") }
値が変更されたかどうかをInnnerXml
プロパティで確認します。
PS> $Navi.InnerXml