Python + lxml:如何找到标签的名称空间?
我正在用python + lxml处理一些HTML文件。其中一些已经使用MS Word编辑过,我们有<p>
标签,例如<o:p> </o:p>
。 IE和Firefox不会将这些MS标记解释为真正的<p>
标记,并且不会在<o:p>
标记之前和之后显示换行符,这就是原始编辑者对文件进行格式化的方式。 nbsp的周围没有空格。Python + lxml:如何找到标签的名称空间?
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'
如果实际上是良好形成的HTML,你可以使用etree.XMLParser
代替。否则,请尝试unutbu的答案。