PythonでExcelを読んでXMLを吐きたい
テスト管理を行うツールにTestLinkというものがあります。
このツールに関する説明は他のサイトにお任せするとして、
TestLinkにテストを登録するには、手動で1件ずつ手作業で入力していくか、
XML形式のものをインポートするかいずれかの方法を使用します。
Excel(所謂テスト仕様書)からXMLに変換するツールは探せば割と出てくるのですが、
たいていマクロ付きのExcelです。
別にいいんですが、マクロ付きのExcelってメンテナンス性微妙だと思うんですよね。。。
ということで、Pythonで変換するツールを作成する中で知った内容をまとめます。
Excelの読み込みには「openpyxl(3.0.10) 」を使用しています。
Excelファイルの読み込み
openpyxl.load_workbook("path/to/excel_file", data_only=True, read_only=True)
data_only: Trueにするとセル内の式の結果を読み込み。Falseだと式そのものを読み込み となります。
read_only: 読み取り専用ですね。
他にもオプションがありましたけど、使ったのはこれぐらいですね。
すべてのシートの取得
book.worksheets
すべてのシートがリストで取得できます。
シートの属性取得
sheet = book.worksheets[0] print(f'シート名:{sheet.title}') print(f'シートの最大行数:{sheet.max_row}') print(f'シートの最大列数:{sheet.max_column}') if sheet.sheet_state != 'visible': print('隠しシートだね')
シート名や最大行数、列数などが取得できます。
なお最大行数はExcelとしての最大行数ではなく、そのシートの一番端の値があるセル行番号です。
また、非表示のシートも取得できます。
セルの値の取得
row = 1 col = 10 sheet[row][col].value
これだけですw
そういえば、XMLについて書くのを忘れていました。。。
xml.etree.ElementTreeを使ったのですが、
これはPython標準なのでまぁググれば腐るほど情報は出てくるでしょうということで1つだけ情報を。
xml.etree.ElementTreeでCDATAを作成したい
ElementTreeでは要素を以下のような感じで作成します。
ET.Element("tag")
そうすると以下のようなXMLになります。
<tag />
これに子要素を追加しながら組み立てていくのですが、CDATAをそのままでは作成できません。
CADATAとは以下のようなやつで、XMLで特別意味をもつ記号等をテキストとして設定したい際に
文字参照に変換せずに値を設定する方法です。
<tag><![CDATA[ 「<html>」を表示したい ]]></tag>
これは、ElementTreeでは実現できません。(たぶん)
上記のXMLをそのままElmentTreeで表現しようとすると以下のようになります。
tag = ET.Element("tag") tag.text = "<![CDATA[ 「<html>」を表示したい ]]>"
これをXML文字列に変換すると以下のようなXMLになってしまいます。
<tag><![CDATA[ 「<html>」を表示したい ]]></tag>
CDATAの開始部分が <![CDATA[
から<![CDATA[
に代わってしまっています。
これでは、ダメなのでCDATAが作成できるようにElementTreeを拡張します。(強引にw)
かなり前に私と同じ壁に当たった方がいたようです。
zlalanneさんのGistに以下のスクリプトがあります。
ただし、このスクリプトは少なくともPython3.9では動かないようなので以下のように調整してあげます。
def CDATA(text=None): element = ET.Element('![CDATA[') element.text = text return element ET._original_serialize_xml = ET._serialize_xml def _serialize_xml(write, elem, qnames, namespaces, short_empty_elements, **kwargs): if elem.tag == '![CDATA[': write("<%s%s]]>" % (elem.tag, elem.text)) return return ET._original_serialize_xml(write, elem, qnames, namespaces, short_empty_elements, **kwargs) ET._serialize_xml = ET._serialize['xml'] = _serialize_xml
標準の機能を汚染しているので、プロダクションに使用する場合には注意が必要ですね。
これで、以下のようにすることでCDATAを作成することができます。
tag = ET.Element("tag") tag.append(CDATA(" 「<html>」を表示したい "))
以下のようなXMLになります。
<tag><![CDATA[ 「<html>」を表示したい ]]></tag>
この手の地味なスクリプトって作り始める前は簡単だろうって思うんですけど、
実際に作り始めるとハマりポイントが割とあるんですよね。
まだまだ精進が足りませんねw
この記事書いてて思ったんですが、ExcelってPandasでも読めますよね
テスト仕様書ならフォーマットにもよるけど普通に読めるんじゃ...
pandasなら楽ができたかも。。。