创建时向 lxml.etree.Element 添加尾巴

Adding a tail to lxml.etree.Element upon creation

我知道我可以对一个元素进行如下操作:

tag = ET.Element(category, attrib=new_tag)
tag.tail= '\n'

是否可以在实例化的时候添加?例如:

ET.Element(category, attrib=new_tag, tail='\n') # adds a "tail" attribute instead.

不幸的是,这是不可能的。查看实际的源代码,这个 Element 构建方法包含在文件 lxml.etree.pyx 中并且很简单(没有文档字符串)

def Element(_tag, attrib=None, nsmap=None, **_extra):
    return _makeElement(_tag, NULL, None, None, None, None, attrib, nsmap, _extra)

追踪这个_makeElement方法,我们在apihelpers.pxi中找到它,声明为

cdef _Element _makeElement(tag, xmlDoc* c_doc, _Document doc,
                       _BaseParser parser, text, tail, attrib, nsmap,
                       dict extra_attrs):

因此,行为与 ElementTree 中的行为完全相同,我们可以定义一个标签名称、一个属性字典、一个命名空间映射(这与 Element Tree 不同),以及一个附加属性列表,这些属性将被添加到属性映射。这里要注意的一件事是,Element 构造函数在 lxml 中作为函数提供,这与 ElementTree 的等效函数 class.

不同。

Element 函数不能接受任何额外的位置参数,任何额外的关键字参数都用作元素中的属性。根本没有办法将 tail 的值传递给元素构造函数。 _makeElement 方法是私有 api 的一部分,没有简单的方法来访问它,但如果可以访问它,这可以提供一种方法来做到这一点(注意这个函数有一个值尾巴)。


当然,如果我们需要这样的功能,我们没有理由不写一个函数来实现。

def TailedElement(tag,attrib=None,nsmap=None,tail=None,**extra):
        x = ET.Element(tag,attrib,nsmap,**extra)
        x.tail = tail
        return x

演示这个,

test = TailedElement("testel",{"testing":"yes"},tail="Tail Value")
ET.tostring(test)
# b'<testel testing="yes"/>Tail Value'

这个有一个小的trade-off。我们不能再将名为 tail 的属性指定为额外的命名参数。但是,我们仍然可以通过将其添加到属性映射来指定它。