lxml.builder.e() 是 elementmaker 实例的快捷调用方式,需显式导入初始化;支持 html 语义、命名空间配置和属性设置(klass代替class),但不自动缩进、不支持 css 缩写,参数顺序严格决定结构,深层嵌套性能较差。

lxml.builder.E() 和 E-factory 本质是同一套机制
用 E() 构建 HTML/XML 元素时,背后其实是 lxml.builder.ElementMaker 实例在工作。所谓 “E-factory”,就是你手动创建的 ElementMaker 对象(比如 E = ElementMaker()),而 E() 是它的调用方式。别被名字绕晕——它不是独立模块,也不是新语法糖,只是函数式写法的快捷入口。
常见错误现象:NameError: name 'E' is not defined,或者构建出的元素没有命名空间、属性丢失、文本内容被忽略。
- 必须显式导入并初始化:先
from lxml.builder import ElementMaker,再E = ElementMaker();直接用E()不会自动存在 - 如果需要 HTML 语义(如自闭合
<img>、<br>),得传html=True:E = ElementMaker(html=True),否则<br>会被当成普通标签,生成<br> - 不支持 CSS 类名缩写(如
div.my-class);那是 PyQuery 或 lxml.cssselect 的事,E()只认关键字参数:E.div(klass="my-class")(注意是klass,不是class,因为class是 Python 关键字)
text、tail 和嵌套子元素的顺序必须手动控制
E() 的调用参数顺序直接影响 XML/HTML 结构:第一个字符串参数是 element 的 text,关键字参数生成属性,而子元素必须作为额外位置参数传入(不能放在字符串后面)。
常见错误现象:文字跑到标签外、换行错乱、<p>Hello<span>world</span>!</p> 变成 <p>Hello!<span>world</span></p>。
- 正确写法:
E.p("Hello", E.span("world"), "!")→<p>Hello<span>world</span>!</p> - 错误写法:
E.p("Hello", "!", E.span("world"))→<p>Hello!<span>world</span></p>(因为"!"成了<p></p>的tail,而非text) - 想加换行或空格?只能显式写进字符串里:
E.div("\n ", E.span("content"), "\n");E()不做格式美化,也不自动缩进
命名空间和前缀支持弱,容易漏掉 xmlns 声明
用 E() 构建带命名空间的 XML(如 SVG、Atom)时,xmlns 属性不会自动提升为文档级声明,而是挂在每个元素上,导致冗余甚至解析失败。
常见错误现象:生成的 SVG 在浏览器中不渲染;XML 解析器报 Namespace prefix 'svg' not declared。
- 必须手动传入命名空间映射:
E = ElementMaker(nsmap={None: "http://www.w3.org/2000/svg"})(设默认命名空间) - 如果要用前缀(如
svg:circle),得同时定义nsmap={"svg": "http://www.w3.org/2000/svg"},然后用E.svg.circle() - 注意:
nsmap只影响当前ElementMaker实例创建的元素,不递归作用于子元素;若子元素也需同命名空间,仍要靠E.svg.xxx调用,不能只靠父元素带入
性能敏感场景慎用链式 E() 构建深层结构
单次 E() 调用开销不大,但嵌套过深(比如 10 层以上)+ 大量重复调用时,对象创建和参数解析成本会明显高于直接用 etree.Element() 手动构造。
使用场景:适合模板化、结构固定、可读性优先的 HTML 片段生成(如邮件模板、API 返回的简单 HTML);不适合高频、流式、动态深度的 XML 组装(如日志聚合、实时消息封装)。
- 实测差异:1000 次
E.html(E.body(E.div("x")))比等价的etree.Element("html"); body = etree.SubElement(html, "body"); div = etree.SubElement(body, "div"); div.text = "x"慢约 2.5 倍 - 如果已有 etree 元素对象,别硬套
E():直接用etree.SubElement(parent, "tag", attrib={...})更轻量 -
E()不缓存元素类、不复用对象,每次都是新实例——这点在内存受限环境(如嵌入式脚本)里值得留意
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










