【问题标题】:How to parse XML leaving particular tags or their contents as plain text?如何解析 XML 将特定标签或其内容保留为纯文本?
【发布时间】:2019-11-05 02:04:41
【问题描述】:

我正在解析一个 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 库的一个很好的比较概述,如果你能在评论中分享它的链接,我将不胜感激。

【问题讨论】:

  • 你可以尝试使用 bs4 beautifulsoup 吗?我已经使用它并得到了那种输出。
  • 是的,它是 html ,但 xml 似乎并没有那么不同。
  • @JainilPatel 也许。谢谢。

标签: python xml


【解决方案1】:

这里

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>

【讨论】:

  • 谢谢。但它会将&lt;a href="http://example.com"&gt;sit&lt;/a&gt; 变成&lt;a&gt;sit href="http://example.com"&lt;/a&gt;
  • @Ivan 错误已修复。如您所见,结构现在很好。唯一的区别是您的原始 HTML 片段带有额外的空格
  • 可爱。谢谢。但是,应该保留空间。 Em/strong 标签本身不插入空格,输入和结果呈现不同,结果变为Dolor sitametconsectetuer(“sitametconsectetuer”的特定部分以秃头、斜体或作为链接装饰)单词之间没有空格如果你丢弃标签之间的空格。
  • @Ivan 我认为空格(例如sit&lt;/a&gt; &lt;em&gt;)被解析器(ElementTree)丢弃,因此无法复制。
  • @Ivan 我认为有一个非常简单的解决方案...ET.tostring(p).strip()。输出:'&lt;p&gt;Dolor &lt;a href="http://example.com"&gt;sit&lt;/a&gt; &lt;em&gt;&lt;strong&gt;amet&lt;/strong&gt; consectetuer&lt;/em&gt;&lt;/p&gt;'
猜你喜欢
  • 2015-09-17
  • 2019-05-18
  • 2016-11-26
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多