解析缺少'/'的自动关闭标签

时间:2019-05-14 13:36:56

标签: python parsing beautifulsoup elementtree sgml

我正在尝试使用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),但是我不知道如何获得这些结果。

1 个答案:

答案 0 :(得分:0)

我最终要做的是提取所有空元素,其中可以从DTD中省略结束标签(例如<!ELEMENT elem_name - o EMPTY >),从这些元素创建一个列表,然后使用正则表达式关闭清单。然后将结果文本传递到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知道应该关闭哪些标签。