その時々

その時々で違うんです。特に決まっていないんです。

PythonでXMLを触ってみる4 minidomね

今回はノードにエレメントを追加してみます。

Sample.xml

<?xml version="1.0" encoding="utf-8"?>
<cars>
  <car>
    <name>
      乗用車
    </name>
    <price>
      150
    </price>
  </car>
</cars>

minidom4.py

# _*_ coding: UTF-8 _*_

import xml.dom, xml.dom.minidom, codecs

def walk(node):
    n = node.firstChild
    while n:
        if n.nodeType == xml.dom.Node.ELEMENT_NODE:
            if n.nodeName == 'car':
                doc = n.ownerDocument
                company = doc.createElement('company')
                txt = doc.createTextNode(u'カーバンク社')
                n.appendChild(company)
                company.appendChild(txt)
            
            walk(n)
        n = n.nextSibling

doc = xml.dom.minidom.parse('Sample.xml')
root = doc.documentElement
walk(root)

result = codecs.open('result.xml', 'w', 'utf-8')
doc.writexml(result)
result.close()

実行結果

$ python minidom4.py
$ cat result.xml
<?xml version="1.0" ?><cars>
  <car>
    <name>乗用車</name>
    <price>150</price>
  <company>カーバンク社</company></car>
  <car>
    <name>トラック</name>
    <price>500</price>
  <company>カーバンク社</company></car>
  <car>
    <name>オープンカー</name>
    <price>200</price>
  <company>カーバンク社</company></car>
</cars>

エレメントが追加されましたが、改行をテキストエレメントとして追加して
体裁を整えてみます。

minidom4.py

# _*_ coding: UTF-8 _*_

import xml.dom, xml.dom.minidom, codecs

def walk(node):
    n = node.firstChild
    while n:
        if n.nodeType == xml.dom.Node.ELEMENT_NODE:
            if n.nodeName == 'car':
                doc = n.ownerDocument
                company = doc.createElement('company')
                txt = doc.createTextNode(u'カーバンク社')
                lf = doc.createTextNode(u'\n  ')
                n.appendChild(company)
                company.appendChild(txt)  # <---追加
                n.appendChild(lf)         # <---追加
                
            walk(n)
        n = n.nextSibling

doc = xml.dom.minidom.parse('Sample.xml')
root = doc.documentElement
walk(root)

result = codecs.open('result.xml', 'w', 'utf-8')
doc.writexml(result)
result.close()

実行結果

$ python minidom4.py
$ cat result.xml
<?xml version="1.0" ?><cars>
  <car>
    <name>乗用車</name>
    <price>150</price>
  <company>カーバンク社</company>
  </car>
  <car>
    <name>トラック</name>
    <price>500</price>
  <company>カーバンク社</company>
  </car>
  <car>
    <name>オープンカー</name>
    <price>200</price>
  <company>カーバンク社</company>
  </car>
</cars>

きれいに整いました。

続いて属性を追加してみます。

minidom4.py

# _*_ coding: UTF-8 _*_

import xml.dom, xml.dom.minidom, codecs

def walk(node):
    n = node.firstChild
    while n:
        if n.nodeType == xml.dom.Node.ELEMENT_NODE:
            if n.nodeName == 'car':
                doc = n.ownerDocument
                company = doc.createElement('company')
                txt = doc.createTextNode(u'カーバンク社')
                lf = doc.createTextNode(u'\n  ')
                n.appendChild(company)
                company.appendChild(txt)
                n.appendChild(lf)
                
                n.setAttribute('color', u'白')    # <-- 追加

            walk(n)
        n = n.nextSibling

doc = xml.dom.minidom.parse('Sample.xml')
root = doc.documentElement
walk(root)

result = codecs.open('result.xml', 'w', 'utf-8')
doc.writexml(result)
result.close()

実行結果

$ python minidom4.py
$ cat result.xml
<?xml version="1.0" ?><cars>
  <car color="白">
    <name>乗用車</name>
    <price>150</price>
  <company>カーバンク社</company>
  </car>
  <car color="白">
    <name>トラック</name>
    <price>500</price>
  <company>カーバンク社</company>
  </car>
  <car color="白">
    <name>オープンカー</name>
    <price>200</price>
  <company>カーバンク社</company>
  </car>
</cars>

参考図書のやさしいXML ではJavaで書かれてい
てNode型からElement型にキャストしてからsetAttributesしています。
pythonでは動的型付けのため変数nはNodeであるにもかかわらず
setAttributes出来ています。
面白いですね。