[英]insert tags in ElementTree text
我正在使用Python ElementTree模塊來操作HTML。 我想強調某些詞,我目前的解決方案是:
for e in tree.getiterator():
for attr in 'text', 'tail':
words = (getattr(e, attr) or '').split()
change = False
for i, word in enumerate(words):
word = clean_word.sub('', word)
if word.lower() in glossary:
change = True
words[i] = word.replace(word, '<b>' + word + '</b>')
if change:
setattr(e, attr, ' '.join(words))
以上內容考察了每個元素的文本,並強調了它所發現的重要詞匯。 然而,它通過在文本屬性中嵌入HTML標記來實現這一點,在渲染時會對其進行轉義,因此我需要使用以下方法進行計數:
html = etree.tostring(tree).replace('>', '>').replace('<', '<')
這讓我感到不舒服,所以我想要做得恰到好處。 然而,為了嵌入一個新元素,我需要轉換'text'和'tail'屬性,以便強調文本出現在同一位置。 如上所述進行迭代時,這將非常棘手。
任何建議如何正確地做到這一點將不勝感激。 我確信我在API中遺漏了一些東西!
您還可以使用xslt和自定義xpath函數來執行此操作。
下面顯示的是一個例子。 它仍然需要一些工作,例如在元素末尾清理額外的空格並處理混合文本,但這是另一個想法。
鑒於此輸入:
<html>
<head>
</head>
<body>
<p>here is some text to bold</p>
<p>and some more</p>
</body>
</html>
和詞匯表包含兩個詞: some,bold
那么示例輸出是:
<?xml version="1.0"?>
<html>
<head/>
<body>
<p>here is <b>some</b> text to <b>bold</b> </p>
<p>and <b>some</b> more </p>
</body>
</html>
這是代碼,我也發布在http://bkc.pastebin.com/f545a8e1d
from lxml import etree
stylesheet = etree.XML("""
<xsl:stylesheet version="1.0"
xmlns:btest="uri:bolder"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*">
<xsl:copy />
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name(.)}">
<xsl:copy-of select="@*" />
<xsl:apply-templates select="text()" />
<xsl:apply-templates select="./*" />
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:copy-of select="btest:bolder(.)/node()" />
</xsl:template>
</xsl:stylesheet>
""")
glossary = ['some', 'bold']
def bolder(context, s):
results = []
r = None
for word in s[0].split():
if word in glossary:
if r is not None:
results.append(r)
r = etree.Element('r')
b = etree.SubElement(r, 'b')
b.text = word
b.tail = ' '
results.append(r)
r = None
else:
if r is None:
r = etree.Element('r')
r.text = '%s%s ' % (r.text or '', word)
if r is not None:
results.append(r)
return results
def test():
ns = etree.FunctionNamespace('uri:bolder') # register global namespace
ns['bolder'] = bolder # define function in new global namespace
transform = etree.XSLT(stylesheet)
print str(transform(etree.XML("""<html><head></head><body><p>here is some text to bold</p><p>and some more</p></body></html>""")))
if __name__ == "__main__":
test()
盡管ElementTree非常易於用於大多數XML處理任務,但它對於混合內容也很不方便。 我建議使用DOM解析器:
from xml.dom import minidom
import re
ws_split = re.compile(r'\s+', re.U).split
def processNode(parent):
doc = parent.ownerDocument
for node in parent.childNodes[:]:
if node.nodeType==node.TEXT_NODE:
words = ws_split(node.nodeValue)
new_words = []
changed = False
for word in words:
if word in glossary:
text = ' '.join(new_words+[''])
parent.insertBefore(doc.createTextNode(text), node)
b = doc.createElement('b')
b.appendChild(doc.createTextNode(word))
parent.insertBefore(b, node)
new_words = ['']
changed = True
else:
new_words.append(word)
if changed:
text = ' '.join(new_words)
print text
parent.replaceChild(doc.createTextNode(text), node)
else:
processNode(node)
我還使用正則表達式來分割單詞以避免它們粘在一起:
>>> ' '.join(ws_split('a b '))
'a b '
>>> ' '.join('a b '.split())
'a b'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.