1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PythonでXML形式のAPIレスポンスをいい感じに辞書にする

Last updated at Posted at 2021-12-05

概要

Redmineのクライアントアプリ的なものを作っており、Redmineの各APIを叩いてチケット起票に必要な情報を取ってくる必要があった。RedmineのAPIレスポンスはXMLだが、パッと調べた感じjsonと違っていい感じに辞書にしてくれる機能がないっぽいので自分でやった。忘れそうなので備忘録として書いとく。もし調べ方が下手なだけでいい感じにしてくれるやつが存在するなら僕はただのバカです。

12/12追記
APIのパス末尾の.xml.jsonにしたらふつーにjsonで返ってきました。僕はただのバカです。

まずAPIを叩く

RedmineのAPIドキュメントはこちら。この中で、とりあえずユーザ取得APIを叩きます
返ってくるデータはこんな感じ

<?xml version="1.0" encoding="UTF-8"?>
<users total_count="10" offset="0" limit="100" type="array">
    <user>
        <id>1</id>
        <login>tanakatarou</login>
        <admin>false</admin>
        <firstname>太郎</firstname>
        <lastname>田中</lastname>
        <mail>tanakatarou@mail.com</mail>
        <created_on>2021-10-10T10:00:00Z</created_on>
        <last_login_on>2021-10-10T10:00:0Z</last_login_on>
    </user>
    <user>
        <id>2</id>
        <login>yamadahanako</login>
        <admin>false</admin>
        <firstname>花子</firstname>
        <lastname>山田</lastname>
        <mail>yamadahanako@mail.com</mail>
        <created_on>2021-10-10T10:00:00Z</created_on>
        <last_login_on>2021-10-10T10:00:0Z</last_login_on>
    </user>
<users>

jsonで返ってくるならjson.loads()で一発だが、XMLとなると使いやすい形にするのに一工夫いる。

XMLを辞書にする

今回は、ユーザIDと名前が欲しいので、以下のような形にすることを目標にする。

[
 {"id":"1","name":"田中太郎"},
 {"id":"2","name":"山田花子"}
]

書いた処理はこんな感じ。

import xml.etree.ElementTree as XmlET

# 1 APIを叩いて取得したXML形式の文字列をElementオブジェクトに変換(execute_api()は自作の関数)
redmine_user_xml = XmlET.fromstring(execute_api(url=redmine_user_api_url, headers=redmine_headers, method="GET"))
# 2 全てのuserタグをElementとして取得
all_user_element = redmine_user_xml.findall("user")users
# 3 userのElementからid、nameを取得しテキストにして辞書に格納
users = []
for user_element in all_user_element:
  users.append({
    "id": user_element.find("id").text,
    "name": f"{user_element.find('lastname').text}{user_element.find('firstname').text}"
  })

return users

以下、解説 (ドキュメント)

  1. 文字列であるXML形式のレスポンスを、pythonでパースするためにElementというオブジェクトに変換する。この変換のためにxml.etree.ElementTreeモジュールをimportする必要がある。
  2. 1で使ったfromstring()により、XMLのタグひとつひとつがElementオブジェクトとなり、その属性としてタグの属性や子のElementを持つような形になる。そこで、まずuserタグのElementを全て取得する。findall()を使うとタグ名で検索&取得できる。
  3. 「まずAPIを叩く」で取得したXMLの形式を見ると、userタグの中にidタグやfirstnameタグ、lastnameタグなどが存在しており各タグに囲まれた部分にデータ文字列が入っていることがわかる。なので、2で取得したuserのElementひとつづつに対して"id"や"firstname"、"lastname"でfindしてタグのElementを取得する。そのタグの文字列はtext属性で持っているので.textで取得できる。firstnameとlastnameが別れている必要はないので結合してる。

結果がこちら。

[
 {"id":"1","name":"田中太郎"},
 {"id":"2","name":"山田花子"}
]

いい感じ!!!

まとめ

jsonで返せ。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?