Метод l xml find работает по-разному, собираю ли я дерево или анализирую файл - PullRequest
0 голосов
/ 22 апреля 2020

Я пишу некоторый код Python, который иногда создает дерево xml с нуля, а иногда анализирует существующий xml и обновляет его или сообщает о нем. У меня проблема в том, что методы l xml find и findall работают по-разному в зависимости от того, построил ли я дерево в памяти или проанализировал его из файла. Пространства имен, кажется, проблема. Пространство имен определено в элементе root (без префиксов). Когда я использую поиск для элемента из дерева, созданного в памяти, добавление ключевого слова namespaces с root nsmap приводит к поискам, которые ничего не возвращают, но если опущен, он возвращает ожидаемый результат. Однако когда дерево анализируется из файла, происходит обратное.

Редактировать: я думаю, что мне здесь не хватает, мне нужно явно добавить пространства имен в дочерние элементы. Этот код немного многословен для совместного использования здесь, но я повторил проблему в простом фрагменте ниже.

from lxml import etree
import os

fname = 'test.xml'
if os.path.exists(fname):
    root = etree.parse(fname).getroot()
    try:
        print('no namespaces -', root.find('title').text) #this doesn't work
    except AttributeError as e:
        print(e)
    try:
        print('namespaced -', root.find('title', namespaces=root.nsmap).text) #this works
    except AttributeError as e:
        print(e)
else:
    root = etree.Element(
        'DC',
        nsmap={None: "http://purl.org/dc/elements/1.1/"})
    etree.SubElement(root, 'title').text = "A title"
    try:
        print('no namespaces -', root.find('title').text) #this works
    except AttributeError as e:
        print(e)
    try:
        print('namespaced -', root.find('title', namespaces=root.nsmap).text) #this doesn't work
    except AttributeError as e:
        print(e)
    tree = etree.ElementTree(root)
    tree.write(fname)

Если вы запустите приведенный выше код один раз, он найдет элемент title и напечатает значение, используя находка без имени. Но если вы запустите его снова, он найдет только элемент title, используя поиск по пространству имен. Я здесь отсутствует?

Редактировать: я думаю, что мне не хватает, мне нужно явно добавить пространства имен к дочерним элементам при построении дерева.

1 Ответ

2 голосов
/ 22 апреля 2020

Вам необходимо создать ваш субэлемент title в том же пространстве имен, что и DC.

. Обычно я использую etree.QName().

Попробуйте изменить это:

etree.SubElement(root, 'title').text = "A title"

на это:

etree.SubElement(root, etree.QName("{http://purl.org/dc/elements/1.1/}title")).text = "A title"
...