python - 如何解析 XML 将特定标签或其内容保留为纯文本?
问题描述
我正在解析一个 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 和强标签视为纯文本,无论它们在哪里”来实现这一点并不重要,尽管我觉得有兴趣了解这两种方式。
事实上,提到的标签并不是唯一相关的,我需要能够指定该原则将适用的标签的名称。
如何在 Python 中以这种方式解析 XML?
使用哪个 XML 库对我来说并不重要。我以前没有在 Python 中使用过 XML,到目前为止也没有选择过。我现在正在使用 lxml(因为我已经阅读过它可以自动解码 ASCII 文件并且具有更好的 XPath 支持,它也不会像 ElementTree 那样混淆命名空间快捷方式)但是其中有很多(ElementTree、MiniDOM、lxml 、Untangle、BeautifulSoup 等)我真的不知道哪个更适合我。顺便说一句,谁知道 Python XML 库的一个很好的比较概述,如果您能在评论中分享指向它的链接,我将不胜感激。
解决方案
这里
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>
推荐阅读
- javascript - 关于 Hyperledger Fabric 的登录注册架构师
- sql - 如果在 Microsoft SQL Server 中未找到任何行,则返回 0
- python - “SQLAlchemy”的实例没有“列”成员
- c# - ItemsControl、ItemContainerStyle 和 ItemTemplate
- python - 导入 ft2font 时 DLL 加载失败:找不到指定的模块
- typo3 - 无法为核心扩展以外的扩展下载语言包
- ios - Swift解码JSON,同一字段有两种可能的类型
- reactjs - React js:TypeError:Object(...)不是函数
- c# - 如何从数据库中获取特定字段?
- javascript - Javascript 将 \\ 替换为 /