在 lxml 中定义默认命名空间(无前缀)

Jon*_*fer 2 python xslt xhtml lxml namespaces

使用 lxml 渲染 XHTML 时,一切都很好,除非您碰巧使用 Firefox,它似乎无法处理以命名空间为前缀的 XHTML 元素和 javascript。虽然Opera是能够执行JavaScript(这适用于jQuery和MathJax)的罚款,无论XHTML命名空间是否具有前缀(h:在我的情况)或没有,Firefox中的脚本将用奇怪的错误(中止this.head是未定义的MathJax 的情况)。

我知道这个register_namespace函数,但它既不接受None也不""作为命名空间前缀。我_namespace_maplxml.etree模块中听说过,但是我的 Python 抱怨这个属性不存在(版本问题?)

有没有其他方法可以删除 XHTML 名称空间的名称空间前缀?请注意str.replace,正如在另一个相关问题的回答中所建议的那样,不是我可以接受的方法,因为它不知道 XML 语义并且可能很容易搞砸结果文档。

根据请求,您会发现两个可以使用的示例。一种带有命名空间前缀一种没有. 第一个将在 Firefox 中显示 0(错误),第二个将显示 1(正确)。Opera 将正确呈现两者。这显然是一个 Firefox 错误,但这只是作为想要使用 lxml 的无前缀 XHTML 的一个基本原理——还有其他很好的理由来减少移动客户端的流量等(h:如果你考虑数十或数百个 html 标签,甚至很多) .

nei*_*owj 8

使用ElementMaker并给它一个nsmap映射None到您的默认命名空间的。

#!/usr/bin/env python
# dogeml.py

from lxml.builder import ElementMaker
from lxml import etree

E = ElementMaker(
    nsmap={
        None: "http://wow/"    # <--- This is the special sauce
    }
)

doge = E.doge(
    E.such('markup'),
    E.many('very namespaced', syntax="tricks")
)

options = {
    'pretty_print': True,
    'xml_declaration': True,
    'encoding': 'UTF-8',
}

serialized_bytes = etree.tostring(doge, **options)
print(serialized_bytes.decode(options['encoding']))
Run Code Online (Sandbox Code Playgroud)

正如您在此脚本的输出中所见,默认命名空间已定义,但标记没有前缀。

<?xml version='1.0' encoding='UTF-8'?>
<doge xmlns="http://wow/">
   <such>markup</such>
   <many syntax="tricks">very namespaced</many>
</doge>
Run Code Online (Sandbox Code Playgroud)

我已经用 Python 2.7.6、3.3.5 和 3.4.0 以及 lxml 3.3.1 测试了这段代码。