Рубрики
Без рубрики

Python: Создание XML с LXML.Objectify

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Sub-пакет LXML.Objectify чрезвычайно удобно для анализа и создания XML. В этой статье мы покажем, как создать XML с помощью пакета LXML. Начнем с некоторых простых XML, а затем попробуйте повторить его. Давайте начнем!

В прошлых статьях я использовал следующий глупый пример XML для демонстрационных целей:



    
        1181251680
        040000008200E000
        1181572063
        
        
        1800
        Bring pizza home
    
    
        1234360800
        1800
        Check MS Office website for updates
        
        604f4792-eb89-478b-a14f-dd34d3cc6c21-1234360800
        dismissed
  

Давайте посмотрим, как мы можем использовать LXML.Objectify, чтобы воссоздать этот XML:

from lxml import etree, objectify

#----------------------------------------------------------------------
def create_appt(data):
    """
    Create an appointment XML element
    """
    appt = objectify.Element("appointment")
    appt.begin = data["begin"]
    appt.uid = data["uid"]
    appt.alarmTime = data["alarmTime"]
    appt.state = data["state"]
    appt.location = data["location"]
    appt.duration = data["duration"]
    appt.subject = data["subject"]
    return appt

#----------------------------------------------------------------------
def create_xml():
    """
    Create an XML file
    """
    
    xml = '''
    
    
    '''
        
    root = objectify.fromstring(xml)
    root.set("reminder", "15")
    
    appt = create_appt({"begin":1181251680,
                        "uid":"040000008200E000",
                        "alarmTime":1181572063,
                        "state":"",
                        "location":"",
                        "duration":1800,
                        "subject":"Bring pizza home"}
                       )
    root.append(appt)
    
    uid = "604f4792-eb89-478b-a14f-dd34d3cc6c21-1234360800"
    appt = create_appt({"begin":1234360800,
                        "uid":uid,
                        "alarmTime":1181572063,
                        "state":"dismissed",
                        "location":"",
                        "duration":1800,
                        "subject":"Check MS Office website for updates"}
                       )
    root.append(appt)
    
    # remove lxml annotation
    objectify.deannotate(root)
    etree.cleanup_namespaces(root)
    
    # create the xml string
    obj_xml = etree.tostring(root,
                             pretty_print=True,
                             xml_declaration=True)
    
    try:
        with open("example.xml", "wb") as xml_writer:
            xml_writer.write(obj_xml)
    except IOError:
        pass
    
#----------------------------------------------------------------------
if __name__ == "__main__":
    create_xml()

Давайте немного сломаемся. Начнем с create_xml функция. В нем мы создаем корневой объект XML, используя объектный модуль отстроитель функция. Корневой объект будет содержать Zappointment как его тег. Мы устанавливаем root Напоминание атрибут, а затем мы называем нашими create_appt Функция с использованием словаря для его аргумента. В create_appt Функция, мы создаем экземпляр элемента (технически, это объективируют ), которые мы присваиваем нашему appt Переменная. Здесь мы используем dot-notation для создания тегов для этого элемента. Наконец мы возвращаем элемент APPT и добавьте его на наш корень объект. Мы повторяем процесс для второй экземпляра назначения.

Следующий раздел create_xml Функция удалит аннотацию LXML. Если вы этого не сделаете, вы XML в конечном итоге выглядят следующим образом:


    
        1181251680
        040000008200E000
        1181572063
        
        
        1800
        Bring pizza home
    
        1234360800
        604f4792-eb89-478b-a14f-dd34d3cc6c21-1234360800
        1181572063
        dismissed
        
        1800
        Check MS Office website for updates
    

Чтобы удалить всю эту нежелательную аннотацию, мы называем следующие две функции:

objectify.deannotate(root)
etree.cleanup_namespaces(root)

Последняя часть головоломки состоит в том, чтобы получить LXML для генерации самого XML. Здесь мы используем модуль Etree LXML, чтобы сделать тяжелую работу:

obj_xml = etree.tostring(root, pretty_print=True)

TOSTRING Функция вернет хорошую строку XML и если вы установите Pretty_Print true, он обычно возвращает XML в приятный формат тоже.

Обновление 11/2020 для Python 3

Код в предыдущем разделе не выводится на «предел» XML в файл в Python 3. Вы должны перейти через пару обручей, чтобы сделать его правильно. Вот обновленная версия кода, которая делает работу. Проверено в Python 3.9 на Mac OS :

from lxml import etree, objectify
from io import BytesIO

def create_appt(data):
    """
    Create an appointment XML element
    """
    appt = objectify.Element("appointment")
    appt.begin = data["begin"]
    appt.uid = data["uid"]
    appt.alarmTime = data["alarmTime"]
    appt.state = data["state"]
    appt.location = data["location"]
    appt.duration = data["duration"]
    appt.subject = data["subject"]
    return appt


def create_xml():
    """
    Create an XML file
    """
    
    xml = '''
    
    
    '''
        
    root = objectify.fromstring(xml)
    root.set("reminder", "15")
    
    appt = create_appt({"begin":1181251680,
                        "uid":"040000008200E000",
                        "alarmTime":1181572063,
                        "state":"",
                        "location":"",
                        "duration":1800,
                        "subject":"Bring pizza home"}
                       )
    root.append(appt)
    
    uid = "604f4792-eb89-478b-a14f-dd34d3cc6c21-1234360800"
    appt = create_appt({"begin":1234360800,
                        "uid":uid,
                        "alarmTime":1181572063,
                        "state":"dismissed",
                        "location":"",
                        "duration":1800,
                        "subject":"Check MS Office website for updates"}
                       )
    root.append(appt)
    
    # remove lxml annotation
    objectify.deannotate(root)
    etree.cleanup_namespaces(root)
    
    # create the xml string
    parser = etree.XMLParser(remove_blank_text=True)
    file_obj = BytesIO(etree.tostring(root))
    tree = etree.parse(file_obj, parser)
    
    try:
        with open("example.xml", "wb") as xml_writer:
            tree.write(xml_writer, pretty_print=True)
    except IOError:
        pass
    
if __name__ == "__main__":
    create_xml()

Это основано на решении, найденном на Stackoverflow Отказ

Вам нужно добавить новый импорт в верхней части файла, чтобы получить Bytesio Отказ Затем в конце вашего кода вам нужно изменить свой код, чтобы выглядеть так:

# create the xml string
parser = etree.XMLParser(remove_blank_text=True)
file_obj = BytesIO(etree.tostring(root))
tree = etree.parse(file_obj, parser)

try:
    with open("example.xml", "wb") as xml_writer:
        tree.write(xml_writer, pretty_print=True)
except IOError:
    pass

Это добавляет новый объект XML Parser, который удаляет пустой текст от вашего корня. Это произойдет после того, как вы поверните рут в байтовую строку, которая сама по себе превратилась в файловый объект, используя Bytesio. Дайте ему выстрел, и вы должны в конечном итоге с файлом, который содержит должным образом отступом XML-код.

Обертывание

Теперь вы знаете, как использовать объектный модуль LXML для создания XML. Это довольно удобный интерфейс и довольно питон по большей части.

Связанное чтение

  • Разбор XML с Python с использованием LXML.Objectify
  • Python: Разборка XML с lxml.etree
  • Python 101 – Intro на XML разбор с ElectionTree