lxml.builder.e.method 默认生成自闭合标签(如),仅当传入文本、子元素或空字符串时才生成非自闭合形式;属性须用字典或**kwargs传入,子节点须为位置参数;不支持tail、cdata、动态命名空间前缀需谨慎处理。

lxml.builder.E.method 为什么生成的 XML 没有闭合标签?
因为 E.method 默认生成的是自闭合元素(empty element),比如 <method></method>,而不是 <method></method> 或带内容的标签。这不是 bug,是 lxml.builder 的设计逻辑:只有传入子节点或文本时,才会展开为非自闭合形式。
- 空调用
E.method()→<method></method> - 加文本
E.method("hello")→<method>hello</method> - 加子元素
E.method(E.arg("1"))→<method><arg>1</arg></method> - 想强制非自闭合但无内容?得显式传空字符串:
E.method("")→<method></method>
如何给 E.method 添加属性和嵌套结构?
属性通过关键字参数传入,嵌套靠函数调用链;但要注意顺序和类型——属性必须在最外层指定,子节点必须作为位置参数或嵌套调用传入,不能混在 kwargs 里。
- 正确:
E.method({"id": "123"}, E.arg("val"))→ 属性用字典,子节点用位置参数 - 错误:
E.method(id="123", E.arg("val"))→ 语法错误,kwargs 不能跟位置参数 - 多属性推荐写法:
E.method(**{"xmlns": "http://a.b/c", "id": "x"}) - 混合文本+子节点?不行:
E.method("text", E.child())会报错;只能二选一:纯文本、纯子节点、或用etree.SubElement手动拼
builder.E 和 etree.Element 对比:什么时候别用 E?
当需要动态控制命名空间、处理 CDATA、设置 tail 文本、或复用已有 Element 实例时,E 就不够用了——它本质是快捷工厂,不暴露底层 Element 接口。
-
E无法设置.tail(换行/空格等后置文本) -
E不支持etree.CDATA("script")包裹 - 命名空间前缀需手动声明(如
E["p:method"]),但解析时若没注册 nsmap,序列化可能丢前缀 - 性能上无差异,但调试时
E生成的元素类型仍是etree._Element,可直接传给etree.tostring()
常见报错:TypeError: 'function' object is not subscriptable
这是把 E 当成字典或列表用了,典型误写如 E["method"]() 或 E[0]。实际上 E 是一个 callable 对象,只支持括号调用,不支持中括号索引。
立即学习“Python免费学习笔记(深入)”;
- 错:
E["method"]→ 报这个错 - 对:
E.method(直接点属性名,支持任意合法 XML 标签名) - 动态标签名?用
getattr(E, tag_name)或E.__getattr__(tag_name) - 标签名含特殊字符(如冒号)?必须用
E["p:method"]——但注意这只是语法糖,底层仍走__getitem__,不是所有 lxml 版本都稳定支持
etree.Element。 builder.E 是快,但不是万能胶。










