当使用lxml呈现XHTML时,一切都很好,除非您碰巧使用了Firefox,它似乎无法处理以名称空间为前缀的XHTML元素和javascript。虽然Opera能够很好地执行javascript(这适用于jQuery和MathJax),但无论XHTML名称空间是否有前缀(在我的例子中是h:),在Firefox中,脚本都会因奇怪的错误而中止(在MathJax中是未定义的)。
我知道this.head函数,但它既不接受register_namespace也不接受None作为命名空间前缀。我在""模块中听说过_namespace_map,但是我的Python抱怨这个属性不存在(版本问题?)
有没有其他方法可以删除XHTML名称空间的名称空间前缀?请注意,正如在对另一个相关问题的回答中所建议的那样,lxml.etree不是一个我可以接受的方法,因为它不知道XML语义,并且可能很容易弄糟结果文档。
根据请求,您将找到两个可供使用的示例。其中一个namespace prefixesone without。第一个将在Firefox中显示0(错误),第二个将显示1(正确)。歌剧将使两者都正确。这显然是a Firefox bug,但这仅仅是希望使用lxml的无前缀XHTML的一个理由-还有其他一些很好的理由可以减少移动客户端的流量等(如果考虑到数十或百分之几的html标记,甚至str.replace也是相当多的)。

最佳答案

This XSL transformation删除content中的所有前缀,同时保留根节点中定义的命名空间:

import lxml.etree as ET

content = '''\
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE html>
<h:html xmlns:h="http://www.w3.org/1999/xhtml" xmlns:ml="http://foo">
  <h:head>
    <h:title>MathJax Test Page</h:title>
    <h:script type="text/javascript"><![CDATA[
      function test() {
        alert(document.getElementsByTagName("p").length);
      };
    ]]></h:script>
  </h:head>
  <h:body onload="test();">
    <h:p>test</h:p>
    <ml:foo></ml:foo>
  </h:body>
</h:html>
'''
dom = ET.fromstring(content)

xslt = '''\
<xsl:stylesheet version="1.0"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no"/>

<!-- identity transform for everything else -->
<xsl:template match="/|comment()|processing-instruction()|*|@*">
    <xsl:copy>
      <xsl:apply-templates />
    </xsl:copy>
</xsl:template>

<!-- remove NS from XHTML elements -->
<xsl:template match="*[namespace-uri() = 'http://www.w3.org/1999/xhtml']">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@*|node()" />
    </xsl:element>
</xsl:template>

<!-- remove NS from XHTML attributes -->
<xsl:template match="@*[namespace-uri() = 'http://www.w3.org/1999/xhtml']">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="." />
    </xsl:attribute>
</xsl:template>
</xsl:stylesheet>
'''

xslt_doc = ET.fromstring(xslt)
transform = ET.XSLT(xslt_doc)
dom = transform(dom)

print(ET.tostring(dom, pretty_print = True,
                  encoding = 'utf-8'))

产量
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>MathJax Test Page</title>
    <script type="text/javascript">
      function test() {
        alert(document.getElementsByTagName("p").length);
      };
    </script>
  </head>
  <body onload="test();">
    <p>test</p>
    <ml:foo xmlns:ml="http://foo"/>
  </body>
</html>

07-25 23:11
查看更多