宽松的xmlpython解析器:解析XML标记重叠

2024-06-09 06:18:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找错误友好的(在BeautifulSoup的术语中是宽容的)python解析器的“坏”XML输入。问题是标签重叠。输入示例如下:

<trn>choya - <i><b>a cholla cactus </i> lat. <i>Cylindropuntia</b></trn></i>

我希望得到什么和XML complient结果,例如(好的我希望的结果)

<trn>choya - <b><i>a cholla cactus </i> lat. <i>Cylindropuntia</i></b></trn>

带有html.parserhtml5libBeautifulSoup给了我另外一些东西(坏的结果我不想要):

<trn>choya - <i><b>a cholla cactus </b></i> lat. <i>Cylindropuntia</i></trn>

注意<i><b>标签的顺序。如果我将<i>标记为斜体,将<b>标记为粗体,那么好的答案是

竹叶仙人掌

坏的答案是

秋叶仙人掌

我也试过旧的tidyhtml,没有得到必要的结果。对于new tidy-html5,找不到python接口。 你能帮帮我吗

  • 为了找到一个解析器,我们可以做这项工作
  • 如果没有,建议一个算法或任何与这类算法有关的知识来源

谢谢!你知道吗


Tags: 答案标记算法解析器错误标签xmllat
1条回答
网友
1楼 · 发布于 2024-06-09 06:18:28

html.parser.HTMLParser擅长解析标记soup,SAXXMLGenerator类有一个方便的API来基于事件生成XML。你知道吗

并不是所有的位都在这里实现,尤其不是标签的“刚性”/“权重”约束(现在我们所做的只是用我们期望的方式关闭标签,以使嵌套正确),但基本思想似乎是可行的。你知道吗

输出为

<trn>choya - <i><com>a cholla cactus </com> lat. <i>Cylindropuntia</i></i> native to US</trn>

这是有效的XML,嵌套方面。你知道吗

祝你好运!你知道吗


import html.parser
import io
from xml.sax.saxutils import XMLGenerator


class Reconstructor(html.parser.HTMLParser):

    def __init__(self):
        super().__init__()
        self.op_stream = []
        self.tag_stack = []

    def handle_startendtag(self, tag, attrs):
        self.op_stream.append(('startendtag', (tag, attrs)))

    def handle_starttag(self, tag, attrs):
        self.op_stream.append(('starttag', (tag, attrs)))
        self.tag_stack.append(tag)

    def handle_endtag(self, tag):
        expected_tag = self.tag_stack[-1]
        if tag != expected_tag:
            print('mismatch closing <{}>, expected <{}>'.format(tag, expected_tag))
            # TODO: implement logic to figure out the correct order for the tags here
            #       and reorder tag_stack accordingly.
        stack_tag = self.tag_stack.pop(-1)
        self.op_stream.append(('endtag', (stack_tag, tag)))

    def handle_charref(self, name):
        self.op_stream.append(('charref', (name,)))

    def handle_entityref(self, name):
        self.op_stream.append(('entityref', (name,)))

    def handle_data(self, data):
        self.op_stream.append(('data', (data,)))

    def handle_comment(self, data):
        self.op_stream.append(('comment', (data,)))

    def handle_decl(self, decl):
        self.op_stream.append(('decl', (decl,)))

    def handle_pi(self, data):
        self.op_stream.append(('pi', (data,)))

    def generate_xml(self):
        stream = io.StringIO()
        xg = XMLGenerator(stream, encoding='utf-8')
        for op, args in self.op_stream:
            if op in ('startendtag', 'starttag'):
                tag, attrib = args
                xg.startElement(tag, dict(attrib))
                if op == 'startendtag':
                    xg.endElement(tag)
            elif op == 'endtag':
                tag = args[0]
                xg.endElement(tag)
            elif op == 'data':
                xg.characters(args[0])
            else:
                raise NotImplementedError('Operator not implemented: %s' % op)
        xg.endDocument()
        return stream.getvalue()


xr = Reconstructor()
xr.feed('<trn>choya - <i><com>a cholla cactus </i> lat. <i>Cylindropuntia</com></trn> native to US</i>')
y = xr.generate_xml()
print(y)

相关问题 更多 >