无论我是构建树还是解析文件,lxml find 方法的运行方式都不同

lxml find method operates differently whether I'm building a tree or parsing a file

我正在编写一些 Python 代码,有时会从头开始构建 xml 树,有时会解析现有的 xml 并更新或报告它。我遇到的问题是 lxml find 和 findall 方法的操作似乎不同,这取决于我是在内存中构建树,还是从文件中解析它。命名空间似乎是问题所在。名称空间在根元素处定义(无前缀)。当我在内存中构造的树中的元素上使用查找时,将名称空间关键字与根 nsmap 添加会导致搜索不返回任何内容,但是当省略它时 returns 预期结果。但是,当从文件解析树时,情况恰恰相反。

编辑:我想我在这里缺少的是我需要明确地向 child 元素添加命名空间。 代码在这里分享有点冗长,但我已经在下面的一个粗略的片段中复制了这个问题。

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)

如果您 运行 上面的一次,它将找到标题元素并使用未命名空间的查找打印值。但是如果你再次 运行 它,它只会使用命名空间查找来查找标题元素。我在这里失踪了吗?

编辑:我想我缺少的是我需要在构建树时明确地将名称空间添加到 child 元素。

您需要在与 DC.

相同的命名空间中创建 title 子元素

我平时用的是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"