curl コマンドで取得した XML 結果を綺麗に整形する

API の呼び出し結果フォーマットはそれぞれ異なる

curl コマンドで様々なウェブ API を呼び出しますが、結果が XML で返ってくる場合 XML データが改行無しで表示されたりインデントが崩れていたりするため、綺麗に整形すると 非常に扱いやすく理解しやすくなります。

実際、API 提供元によって XML のフォーマット(インデント幅等)が若干異なって いますので、その違いを吸収すると統一性がとれて非常に見やすくなります。




通常の curl コマンドで XML API を呼び出した場合

ここでは「JR 山手線 東京駅の情報」を取得する API と「郵便番号 103-0000 を現行郵便番号から検索し該当する住所を格納した XML 結果」を取得する API を呼び出してみます。

まずは「JR 山手線 東京駅の情報」を取得する API を curl コマンドで呼び出してみます。

$ curl -sL http://www.ekidata.jp/api/s/1130224.xml

<ekidata version="ekidata.jp station api 1.0">
        <station>
                <pref_cd>13</pref_cd>
                <line_cd>11302</line_cd>
                <line_name>JR山手線</line_name>
                <station_cd>1130224</station_cd>
                <station_g_cd>1130101</station_g_cd>
                <station_name>東京</station_name>
                <lon>139.766103</lon>
                <lat>35.681391</lat>
        </station>
</ekidata>

上記結果はインデント幅が8個のスペースになっています。

今度は「郵便番号 103-0000 を現行郵便番号から検索し該当する住所を格納した XML 結果を取得」という API を呼び出してみます。

$ curl -sL http://zip.cgis.biz/xml/zip.php?zn=1030000

<?xml version="1.0" encoding="utf-8" ?>
<ZIP_result>
<result name="ZipSearchXML" />
<result version="1.01" />
<result request_url="http%3A%2F%2Fzip.cgis.biz%2Fxml%2Fzip.php%3Fzn%3D1030000" />
<result request_zip_num="1030000" />
<result request_zip_version="none" />
<result result_code="1" />
<result result_zip_num="1030000" />
<result result_zip_version="0" />
<result result_values_count="1" />
<ADDRESS_value>
<value state_kana="トウキョウト" />
<value city_kana="チュウオウク" />
<value address_kana="イカニケイサイガナイバアイ" />
<value company_kana="none" />
<value state="東京都" />
<value city="中央区" />
<value address="none" />
<value company="none" />
</ADDRESS_value>
</ZIP_result>

こちらはインデントが全くありませんね。このように API 提供元によってフォーマット(インデント幅等)が異なります。また API によっては改行すら入っていない場合があり、整形し直す必要があります。


API からの XML 結果を整形する


では上記のようなフォーマットの違いをどうやって吸収すれば一番簡単でしょうか。それには xmllint というコマンドを使えば解決できます。

それでは先に呼び出した「JR 山手線 東京駅の情報」を取得する API を curl コマンドと xmllint コマンドを組み合わせて呼び出してみます。

$ curl -sL http://www.ekidata.jp/api/s/1130224.xml | xmllint --format -

<?xml version="1.0" encoding="UTF-8"?>
<ekidata version="ekidata.jp station api 1.0">
  <station>
    <pref_cd>13</pref_cd>
    <line_cd>11302</line_cd>
    <line_name>JR山手線</line_name>
    <station_cd>1130224</station_cd>
    <station_g_cd>1130101</station_g_cd>
    <station_name>東京</station_name>
    <lon>139.766103</lon>
    <lat>35.681391</lat>
  </station>
</ekidata>

上記結果はスペース2文字でインデントされています。

同様に、今度は「郵便番号 103-0000 を現行郵便番号から検索し該当する住所を格納した XML 結果を取得」という API を curl コマンドと xmllint コマンドを組み合わせて呼び出してみます。

$ curl -sL http://zip.cgis.biz/xml/zip.php?zn=1030000 | xmllint --format -

<?xml version="1.0" encoding="utf-8"?>
<ZIP_result>
  <result name="ZipSearchXML"/>
  <result version="1.01"/>
  <result request_url="http%3A%2F%2Fzip.cgis.biz%2Fxml%2Fzip.php%3Fzn%3D1030000"/>
  <result request_zip_num="1030000"/>
  <result request_zip_version="none"/>
  <result result_code="1"/>
  <result result_zip_num="1030000"/>
  <result result_zip_version="0"/>
  <result result_values_count="1"/>
  <ADDRESS_value>
    <value state_kana="トウキョウト"/>
    <value city_kana="チュウオウク"/>
    <value address_kana="イカニケイサイガナイバアイ"/>
    <value company_kana="none"/>
    <value state="東京都"/>
    <value city="中央区"/>
    <value address="none"/>
    <value company="none"/>
  </ADDRESS_value>
</ZIP_result>

こちらも結果がスペース2文字でインデントされました。これでどの API を呼び出しても同じインデント幅で結果が得られます。

xmllint コマンドにはとても多くのオプションがありますので、それらを使うともっと柔軟なフォーマット変更が 可能です。またウェブ API だけでなく、様々な XML ファイルの変換にも利用できますので大変便利です。