Skip to main content
 首页 » 编程设计

Python + lxml : how to find the namespace of a tag

2025年05月04日15tintown

我正在用 python + lxml 处理一些 HTML 文件。其中一些已经用 MS Word 编辑过,我们有 <p>标记为 <o:p>&nbsp</o:p>例如。 IE 和 Firefox 不会将这些 MS 标签解释为真实的 <p>标签,<o:p>前后不显示换行符标签,这就是原始编辑器格式化文件的方式,例如nbsp 周围没有空格。

另一方面,lxml 是整洁的,在处理 HTML 文件后,我们看到所有 <o:p>标签已更改为正确的 <p>标签。不幸的是,在整理之后,两个浏览器现在都会在所有 nbsp 周围显示换行符,这会破坏原始格式。

所以,我的想法是浏览所有这些 <o:p>标签并删除它们或将它们的 .text 属性添加到父 .text 属性,即删除 <o:p>标签标记。

from lxml import etree 
import lxml.html 
from StringIO import StringIO 
 
s='<p>somepara</p> <o:p>msoffice_para</o:p>' 
 
parser = lxml.html.HTMLParser() 
html=lxml.html.parse( StringIO( s), parser) 
 
for t in html.xpath( "//p"): 
     print "tag: " + t.tag + ",  text: '" + t.text + "'" 

结果是:

tag: p,  text: 'somepara' 
tag: p,  text: 'msoffice_para' 

因此,lxlm 从标签标记中删除命名空间名称。有没有办法知道哪个<p>标签来自哪个命名空间,所以我只删除带有 <o:p> 的标签?

谢谢。

请您参考如下方法:

来自 HTML 规范:“The HTML syntax does not support namespace declarations”。 所以我认为 lxml.html.HTMLParser 删除/忽略了命名空间。

但是,BeautifulSoup 以不同的方式解析 HTML,因此我认为它可能值得一试。如果您还安装了 BeautifulSoup,则可以像这样将 BeautifulSoup 解析器与 lxml 一起使用:

import lxml.html.soupparser as soupparser 
import lxml.html 
import io 
s='<p>somepara</p> <o:p>msoffice_para</o:p>' 
html=soupparser.parse(io.BytesIO(s))  

BeautifulSoup 不会删除命名空间,但它也不会识别命名空间本身。相反,它只是标签名称的一部分。

也就是说,

html.xpath('//o:p',namespaces={'o':'foo'}) 

不起作用。但是这个解决方法/黑客

for t in html.xpath('//*[name()="o:p"]'):     
    print "tag: " + t.tag + ",  text: '" + t.text + "'" 

产量

tag: o:p,  text: 'msoffice_para'