2008-12-19 64 views

回答

5

这是我最终使用的解决方案:

def element_to_string(element): 
    s = element.text or "" 
    for sub_element in element: 
     s += etree.tostring(sub_element) 
    s += element.tail 
    return s 
11

ElementTree的作品完美,你有自己组装答案。像这样的东西...

"".join([ "" if t.text is None else t.text ] + [ xml.tostring(e) for e in t.getchildren() ]) 

感谢合资公司和PEZ指出了错误。


编辑。

>>> import xml.etree.ElementTree as xml 
>>> s= '<p>blah <b>bleh</b> blih</p>\n' 
>>> t=xml.fromstring(s) 
>>> "".join([ t.text ] + [ xml.tostring(e) for e in t.getchildren() ]) 
'blah <b>bleh</b> blih' 
>>> 

尾巴不需要。

+0

只是指出了一个错字 - 方法名 - 我认为应该是“findall”的“finall”。即使findall被使用,它也会导致这个http://pastebin.com/f6de9a841。请修改你的答案。 – 2008-12-19 11:45:49

+0

@JV:谢谢。固定。 – 2008-12-19 12:19:25

-3

不知道,如果一个外部库可能是一种选择,但无论如何 - 假如有一个<p>与页面上的这段文字,一个jQuery的解决办法是:

alert($('p').html()); // returns blah <b>bleh</b> blih 
1

我怀疑ElementTree的是为此使用的东西。但是,假设你有使用它,也许你可以尝试从片段剥离根标签有力的理由:

re.sub(r'(^<%s\b.*?>|</%s\b.*?>$)' % (element.tag, element.tag), '', ElementTree.tostring(element)) 
3

这些都是很好的答案,这回答OP的问题,特别是如果问题仅限于HTML。但文件本质上是混乱的,元素嵌套的深度通常无法预测。

要模拟DOM的getTextContent(),您必须使用(非常)简单的递归机制。

得到的只是光秃秃的文字:

def get_deep_text(element): 
    text = element.text or '' 
    for subelement in element: 
     text += get_deep_text(subelement) 
    text += element.tail or '' 
    return text 
print(get_deep_text(element_of_interest)) 

要获得所有有关原始文本之间的界限的细节:从LibreOffice的作家DOC单对

root_el_of_interest.element_count = 0 
def get_deep_text_w_boundaries(element, depth = 0): 
    root_el_of_interest.element_count += 1 
    element_no = root_el_of_interest.element_count 
    indent = depth * ' ' 
    text1 = '%s(el %d - attribs: %s)\n' % (indent, element_no, element.attrib,) 
    text1 += '%s(el %d - text: |%s|)' % (indent, element_no, element.text or '',) 
    print(text1) 
    for subelement in element: 
     get_deep_text_w_boundaries(subelement, depth + 1) 
    text2 = '%s(el %d - tail: |%s|)' % (indent, element_no, element.tail or '',) 
    print(text2) 
get_deep_text_w_boundaries(root_el_of_interest) 

输出示例(.fodt文件):

(el 1 - attribs: {'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'Standard'}) 
(el 1 - text: |Ci-après individuellement la "|) 
    (el 2 - attribs: {'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'T5'}) 
    (el 2 - text: |Partie|) 
    (el 2 - tail: |" et ensemble les "|) 
    (el 3 - attribs: {'{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name': 'T5'}) 
    (el 3 - text: |Parties|) 
    (el 3 - tail: |", |) 
(el 1 - tail: | 
    |) 

关于混乱的一点是,没有硬性规定和快速规则关于什么时候文本样式表示一个字的边界,什么时候它没有:立即跟在一个字之后的上标(没有空格)意味着我可以想象的所有用例中的一个单独的字。例如,OTOH有时可能会找到一个文件,其中第一个字母由于某种原因被粗体显示,或者可能对第一个字母使用不同的样式来表示为大写字母,而不是简单地使用普通的UC字符。

当然,主要以“以英语为中心”的这种讨论越来越微妙和复杂!

0

这里的大部分答案都基于XML解析器ElementTree,即使PEZ's regex-based answer仍然部分依赖于ElementTree。

所有这些都很好,适合大多数用例,但为了完整起见,值得注意的是,ElementTree.tostring(...)会给你一个等效的片段,但并不总是与原始有效载荷相同。如果出于某种非常罕见的原因想要按原样提取内容,则必须使用纯正则表达式的解决方案。 This example是我如何使用基于正则表达式的解决方案。

相关问题