目次

XML整形

2026-04-28 コピペ用

事前の知識

Chat-GPTさん情報で、PowerShell 5.1系はスクリプトを UTF-8 BOM付 で保存しておく。こうしておかないとスクリプトのパースに失敗する事があるそうだ。
※今回 xmlupdate.ps1 で実際に喰らった

XML整形

powershell 5.x シリーズ用

xmlformatter.ps1
## powershell -NoProfile -ExecutionPolicy Bypass -File xmlformatter.ps1 XMLファイル名
 
param(
  [Parameter(Mandatory = $true)]
  [string] $InputPath
)
 
if (Test-Path $InputPath) {
    $base = [System.IO.Path]::GetFileNameWithoutExtension($InputPath)
    $OutputPath = ([System.IO.Path]::GetFullPath($base) + ".new.xml")
} else {
    Write-Host "ファイルなし"
    exit
}
 
## 整形用にインデントを指示
$settings = New-Object System.Xml.XmlWriterSettings
$settings.Indent = $true
 
## XML読み込み
$xmldoc = New-Object System.Xml.XmlDocument
$xmldoc.Load($InputPath)
 
## XML整形結果書き出し
$writer = [System.Xml.XmlWriter]::Create($OutputPath, $settings)
$xmldoc.Save($writer)
$writer.Close()

powershell 7.x シリーズ用

xmlformatter.ps1
## powershell -NoProfile -ExecutionPolicy Bypass -File xmlformatter.ps1 XMLファイル名
 
param(
  [Parameter(Mandatory = $true)]
  [string] $InputPath
)
 
Add-Type -AssemblyName System.Xml.Linq
 
if (Test-Path $InputPath) {
    $base = [System.IO.Path]::GetFileNameWithoutExtension($InputPath)
    $OutputPath = ([System.IO.Path]::GetFullPath($base) + ".new.xml")
} else {
    Write-Host "ファイルなし"
    exit
}
 
## 整形用にインデントを指示
$settings = [System.Xml.Linq.SaveOptions]::None
 
## XML読み込み
$xmldoc = [System.Xml.Linq.XDocument]::Load($InputPath)
 
## XML整形結果書き出し
$xmldoc.Save($OutputPath, $settings)

入力サンプルXML

sample.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<items><item id="001">アイテム1</item><item id="005RD">アイテム5赤</item>
<item id="003BK">アイテム3黒</item></items>
</root>

実行コマンドライン

G:\sandbox\xmlformatter>powershell -NoProfile -ExecutionPolicy Bypass -File xmlformatter.ps1 sample.xml

実行結果(整形結果)

sample.new.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
  <items>
    <item id="001">アイテム1</item>
    <item id="005RD">アイテム5赤</item>
    <item id="003BK">アイテム3黒</item>
  </items>
</root>

XML更新

xmlupdate.ps1
## powershell -NoProfile -ExecutionPolicy Bypass -File xmlupdate.ps1 XMLファイル名
 
param(
  [Parameter(Mandatory = $true)]
  [string] $InputPath
)
 
if (Test-Path $InputPath) {
    $base = [System.IO.Path]::GetFileNameWithoutExtension($InputPath)
    $OutputPath =([System.IO.Path]::GetFullPath($base) + ".new.xml")
} else {
    Write-Host "ファイルなし"
    exit
}
 
## 整形用にインデントを指示
$settings = New-Object System.Xml.XmlWriterSettings
$settings.Indent = $true
 
## XML読み込み
$xmldoc = New-Object System.Xml.XmlDocument
$xmldoc.Load($InputPath)
 
## ノード修正
$node = $xmldoc.SelectSingleNode("/root/items/item[@id='005RD']")
if ($node -ne $null) {
  $node.InnerText="アイテムX"
  $node.SetAttribute("id", "005X")
}
 
## ノード追加
$node = $xmldoc.SelectSingleNode("/root/items")
if ($node -ne $null) {
  $itemdoc = $xmldoc.CreateElement("item")
  $itemdoc.InnerText="アイテム7Z"
  $itemdoc.SetAttribute("id","007Z")
  [void] $node.AppendChild($itemdoc)
}
 
## 修正結果書き出し
$writer = [System.Xml.XmlWriter]::Create($OutputPath, $settings)
$xmldoc.Save($writer)
$writer.Close()

入力サンプル

sample2.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
  <items>
    <item id="001">アイテム1</item>
    <item id="005RD">アイテム5赤</item>
    <item id="003BK">アイテム3黒</item>
  </items>
</root>

実行コマンドライン

G:\sandbox\xmlformatter>powershell -NoProfile -ExecutionPolicy Bypass -File xmlformatter.ps1 sample2.xml

実行結果(更新結果)

sample2.new.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
  <items>
    <item id="001">アイテム1</item>
    <item id="005X">アイテムX</item>
    <item id="003BK">アイテム3黒</item>
    <item id="007Z">アイテム7Z</item>
  </items>
</root>