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宣言をレンダリングする適切な方法はありますか?
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
この質問 を参照してください。その場合でも、自分で追加することなく「スタンドアロン」属性を取得できるとは思いません。
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))
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>"
最近、この問題に遭遇しました。コードを掘り下げたところ、次のコードスニペットが関数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
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>
[〜#〜] 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))
別の非常に簡単なオプションは、目的のヘッダーを次のように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)
これは、印刷したいだけの場合に機能します。ファイルに送信しようとするとエラーが発生します...
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=" ")
ドキュメントに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)