Python で XML 操作

phiary に引っ越しました. 毎日プログラミングやWebに関する情報を発信しています! RSS 登録してたまに覗いたり, tweet やハテブして拡散してもらえると幸いです.

Pocket

python で xml を扱うモジュールはいくつかあるのですが, 今回は minidom モジュールについて書きます.

DATA

サンプルはこちらからダウンロードできます

SAMPLE

読み込むXMLファイル

<?xml version="1.0" encoding="UTF-8"?>
<recipe name="パン" preparations-time="5分" cokking-time="3時間">
    <dish>基本的なパン</dish>
    <material quantity='3' unit='カップ'>小麦粉</material>
    <material quantity='0.25' unit='オンス'>イースト</material>
    <material quantity='1.5' unit='カップ'>水</material>
    <material quantity='1' unit='ティースプーン'>食塩</material>
    <point>
        <process>全ての材料を一緒にして混ぜます。</process>
        <process>十分にこねます。</process>
        <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
        <process>もう一度こねます。</process>
        <process>パン焼きの容器に入れます。</process>
        <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
        <process>オーブンに入れて温度を180℃にして30分間焼きます。</process>
    </point>
</recipe>
    
  • XML ファイルを読み込んで表示

    # coding: utf-8
    # xmlファイルを読み込んで表示
    
    from xml.dom import minidom
    
    # sample.xmlファイルを読み込む
    xdoc = minidom.parse("sample.xml")
    
    # 内容を文字列に変換して表示
    print(xdoc.toxml())
    
    """    実行結果
    <?xml version="1.0" ?><recipe cokking-time="3時間" name="パン" preparations-time="5分">
        <dish>基本的なパン</dish>
        <material quantity="3" unit="カップ">小麦粉</material>
        <material quantity="0.25" unit="オンス">イースト</material>
        <material quantity="1.5" unit="カップ">水</material>
        <material quantity="1" unit="ティースプーン">食塩</material>
        <point>
            <process>全ての材料を一緒にして混ぜます。</process>
            <process>十分にこねます。</process>
            <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
            <process>もう一度こねます。</process>
            <process>パン焼きの容器に入れます。</process>
            <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
            <process>オーブンに入れて温度を180℃にして30分間焼きます。</process>
        </point>
    </recipe>
    
    """
        
  • タグの中身のテキストにアクセス

    # coding: utf-8
    # タグの中身のテキストにアクセス
    
    from xml.dom import minidom
    
    # sample.xmlファイルを読み込む
    xdoc = minidom.parse("sample.xml")
    
    # recipe タグの0番目の要素を取得
    recipe_element = xdoc.getElementsByTagName("dish")[0]
    
    # データを表示
    print(recipe_element.childNodes[0].data)
    
    # データを変更
    recipe_element.childNodes[0].data = "基本的ではないパン"
    
    # データを再表示
    print(recipe_element.childNodes[0].data)
    
    
    """    実行結果
    <?xml version="1.0" encoding="UTF-8"?>
    基本的なパン
    基本的ではないパン
    """
        
  • タグの属性にアクセス

    # coding: utf-8
    # タグの属性にアクセス
    
    from xml.dom import minidom
    
    # sample.xmlファイルを読み込む
    xdoc = minidom.parse("sample.xml")
    
    # recipe タグの0番目の要素を取得
    recipe_element = xdoc.getElementsByTagName("recipe")[0]
    
    # name 属性を取得して表示
    print(recipe_element.getAttribute("name"))
    
    print("の父親は")
    
    # name 属性を変更
    recipe_element.setAttribute("name", "悟飯")
    
    # 再度 name 属性を表示
    print(recipe_element.getAttribute("name"))
    
    """    実行結果
    パン
    の父親は
    悟飯
    
    """
        
  • 指定したタグに一致する要素をすべて取得して表示

    # coding: utf-8
    # 指定したタグに一致する要素をすべて取得して表示
    
    from xml.dom import minidom
    
    # ファイルを読み込む
    xdoc = minidom.parse("sample.xml")
    
    # processタグの要素をすべて取得
    elements = xdoc.getElementsByTagName("process")
    
    # processタグの中身を表示
    print("手順")
    for i, element in enumerate(elements) :
        print( "{0} : {1}".format(i, element.childNodes[0].data) )
    
    
    """ 実行結果
    手順
    0 : 全ての材料を一緒にして混ぜます。
    1 : 十分にこねます。
    2 : 布で覆い、暖かい部屋で1時間そのままにしておきます。
    3 : もう一度こねます。
    4 : パン焼きの容器に入れます。
    5 : 布で覆い、暖かい部屋で1時間そのままにしておきます。
    6 : オーブンに入れて温度を180℃にして30分間焼きます。
    """
        
  • エレメントを操作する(追加したり移動したり)

    # coding: utf-8
    # エレメントを操作する(追加したり移動したり)
    
    from xml.dom import minidom
    
    # sample.xmlファイルを読み込む
    xdoc = minidom.parse("sample.xml")
    
    # レシピを取得
    recipe = xdoc.getElementsByTagName("recipe")[0]
    
    # レシピリストを生成
    recipe_list = xdoc.createElement("recipeList")
    
    # レシピの前にレシピリストを追加
    recipe.parentNode.insertBefore(recipe_list, recipe)
    
    # レシピリストにレシピを追加
    recipe_list.appendChild(recipe)
    
    # 内容を文字列に変換して表示
    print(xdoc.toxml())
    
    """    実行結果
    <?xml version="1.0" ?>
    <recipeList>
        <recipe cokking-time="3時間" name="パン" preparations-time="5分">
            <dish>基本的なパン</dish>
            <material quantity="3" unit="カップ">小麦粉</material>
            <material quantity="0.25" unit="オンス">イースト</material>
            <material quantity="1.5" unit="カップ">水</material>
            <material quantity="1" unit="ティースプーン">食塩</material>
            <point>
                <process>全ての材料を一緒にして混ぜます。</process>
                <process>十分にこねます。</process>
                <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
                <process>もう一度こねます。</process>
                <process>パン焼きの容器に入れます。</process>
                <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
                <process>オーブンに入れて温度を180℃にして30分間焼きます。</process>
            </point>
        </recipe>
    </recipeList>
    
    """
        
  • element のクローンを生成, 追加する

    # coding: utf-8
    # element のクローンを生成, 追加する
    
    from xml.dom import minidom
    
    # sample.xmlファイルを読み込む
    xdoc = minidom.parse("sample.xml")
    
    # レシピを取得
    recipe = xdoc.documentElement
    
    # レシピをコピー
    recipe2 = xdoc.documentElement.cloneNode(recipe)
    # コピーしたレシピ内にある料理名を変更
    recipe2.getElementsByTagName("dish").item(0).childNodes[0].data="不都合なパン"
    # コピーしたレシピをドキュメントに追加
    xdoc.insertBefore(recipe2, recipe)
    
    # 内容を文字列に変換して表示
    print(xdoc.toxml())
    
    
    """    実行結果
    <?xml version="1.0" ?>
    <recipe cokking-time="3時間" name="パン" preparations-time="5分">
        <dish>不都合なパン</dish>
        <material quantity="3" unit="カップ">小麦粉</material>
        <material quantity="0.25" unit="オンス">イースト</material>
        <material quantity="1.5" unit="カップ">水</material>
        <material quantity="1" unit="ティースプーン">食塩</material>
        <point>
            <process>全ての材料を一緒にして混ぜます。</process>
            <process>十分にこねます。</process>
            <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
            <process>もう一度こねます。</process>
            <process>パン焼きの容器に入れます。</process>
            <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
            <process>オーブンに入れて温度を180℃にして30分間焼きます。</process>
        </point>
    </recipe>
    <recipe cokking-time="3時間" name="パン" preparations-time="5分">
        <dish>基本的なパン</dish>
        <material quantity="3" unit="カップ">小麦粉</material>
        <material quantity="0.25" unit="オンス">イースト</material>
        <material quantity="1.5" unit="カップ">水</material>
        <material quantity="1" unit="ティースプーン">食塩</material>
        <point>
            <process>全ての材料を一緒にして混ぜます。</process>
            <process>十分にこねます。</process>
            <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
            <process>もう一度こねます。</process>
            <process>パン焼きの容器に入れます。</process>
            <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
            <process>オーブンに入れて温度を180℃にして30分間焼きます。</process>
        </point>
    </recipe>
    """
        
  • 2つのxmlファイルを1つにまとめる

    # coding: utf-8
    # 2つのxmlファイルを1つにまとめる
    
    from xml.dom import minidom
    
    # xmlを作成
    xdoc = minidom.parseString("<recipeList />")
    
    # xmlファイルを読み込む
    xdoc0 = minidom.parse("sample.xml")
    xdoc1 = minidom.parse("sample2.xml")
    
    # 追加
    clone = xdoc0.cloneNode(xdoc0.documentElement)
    print(clone)
    xdoc.documentElement.appendChild(xdoc0.documentElement)
    xdoc.documentElement.appendChild(xdoc1.documentElement)
    
    # 内容を文字列に変換して表示
    print(xdoc.toxml())
    
    """    実行結果
    <?xml version="1.0" ?>
    <recipeList>
        <recipe cokking-time="3時間" name="パン" preparations-time="5分">
            <dish>基本的なパン</dish>
            <material quantity="3" unit="カップ">小麦粉</material>
            <material quantity="0.25" unit="オンス">イースト</material>
            <material quantity="1.5" unit="カップ">水</material>
            <material quantity="1" unit="ティースプーン">食塩</material>
            <point>
                <process>全ての材料を一緒にして混ぜます。</process>
                <process>十分にこねます。</process>
                <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
                <process>もう一度こねます。</process>
                <process>パン焼きの容器に入れます。</process>
                <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
                <process>オーブンに入れて温度を180℃にして30分間焼きます。</process>
            </point>
        </recipe>
        <recipe cokking-time="3時間" name="ぶどうパン" preparations-time="6分">
            <dish>ぶどうパン</dish>
            <material quantity="3" unit="カップ">小麦粉</material>
            <material quantity="0.25" unit="オンス">イースト</material>
            <material quantity="1.5" unit="カップ">水</material>
            <material quantity="1" unit="ティースプーン">食塩</material>
            <material quantity="2" unit="手掴み">干しぶどう</material>
            <point>
                <process>全ての材料を一緒にして混ぜます。</process>
                <process>十分にこねます。</process>
                <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
                <process>もう一度こねます。</process>
                <process>パン焼きの容器に入れます。</process>
                <process>布で覆い、暖かい部屋で1時間そのままにしておきます。</process>
                <process>オーブンに入れて温度を180℃にして30分間焼きます。</process>
            </point>
        </recipe>
    </recipeList>
    
    """
        
  • 全ての要素にアクセスする

    # coding: utf-8
    # 全ての要素にアクセスする
    
    from xml.dom import minidom
    
    # 全ての要素のタグ名もしくはテキストを表示する
    def printAllElement(node, hierarchy=0):
        # スペース調整
        space = ''
        for i in range(hierarchy*4):
            space += ' '
        
        # エレメントノードの場合はタグ名を表示する
        if node.nodeType == node.ELEMENT_NODE:
            print("{0}{1}".format(space, node.tagName))
            # 再帰呼び出し
            for child in node.childNodes:
                printAllElement(child, hierarchy+1)
        # テキストもしくはコメントだった場合dataを表示する
        elif node.nodeType in [node.TEXT_NODE, node.COMMENT_NODE]:
            # スペースを取り除く
            data = node.data.replace(' ', '')
            # 改行のみではなかった時のみ表示する
            if data!='\n': print("{0}{1}".format(space, node.data))
            
        
    
    # sample.xmlファイルを読み込む
    xdoc = minidom.parse("sample.xml")
    
    # 全ての要素を表示
    printAllElement(xdoc.documentElement)
    
    
    """    実行結果
    recipe
        dish
            基本的なパン
        material
            小麦粉
        material
            イースト
        material
            水
        material
            食塩
        point
            process
                全ての材料を一緒にして混ぜます。
            process
                十分にこねます。
            process
                布で覆い、暖かい部屋で1時間そのままにしておきます。
            process
                もう一度こねます。
            process
                パン焼きの容器に入れます。
            process
                布で覆い、暖かい部屋で1時間そのままにしておきます。
            process
                オーブンに入れて温度を180℃にして30分間焼きます。
    
    """
        

最近, 仕事でpythonを使う機会が増えてきたのでちょこちょこpythonについてまとめていこうと思います.

TRACK BACK URL

POST COMMENT

メールアドレスが公開されることはありません。

COMMENT