簡體   English   中英

如何使用 ElementTree 獲取元素的完整 XML 或 HTML 內容?

[英]How do I get the full XML or HTML content of an element using ElementTree?

也就是說,所有的文本和子標簽,沒有元素本身的標簽?

擁有

<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>

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'
>>> 

不需要尾巴。

這是我最終使用的解決方案:

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

這些是很好的答案,可以回答 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 ))

要獲取有關原始文本之間邊界的所有詳細信息:

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 )

LibreOffice Writer 文檔(.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 字符。

當然,這種討論越不以“以英語為中心”,其微妙之處和復雜性就越大!

我懷疑 ElementTree 是否適合用於此目的。 但是假設您有充分的理由使用它,也許您可​​以嘗試從片段中剝離根標記:

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

這里的大多數答案都基於 XML 解析器ElementTree ,即使是PEZ 的基於正則表達式的答案仍然部分依賴於 ElementTree。

所有這些都很好並且適用於大多數用例,但是,為了完整性,值得注意的是, ElementTree.tostring(...)將為您提供等效的代碼段,但並不總是與原始有效負載相同。 如果出於某種非常罕見的原因,您想按原樣提取內容,則必須使用基於正則表達式的純解決方案。 這個例子是我如何使用基於正則表達式的解決方案。

這個答案稍微修改了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

不知道是否可以選擇外部庫,但無論如何 - 假設頁面上有一個帶有此文本的<p> ,jQuery 解決方案將是:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM