11

也就是说,所有文本和子标签,没有元素本身的标签?

<p>blah <b>bleh</b> blih</p>

我想

blah <b>bleh</b> blih

element.text 返回“blah”并且 etree.tostring(element) 返回:

<p>blah <b>bleh</b> blih</p>
4

7 回答 7

11

ElementTree 完美运行,您必须自己组装答案。像这样的东西...

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

感谢 JV amd 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'
>>> 

不需要尾巴。

于 2008-12-19T11:21:52.900 回答
8

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

def element_to_string(element):
    s = element.text or ""
    for sub_element in element:
        s += etree.tostring(sub_element)
    s += element.tail
    return s
于 2008-12-19T17:27:09.257 回答
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 ))

要获取有关原始文本之间边界的所有详细信息:

class holder: pass # this is just a way of creating a holder object
holder.element_count = 0
def get_deep_text_w_boundaries(element, depth = 0):
    holder.element_count += 1
    element_no = holder.element_count 
    indent = depth * '  '
    text1 = f'{indent}(el {element_no} tag {element.tag}: text |{element.text or ""}| - attribs: {element.attrib})' 
    print(text1)
    for subelement in element:
        get_deep_text_w_boundaries(subelement, depth + 1)
    text2 = f'{indent}(el {element_no} tag {element.tag} - tail: |{element.tail or ""}|)' 
    print(text2)
get_deep_text_w_boundaries(etree_element)

示例输出:

(el 1 tag source: text |DEVANT LE | - attribs: {})
  (el 2 tag g: text |TRIBUNAL JUDICIAIRE| - attribs: {'style_no': '3'})
  (el 2 tag g - tail: ||)
(el 1 tag source - tail: | DE VERSAILLES|)
于 2015-12-04T09:29:26.607 回答
2

我怀疑 ElementTree 是用来做这个的。但是假设您有充分的理由使用它,也许您可​​以尝试从片段中剥离根标签:

 re.sub(r'(^<%s\b.*?>|</%s\b.*?>$)' % (element.tag, element.tag), '', ElementTree.tostring(element))
于 2008-12-19T11:56:30.373 回答
1

这里的大部分答案都是基于 XML parser的ElementTree,即使PEZ 的基于正则表达式的答案仍然部分依赖于 ElementTree。

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

于 2018-02-21T01:32:18.073 回答
0

这个答案稍微修改了Pupeno 的回复。在这里,我将编码类型添加到“tostring”中。这个问题花了我好几个小时。我希望这个小修正能帮助其他人。

def element_to_string(element):
        s = element.text or ""
        for sub_element in element:
            s += ElementTree.tostring(sub_element, encoding='unicode')
        s += element.tail
        return s
于 2020-07-21T00:06:21.657 回答
-4

不知道是否可以选择外部库,但无论如何——假设<p>页面上有一个带有此文本的库,则 jQuery 解决方案将是:

alert($('p').html()); // returns blah <b>bleh</b> blih
于 2008-12-19T11:23:59.523 回答