【问题标题】:Parse self-closing tags missing the '/'解析缺少“/”的自闭合标签
【发布时间】:2019-05-14 13:36:55
【问题描述】:

我正在尝试使用 BeautifulSoup4 解析一些旧的 SGML 代码并使用数据构建一个元素树。它大部分工作正常,但一些应该自动关闭的标签没有被标记为这样。例如:

<element1>
    <element2 attr="0">
    <element3>Data</element3>
</element1>

当我解析数据时,结果如下:

<element1>
    <element2 attr="0">
        <element3>Data</element3>
    </element2>
</element1>

我希望它假设如果它没有找到此类元素的结束标签,它应该将其视为自结束标签,而不是假设它之后的所有内容都是一个孩子并将结束尽可能晚地标记,如下所示:

<element1>
    <element2 attr="0"/>
    <element3>Data</element3>
</element1>

谁能指出一个可以做到这一点的解析器,或者以某种方式修改现有的解析器以实现这种方式?我已经挖掘了一些解析器(lxml、lxml-xml、html5lib),但我不知道如何获得这些结果。

【问题讨论】:

  • 如果你有 SGML DTD 并且element2 被声明为 EMPTY,你也许可以使用 osx SGML 到 XML 转换器。见stackoverflow.com/a/12534420/407651
  • 我之前确实偶然发现了那个。我最初忽略了它,因为我希望有一个更通用的解决方案,还因为我需要解析的文件使用分布在多个文件中的几个不同的 DTD,所以我不太确定它是否会工作。无论如何我都会试一试。我已经用尽了所有其他选择,除非有人给我其他尝试。谢谢!
  • 其实,我现在想起来了:我确实试过了,但是我在安装 OpenSP 时遇到了问题。
  • 查看stackoverflow.com/questions/50450793/… 回答与您类似的问题,并提供有关安装 OpenSP 的信息
  • @imhotap 我看了一下帖子。安装 OpenSP 的说明没有帮助,因为它们是 Linux 的说明,而我在 Windows 上。我确实按照原始 SP 工具的链接进行操作,并且没有任何问题。它有点有效,因为它解析文件,但我传递给它的参数都没有做任何事情。我什至不能通过它来读取一个 DTD 文件;它只是忽略了一切。因此,虽然它确实解析了文件,但因为我无法告诉它哪些参数应该为空,它的输出与我尝试过的其他解析器大致相同。

标签: python parsing beautifulsoup elementtree sgml


【解决方案1】:

我最终做的是提取所有可以从 DTD 中省略结束标签的空元素(例如&lt;!ELEMENT elem_name - o EMPTY &gt;),从这些元素创建一个列表,然后使用正则表达式关闭列表中的所有标签。然后将生成的文本传递给 XML 解析器。

这是我正在做的事情的简化版本:

import re
from lxml.html import soupparser
from lxml import etree as ET

empty_tags = ['elem1', 'elem2', 'elem3']

markup = """
<elem1 attr="some value">
<elem2/>
<elem3></elem3>
"""

for t in empty_tags:
    markup = re.sub(r'(<{0}(?:>|\s+[^>/]*))>\s*(?:</{0}>)?\n?'.format(t), r'\1/>\n', markup)

tree = soupparser.fromstring(markup)
print(ET.tostring(tree, pretty_print=True).decode("utf-8"))

输出应该是:

<elem1 attr="some value"/>
<elem2/>
<elem3/>

(这实际上将包含在标签中,但解析器会将它们添加进去。)

它将单独保留属性,并且不会触及已经自闭合的标签。如果标签有一个结束标签,但它是空的,它将删除结束标签并自动关闭标签,这样它就被标准化了。

这不是一个非常通用的解决方案,但据我所知,在不知道应该关闭哪些标签的情况下,没有其他方法可以做到这一点。甚至 OpenSP 也需要 DTD 知道它应该关闭哪些标签。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 2018-06-15
    相关资源
    最近更新 更多