我正在解析XML格式的文档,该文档支持一些类似HTML的标记,包括内联格式标记。我想以正常方式解析所有标签,但不解析p
标签的内容,因此我可以以结构感知的方式使用结构化数据,并退回纯文本操作以获取文本内容和格式。例如
<root>
<data1><field1>qwerty</field1> <field2>qwerty</field2> </data1>
<body>
<p>Lorem ipsum</p>
<p>Dolor <a href="http://example.com">sit</a> <em><strong>amet</strong> consectetuer</em></p>
</body>
</root>
应该导致一棵树,其中根元素包含一个data1元素和一个body元素; data1元素包含field1和field2元素(应删除这些标签之后的空格); body元素包含2个p元素,但p个元素(全部)不包含任何子标记,并将其全部内容公开为文本字符串。
即给定第二个p标签对象,我希望满足以下条件:
p.text == 'Dolor <a href="http://example.com">sit</a> <em><strong>amet</strong> consectetuer'
这是否要通过“将ap标签中包含的所有内容作为纯文本处理”或“将a,em和strong标签作为任何地方的纯文本处理”都没有关系尽管我对同时了解这两种方式都很感兴趣。
实际上,提到的标签并不是唯一相关的标签,我需要能够指定该原理将适用的标签的名称。
如何在Python中以这种方式解析XML?
使用哪个XML库对我来说都没有关系。我以前从未在Python中使用过XML,到目前为止还没有选择XML。我现在正在使用lxml(因为我已经读过它可以自动解码ASCII文件并具有更好的XPath支持,它也不会像ElementTree那样与名称空间快捷方式混为一谈),但是它们太多了(ElementTree,MiniDOM,lxml ,Untangle,BeautifulSoup等),我真的不知道哪个更适合我。顺便说一句,无论谁知道Python XML库的比较好概述,如果您能在评论中共享指向它的链接,我将不胜感激。
答案 0 :(得分:0)
这里
import xml.etree.ElementTree as ET
xml = '''<root>
<data1><field1>qwerty</field1> <field2>qwerty</field2> </data1>
<body>
<p>Lorem ipsum</p>
<p>Dolor <a href="http://example.com">sit</a> <em><strong>amet</strong> consectetuer</em></p>
</body>
</root>'''
TEST_STRINGS = ['<p>Lorem ipsum</p>',
'<p>Dolor <a href="http://example.com">sit</a> <em><strong>amet</strong> consectetuer</em></p>']
def _add_text_before_traversing_tree(e):
return e.tag in ['p']
def _handle_attrib(attrib):
result = ''
for k, v in attrib.items():
result += '{}="{}"'.format(k, v)
return ' ' + result if result else ''
def _element_to_text(e, tree_fragments):
tree_fragments.append('<{}'.format(e.tag))
if not e.attrib:
tree_fragments.append('>')
tree_fragments.append(_handle_attrib(e.attrib))
add_text_now = _add_text_before_traversing_tree(e)
if add_text_now:
tree_fragments.append(e.text if e.text else '')
for child in list(e):
_element_to_text(child, tree_fragments)
if not add_text_now:
if not e.attrib:
tree_fragments.append(e.text if e.text else '')
else:
tree_fragments.append('>' + e.text if e.text else '')
tree_fragments.append('</{}>'.format(e.tag))
tree_fragments.append(e.tail.strip() if e.tail else '')
def element_to_text(e):
""" Traverse element tree and return a string representation of the tree"""
tree_fragments = []
_element_to_text(e, tree_fragments)
tree_fragments = [x for x in tree_fragments if len(x) > 0]
return ''.join(tree_fragments)
root = ET.fromstring(xml)
p_elements = root.findall('./body/p')
for idx, p in enumerate(p_elements):
element_as_text = element_to_text(p)
print('Original text : ' + TEST_STRINGS[idx])
print('Element as text: ' + element_as_text)
print('')
# now you need to create a new element,
# attach it to the parent element ('body'),
# set its new text and remove the current element
输出
Original text : <p>Lorem ipsum</p>
Element as text: <p>Lorem ipsum</p>
Original text : <p>Dolor <a href="http://example.com">sit</a> <em><strong>amet</strong> consectetuer</em></p>
Element as text: <p>Dolor <a href="http://example.com">sit</a><em><strong>amet</strong>consectetuer</em></p>