web-dev-qa-db-ja.com

xml.etree.ElementTreeを使用してXML宣言を作成する方法

Pythonを使用して ElementTree でXMLドキュメントを生成していますが、tostring関数は、プレーンテキストへの変換時に XML宣言 を含みません。

from xml.etree.ElementTree import Element, tostring

document = Element('outer')
node = SubElement(document, 'inner')
node.NewValue = 1
print tostring(document)  # Outputs "<outer><inner /></outer>"

次のXML宣言を含めるには文字列が必要です。

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

ただし、これを行う方法は文書化されていません。

ElementTreeでXML宣言をレンダリングする適切な方法はありますか?

48
Roman Alexander

ElementTree.tostring()には方法がないように見えることに驚いています。ただし、ElementTree.ElementTree.write()を使用して、XMLドキュメントを偽のファイルに書き込むことができます。

from io import BytesIO
from xml.etree import ElementTree as ET

document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
et = ET.ElementTree(document)

f = BytesIO()
et.write(f, encoding='utf-8', xml_declaration=True) 
print(f.getvalue())  # your XML file, encoded as UTF-8

この質問 を参照してください。その場合でも、自分で追加することなく「スタンドアロン」属性を取得できるとは思いません。

80
wrgrs

Lxmlを使用します( http://lxml.de/api.html を参照)。

その後、次のことができます。

from lxml import etree
document = etree.Element('outer')
node = etree.SubElement(document, 'inner')
print(etree.tostring(document, xml_declaration=True))
20
glormph

encoding='utf8'、XMLヘッダーを取得します

xml.etree.ElementTree.tostringはencoding = 'utf8'でXMLエンコーディング宣言を書き込みます

サンプルPythonコード(Python 2および3で動作):

import xml.etree.ElementTree as ElementTree

tree = ElementTree.ElementTree(
    ElementTree.fromstring('<xml><test>123</test></xml>')
)
root = tree.getroot()

print('without:')
print(ElementTree.tostring(root, method='xml'))
print('')
print('with:')
print(ElementTree.tostring(root, encoding='utf8', method='xml'))

Python 2出力:

$ python2 example.py
without:
<xml><test>123</test></xml>

with:
<?xml version='1.0' encoding='utf8'?>
<xml><test>123</test></xml>

Python 3に注意してください bプレフィックス バイトリテラルが返されることを示します(Python 2 ):

$ python3 example.py
without:
b'<xml><test>123</test></xml>'

with:
b"<?xml version='1.0' encoding='utf8'?>\n<xml><test>123</test></xml>"
14

最近、この問題に遭遇しました。コードを掘り下げたところ、次のコードスニペットが関数ElementTree.writeの定義であることがわかりました。

def write(self, file, encoding="us-ascii"):
    assert self._root is not None
    if not hasattr(file, "write"):
        file = open(file, "wb")
    if not encoding:
        encoding = "us-ascii"
    Elif encoding != "utf-8" and encoding != "us-ascii":
        file.write("<?xml version='1.0' encoding='%s'?>\n" % 
     encoding)
    self._write(file, self._root, encoding, {})

したがって、答えは、XMLヘッダーをファイルに書き込む必要がある場合は、utf-8またはus-ascii以外のencoding引数を設定します。 UTF-8

3
alijandro

ElementTreeパッケージを使用した最小限の作業例:

import xml.etree.ElementTree as ET

document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
node.text = '1'
res = ET.tostring(document, encoding='utf8', method='xml').decode()
print(res)

出力は次のとおりです。

<?xml version='1.0' encoding='utf8'?>
<outer><inner>1</inner></outer>
2
Andriy

[〜#〜] et [〜#〜] :を使用します。

try:
    from lxml import etree
    print("running with lxml.etree")
except ImportError:
    try:
        # Python 2.5
        import xml.etree.cElementTree as etree
        print("running with cElementTree on Python 2.5+")
    except ImportError:
        try:
            # Python 2.5
            import xml.etree.ElementTree as etree
            print("running with ElementTree on Python 2.5+")
        except ImportError:
            try:
                # normal cElementTree install
                import cElementTree as etree
                print("running with cElementTree")
            except ImportError:
               try:
                   # normal ElementTree install
                   import elementtree.ElementTree as etree
                   print("running with ElementTree")
               except ImportError:
                   print("Failed to import ElementTree from any known place")

document = etree.Element('outer')
node = etree.SubElement(document, 'inner')
print(etree.tostring(document, encoding='UTF-8', xml_declaration=True))
0
Alessandro

別の非常に簡単なオプションは、目的のヘッダーを次のようにxmlの文字列に連結することです。

xml = (bytes('<?xml version="1.0" encoding="UTF-8"?>\n', encoding='utf-8') + ET.tostring(root))
xml = xml.decode('utf-8')
with open('invoice.xml', 'w+') as f:
    f.write(xml)
0
Novak

これは、印刷したいだけの場合に機能します。ファイルに送信しようとするとエラーが発生します...

import xml.dom.minidom as minidom
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element, SubElement, Comment, tostring

def prettify(elem):
    rough_string = ET.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="  ")
0
Rebecca Fallon

宣言に「スタンドアロン」を含める

ドキュメントにstandalone引数を追加する代替手段が見つからなかったため、ET.tosting関数を引数として受け取ります。

from xml.etree import ElementTree as ET

# Sample
document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
et = ET.ElementTree(document)

 # Function that you need   
 def tostring(element, declaration, encoding=None, method=None,):
     class dummy:
         pass
     data = []
     data.append(declaration+"\n")
     file = dummy()
     file.write = data.append
     ET.ElementTree(element).write(file, encoding, method=method)
     return "".join(data)
# Working example
xdec = """<?xml version="1.0" encoding="UTF-8" standalone="no" ?>"""    
xml = tostring(document, encoding='utf-8', declaration=xdec)
0
G M