Python + lxml:如何找到标签的命名空间?

时间:2011-09-05 14:10:39

标签: python namespaces lxml

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

另一方面,

lxml很整洁,在处理完HTML文件后,我们发现所有<o:p>标记都已更改为正确的<p>标记。不幸的是,在整理完两个浏览器之后,现在会在所有的浏览器周围显示换行符,这会打破原始格式。

所以,我的想法是浏览所有这些<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>的标记?

感谢。

2 个答案:

答案 0 :(得分:1)

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

然而,BeautifulSoup以不同的方式解析HTML,所以我认为它可能值得一试。如果你还安装了BeautifulSoup,你可以像这样使用带有lxml的BeautifulSoup解析器:

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'

答案 1 :(得分:0)

如果html实际上格式正确,您可以使用etree.XMLParser代替。否则,试试unutbu的答案。