[lxml find方法无论是在构建树还是在解析文件时,其操作方式都不同

问题描述 投票:0回答:1

我正在编写一些Python代码,有时会从头开始构建xml树,有时会解析现有的xml并对其进行更新或报告。我遇到的问题是lxml find和findall方法的操作方式似乎有所不同,具体取决于我是在内存中构造树还是从文件中解析树。命名空间似乎是个问题。名称空间是在根元素(无前缀)处定义的。当我在内存中构造的树中的元素上使用find时,将namespaces关键字与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元素并使用未命名间隔的find打印该值。但是,如果再次运行它,它将仅使用命名空间的find查找title元素。我在这里想念吗?

编辑:我想我缺少的是在构造树时需要向子元素显式添加名称空间。

python-3.x xml lxml xml-namespaces
1个回答
0
投票

您需要在与title相同的名称空间中创建DC子元素。

我通常要做的是使用etree.QName()

尝试更改此内容:

etree.QName()

至此:

etree.SubElement(root, 'title').text = "A title"
© www.soinside.com 2019 - 2024. All rights reserved.