PowershellでXMLファイルを新規作成してみる

コンピュータ
PowerShellのあれこれ

PowerShellはSystem.Xml.XmlDocumentを使いXMLファイルを作成や編集することができます。
よく使う機能をまとめて記事にしてみました。

新規作成

以下のようなXMLファイルを作成したい。

<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
  <rootfiles>
    <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml" />
  </rootfiles>
</container>

スクリプト

<#
.SYNOPSIS
 XmlWriterのサンプル
#>

using namespace System.Xml

$xmlFile = ".\container.xml"

$xmlns = "urn:oasis:names:tc:opendocument:xmlns:container"

[xml]$doc = [XmlDocument]::new()

$dec = $doc.CreateXmlDeclaration("1.0", $null, $null)
$doc.AppendChild($dec) | Out-Null

$container = $doc.CreateNode("element", "container", $xmlns)
$container.SetAttribute("version", "1.0")

$rootfiles = $doc.CreateNode("element", "rootfiles", $xmlns)
$container.AppendChild($rootfiles) | Out-Null

$rootfile = $doc.CreateNode("element", "rootfile", $xmlns)
$rootfile.SetAttribute("full-path", "OEBPS/content.opf")
$rootfile.SetAttribute("media-type", "application/oebps-package+xml")
$rootfiles.AppendChild($rootfile) | Out-Null

$doc.AppendChild($container) | Out-Null
$doc.Save($xmlFile) | Out-Null

データの構造を表現するので仕方がないですがコード量が多くなりがちです。
この程度サイズのXMLの場合、スクリプトにヒアドキュメントで直接XMLを埋め込んだ方がシンプルで良さそうです。

既存のXMLファイルを読み込みdomオブジェクトを生成

$xmlDoc = [System.Xml.XmlDocument](Get-Content -Encoding UTF8 -Raw XMLファイルのパス)

(以下、$xmlDocにはWindowエレメントが一つあるものとします。)

XMLファイルの保存

$xmlDoc.Save($inFile) 

属性(Attribute)を追加

$val = "セットする値"
$attri = $xmlDoc.CreateAttribute("属性の名前")
$attri.Value = $val
$xmlDoc.Window.Attributes.Append($attri) | Out-Null

属性(Attribute)を変更

$xmlDoc.Window.setAttribute("名前", "値")

エレメントを作成

$child3 = $xmlDoc.CreateElement("エレメント", "ネームスペース")

タグからエレメントを取得

$element = $xmlDoc.getElementsByTagName("タグ名")

指定のエレメントの直前にエレメントを挿入

$dc = $xmlDoc.Window.insertBefore(挿入するエレメント, ここで指定されたエレメントの直前に挿入される)

子エレメントをインデックス指定して取得

$pos = $xmlDoc.getElementsByTagName("Grid")[インデックス]

既存 XML を読み込み

$path = "sample.xml"
[xml]$xmlDoc = Get-Content $path

「xml」 キャストにより、XML を XmlDocument として読み込みます。
以降は $xmlDoc を直接操作します。

ノードを検索する(XPath)

# 最初に見つかった1件
$node = $xmlDoc.SelectSingleNode("//item")

# 条件付き検索
$node = $xmlDoc.SelectSingleNode("//item[@id='1']")

最初の1件のみ取得

複数ノードを検索する

$nodes = $xmlDoc.SelectNodes("//item")

こちらは全ノードが返る

ノードを更新する

$node = $xmlDoc.SelectSingleNode("//item[@id='1']")
$node.InnerText = "New Value"

InnerTextに値をセット(更新)します。

属性を更新(なければ追加)

$node = $xmlDoc.SelectSingleNode("//item[@id='1']")
$node.SetAttribute("status", "enabled")

ノードを削除する

$node = $xmlDoc.SelectSingleNode("//item[@id='2']")
if ($node) {
    $node.ParentNode.RemoveChild($node)
}

親ノード経由で削除

「あれば更新・なければ追加」パターン

$node = $xmlDoc.SelectSingleNode("//item[@id='3']")

if ($node) {
    $node.InnerText = "Updated"
} else {
    $item = $xmlDoc.CreateElement("item")
    $item.SetAttribute("id", "3")
    $item.InnerText = "Created"
    $xmlDoc.root.AppendChild($item)
}

コメント