5.76. mxml2csv xmlからcsvへの変換

xml形式のデータをcsv形式のデータに変換する。 基本的な変換規則は、一行の単位となる要素(XMLタグ)と、 項目に対応させる要素(もしくは属性)を、それぞれ k=f= によって指定する。 項目の値としては、 要素で囲われたテキスト、要素が出現するかどうか、 属性の値、属性が出現するかどうか、の4通りの方法を指定できる。 XMLのパーサーとしてはSAXを用いているので、XMLのサイズ制約はない。 XMLのエンコーディングがUTF-8以外であれば、UTF-8に変換されてCSVに出力される。 XMLデータは、整形式XML文書(well-formed XML document)であることを前提としている。 そうでない場合の処理結果は不定である。

典型例を、 リスト 5.4 に示されたXMLデータを用いて概略を示す。 リスト 5.5 は、 行の単位を要素 <b> とし(このような要素のことを「キー要素」と呼ぶ)、 項目として、要素 b の属性 att の値(CSV項目名 b_att )、 要素 c の属性 p の値( b_p )とフラグ( b_p_f )、 そして要素 da 内のテキスト( da )を出力した結果である。 ここで、フラグとは、指定した要素もしくは属性が、出現するかどうかを0-1で出力したものである。 要素のテキスト出力は、指定した要素で囲われた範囲に出現する文字列を全て連結した文字列である。 ただし、スペースと制御文字は出力されないことに注意する。

リスト 5.4 XMLデータ
 1<a att="aa">
 2  <b att="bb1">
 3    <c p="pp1" q="qq1"/>
 4    <d>text1</d>
 5  </b>
 6  <b att="bb2">
 7    <c q="qq2"></c>
 8    <d>text2</d>
 9  </b>
10  <b>
11    <c p="pp3"/>
12    <d>text3</d>
13  </b>
14</a>
リスト 5.5 k=/a/b、f=b@att,c@p,d,/a
1b_att,c_p,c_p_f,d,a
2bb1,pp1,1,text1,text1
3bb2,,,text2,text1text2
4,pp3,1,text3,text1text2text3

解説

キー要素の指定方法

一行の単位となるキー要素( k= パラメータで指定)は絶対パスで指定する。 絶対パスは、ルート記号( '/' )から始めて、要素の階層を '/' 記号で区切って表される。 本コマンドにおけるキー要素の役割は、キー要素の終了タグが出現した時に、以下の2点を実行することにある。

  • 項目データを一行出力する。上記の例では、キー要素の終了タグ </b> が3回出現しており、

  • その度にCSVデータ一行が出力され改行される。

  • 項目データを初期化する。ただし、キー要素の外側にある項目要素の出力データは初期化しない。

  • リスト 5.5 の要素 a の出力において、テキストが連結されていくのは、

  • キー要素の終了タグが出現した時であっても、要素 /a がキー要素 /a/b より外側にあり、

  • 出力データが初期化されないためである。

要素の出力項目指定

f= で要素をCSV項目として出力する場合、以下に示すフォーマットに従う。 要素パス[%フラグ]:CSV項目名 「項目名」は、出力されるCSVの項目名であり、必ず指定しなければならない。 要素を項目として出力する方法は2通りある。 一つは、指定の要素の開始タグと終了タグで囲われたテキストを出力する方法で、 他方は、指定した要素が存在するかどうかを0-1値で出力する方法である。 前者は、対象となる要素パスを指定し、 後者は、加えてフラグ %f を付与する。 また要素パスの指定方法は、絶対パスと相対パスの2通りある。 相対パスは、k=で指定された要素からのパスを指定する。 以下、 リスト 5.4 のXMLについて、いくつかの要素パスの指定例を示す。

  • k=/a/b において、 f=:B と指定すると、相対パスは空でキー要素と同じ要素となる。CSVの項目名は B である。

  • k=/a/b において、 f=c:Cf=/a/b/c:C は同じ意味である。

  • 前者は相対パスによる指定、後者は絶対パスによる指定である。両者ともCSV項目名は C である。

  • f=d:D は要素 d で囲われたテキストを出力し、

  • f=d%f:D は要素 d が存在するかどうかを出力する。CSV項目名は D である。

  • k=/a/b において f=/a:A とした場合、

  • 項目要素はキー要素の外側にあるため、 a 要素内に含まれるテキストが次々と結合される。

  • なぜならば、キー要素の終了タグが出現しても、項目要素の終了タグが出現しないために、その時点でデータがクリアされることがないためである。

属性の出力項目指定

f= で属性をCSV項目として出力する場合、以下に示すフォーマットに従う。 要素パス@要素名[%フラグ]:CSV項目名 「項目名」は、出力されるCSVの項目名であり、必ず指定しなければならない。 要素パスの指定は、要素の出力項目指定と同様である。 そして、属性名は、要素パスに続けて @ で連結して指定する。 要素名の後に %f を付けることで、その要素が存在するかどうかを0-1値で出力する。

パラメータ

o= : 型=str , 任意(default=標準出力)

出力データを指定する。

k= : 型=str , 必須

一行の単位となる要素をルートからのパス名として指定する。
パスはルート記号'/'から始まり、要素を'/'でつなげることで指定する。
例: /article/sentence/chunk

f= : 型=str , 必須

項目として出力する要素もしくは属性をカンマで区切って指定する。
フォーマットは以下のとおり。
要素パス[%フラグ]:CSV項目名
要素パス@要素名[%フラグ]:CSV項目名

i= : 型=str , 任意(default=標準入力)

xmlデータデータを指定する。省略時は標準入力から読み込まれる。

共通パラメータ

o= , nfn= , nfno= , x= , tmppath= , precision=

利用例

importと入力データ(CSV)の準備

 1import nysol.mcmd as nm
 2
 3with open('dat1.xml','w') as f:
 4  f.write(
 5'''<a att="aa">
 6<b att="bb1">
 7<c p="pp1" q="qq1"/>
 8<d>text1</d>
 9</b>
10<b att="bb2">
11<c q="qq2"></c>
12<d>text2</d>
13</b>
14<b>
15<c p="pp3"/>
16<d>text3</d>
17</b>
18</a>
19''')

基本例

概要にて解説した例。 /a/bをキー要素として、5つのCSV項目を出力する。

1nm.mxml2csv(k="/a/b", f="@att:b_att,c@p:c_p,c@p%f:c_p_f,d:d,/a:a", i="dat1.xml", o="rsl1.csv").run()
2### rsl1.csv の内容

絶対パス

基本例と同じ要素を絶対パスで指定する例。 /a/bをキー要素として、5つのCSV項目を出力する。

1nm.mxml2csv(k="/a/b", f="/a/b@att:b_att,/a/b/c@p:c_p,/a/b/c@p%f:c_p_f,/a/b/d:d,/a:a", i="dat1.xml", o="rsl2.csv").run()
2### rsl2.csv の内容

キー要素の変更

絶対パスの例でキー要素をaに変更した例。 aの終了タグは一つしかないので、一行だけ出力されている。 f=で指定した/a/b@attは、2回出現しているが、最後に出現した値が出力されている。

1nm.mxml2csv(k="/a", f="/a/b@att:b_att,/a/b/c@p:c_p,/a/b/c@p%f:c_p_f,/a/b/d:d,/a:a", i="dat1.xml", o="rsl3.csv").run()
2### rsl3.csv の内容

関連メソッド