Подтвердить что ты не робот

Как написать объявление XML с помощью xml.etree.ElementTree

Я генерирую XML-документ в Python, используя ElementTree, но функция 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" ?>

Тем не менее, похоже, нет никакого документированного способа сделать это.

Есть ли правильный метод для рендеринга декларации XML в ElementTree?

4b9b3361

Ответ 1

Я с удивлением обнаружил, что с 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

См. этот вопрос. Даже тогда я не думаю, что вы можете получить свой "автономный" атрибут, не нажимая заранее его.

Ответ 2

Я бы использовал 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))

Ответ 3

Если вы включите encoding='utf8', вы получите заголовок XML:

xml.etree.ElementTree.tostring записывает объявление кодировки XML с encoding = 'utf8'

Пример кода 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>"

Ответ 4

Я столкнулся с этой проблемой недавно, после некоторого копания кода я нашел следующий фрагмент кода - это определение функции 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 в свой файл, установите аргумент encoding, отличный от utf-8 или us-ascii, например. utf-8

Ответ 5

Минимальный рабочий пример использования пакета 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>

Ответ 6

Я бы использовал 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))

Ответ 7

Это работает, если вы просто хотите распечатать. Получение ошибки при попытке отправить ее в файл...

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="  ")

Ответ 8

Включая "автономный" в декларации

Я не нашел альтернативы для добавления 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)

Ответ 9

Другой довольно простой вариант - объединить нужный заголовок со строкой 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)