この記事は、先日書いた以下の記事のMySQL(mysqlコマンド)版です。
まずは結果から
サンプルスクリプトは以下のGistに格納しました。
https://gist.github.com/noobow34/42384dc343f2df44793b3bff7261fc70
PS C:\> .\Get-MySqlXmlData.ps1
-----------行を指定して使用する-----------
SEQ2 SEQ
---- ---
3 2
-----------行と列を指定して使用する-----------
3
-----------ループで処理する場合-----------
1:2
2:3
3:4
4:5
5:6
6:7
7:8
8:9
9:10
10:11
やりかた
扱うデータ
Oracle版で使ったのと同じ結果になるSQLをChatGPTに作ってもらいました。
WITH RECURSIVE Numbers AS (
SELECT 1 AS SEQ
UNION ALL
SELECT SEQ + 1 FROM Numbers WHERE SEQ < 10
)
SELECT SEQ, SEQ + 1 AS SEQ2 FROM Numbers;
PS C:\> @"
>> WITH RECURSIVE Numbers AS (
>> SELECT 1 AS SEQ
>> UNION ALL
>> SELECT SEQ + 1 FROM Numbers WHERE SEQ < 10
>> )
>> SELECT SEQ, SEQ + 1 AS SEQ2 FROM Numbers;
>> "@ | mysql -u user
SEQ SEQ2
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
mysqlの出力をXMLにする
なんとmysqlコマンドは--xml
オプションをつけるだけで出力がXMLになります。簡単じゃん!と思ったのですが、出力が以下のようになります。
PS C:\> @"
>> WITH RECURSIVE Numbers AS (
>> SELECT 1 AS SEQ
>> UNION ALL
>> SELECT SEQ + 1 FROM Numbers WHERE SEQ < 10
>> )
>> SELECT SEQ, SEQ + 1 AS SEQ2 FROM Numbers;
>> "@ | mysql -u user --xml
<?xml version="1.0"?>
<resultset statement="WITH RECURSIVE Numbers AS (
SELECT 1 AS SEQ
UNION ALL
SELECT SEQ + 1 FROM Numbers WHERE SEQ < 10
)
SELECT SEQ, SEQ + 1 AS SEQ2 FROM Numbers" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<field name="SEQ">1</field>
<field name="SEQ2">2</field>
</row>
<row>
<field name="SEQ">2</field>
<field name="SEQ2">3</field>
</row>
<row>
<field name="SEQ">3</field>
<field name="SEQ2">4</field>
</row>
<row>
<field name="SEQ">4</field>
<field name="SEQ2">5</field>
</row>
<row>
<field name="SEQ">5</field>
<field name="SEQ2">6</field>
</row>
<row>
<field name="SEQ">6</field>
<field name="SEQ2">7</field>
</row>
<row>
<field name="SEQ">7</field>
<field name="SEQ2">8</field>
</row>
<row>
<field name="SEQ">8</field>
<field name="SEQ2">9</field>
</row>
<row>
<field name="SEQ">9</field>
<field name="SEQ2">10</field>
</row>
<row>
<field name="SEQ">10</field>
<field name="SEQ2">11</field>
</row>
</resultset>
各列が列名のタグではなくfieldタグでname属性に列名という形なので、そのままXML型でPowerShellの変数に入れても$row.SEQ
の様に列名で扱うことができません。
そこで、簡単に列名で扱えるようにするためにカスタムオブジェクトに変換する関数をかませることにしました。この関数はChatGPTにサクッと作ってもらいました。
function Convert-XmlToCustomObject {
param (
[Parameter(ValueFromPipeline)] [xml]$xml
)
process {
# すべての <row> 要素をカスタムオブジェクトに変換
$rows = $xml.resultset.row | ForEach-Object {
$properties = @{}
# 各 <field> 要素の name 属性をプロパティ名に、#text の値をプロパティ値にする
$_.field | ForEach-Object {
$properties[$_.name] = $_.'#text'
}
# PSCustomObject に変換
[PSCustomObject]$properties
}
return $rows
}
}
mysqlコマンドの結果を上記の関数に渡せばカスタムオブジェクトの出来上がりです。
$xml = [xml]($execSql | mysql -u user --xml) | Convert-XmlToCustomObject
カスタムオブジェクトの扱い方
$xml
自体が行の配列になっているので$xml[0]
の様にインデックスを指定して扱います。あとは、$xml[0].SEQ
の様に列名をそのままプロパティとして扱えます。