xmlを編集・生成する方法についての備忘
構造を変えずに属性やテキストに編集を加える場合
読み込んだファイルオブジェクト(Elementオブジェクト)を直接編集し,別名のオブジェクトを作って書き出す.
from lxml import etree as ET tree = ET.parse(filename) root = tree.getroot() # 編集するテキストをXPathで取り出し,編集 for t in root.findall('./path/to/node'): t.text = t.text.replace('hoge', 'huga') # ElementTreeオブジェクトに変更を反映し,ファイルに書き出す new_tree = ET.ElementTree(root) new_tree.write(filename, encoding='utf-8', xml_declaration=True)
構造を変えずに値を編集するだけなら,変えたい値を代入するだけで変更できる.
ただしもちろんElementTreeオブジェクトを生成し直して書き出す必要がある.
読み込んだxmlの一部を使い,構造を大きく変える場合
from lxml import etree as ET tree = ET.parse(filename) root = tree.getroot() # ルートの作成 # ET.Elementで指定したタグをルートにする(ここではもとのまま) new_root = ET.Element(root.tag) # 辞書形式でルートの属性を指定(ここではもとのまま) for k, v in root.attrib.items(): new_root.set(k, v) # ルートより下のノードを作成 # 元のファイルのノードを一旦格納 n1 = root.find('./path') # ET.SubElementで,直上のノードとノードのタグを指定 node1 = ET.SubElement(new_root, n1.tag) # 属性の追加 for k, v in n1.attrib.items(): node1.set(k, v) # 元のファイルのノードの一部を編集して追加 n2 = root.find('./path2') node2 = ET.SubElement(new_root, n2.tag) for k, v in n2.attrib.items(): node2.set(k, v) # テキストの追加 node2.text = 'hoge' # 元のファイルにないノードを追加 node3 = ET.SubElement(new_root, 'huga') node3.set('pura', 'piyo') node3.text = 'picopico' new_tree = ET.ElementTree(new_root) # pretty_print=Trueをしないと改行やインデントがされない new_tree.write(filename, encoding='utf-8', xml_declaration=True, pretty_print=True)
構造を変える場合にはxmlのパーツになるElementオブジェクトを生成する必要がある.
lxmlとxml.etree.elementtree
どちらもほぼ同じメソッドをもっていて,解析するだけなら同様に使えるが,
生成する際のpretty_print
オプションにはxml.etree.elementtree
は対応していない.