【问题标题】:Escape HTML entities that aren't XML转义不是 XML 的 HTML 实体
【发布时间】:2020-05-02 15:27:53
【问题描述】:

我正在解析一个由 SMS 备份应用程序生成的 XML 文件,但有些内容被 HTML 实体转义了。我正在使用xml.etree.ElementTree,但它抱怨xml.etree.ElementTree.ParseError: reference to invalid character number: line 29, column 308,它与XML 文件中的��
 一致。我知道我可以使用 BeautifulSoup。事实上,我已经有一个使用它的工作程序,但我正在尝试重写它以便加快速度。示例标签在这里:

<sms protocol="0" address="1012223434" date="1548857971596" type="1" subject="null" body="... by the time you want a ride. &#55357;&#56841;&#10;" toa="null" sc_toa="null" service_center="null" read="1" status="-1" locked="0" date_sent="0" readable_date="Jan 30, 2019 9:19:31 AM" contact_name="Mom" />

为了不消耗太多内存,我在数据上使用了iterparse,但我也尝试过只使用parse,并在完成后清除每个元素,以便更好地控制,但我实际上还没有弄清楚这一部分。如果我使用html.unescape,它转义太多,然后我得到xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 27, column 175,这是在它转义之前有&amp;apos; 的地方。如果我尝试将xml.sax.saxutils.escape 放在未转义的 HTML 之上,那么它当然也会转义实际上应该是 XML 一部分的所有其他内容。

如何在不转义所有 XML 实体的情况下对 HTML 实体进行转义?

【问题讨论】:

    标签: python python-3.x xml xml-parsing html-entities


    【解决方案1】:

    XML 允许的字符

    Per the W3C XML Recommendation

    [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
    

    符号

    • &amp;#d; 表示法表示 d 是字符代码点的十进制表示。

    • &amp;#xd; 表示法表示 d 是字符代码点的十六进制表示。

    错误分析

    • &amp;#55357;&amp;#xD83D;,在 XML 中不是合法字符。

    • &amp;#56841;&amp;#xDE09;,这在 XML 中也不是合法字符。

    因此,你的开场白,

    我正在解析一个 XML 文件

    不正确,您无法使用符合标准的 XML 解析器来解析此数据。相反,您只能使用How to parse invalid (bad / not well-formed) XML?

    的技术

    #1 建议是从源头解决问题。 (提示:在 UTF-16 中,55,357 56,842 是?,因此请考虑编码问题。)如果无法修复来源,上面的链接建议了许多其他方法来处理错误的“XML”许多不同的编程语言,包括 Python。

    另见

    【讨论】:

      【解决方案2】:

      该库可以处理HTML和XML,容错能力强

      from simplified_scrapy.simplified_doc import SimplifiedDoc
      html='''<sms protocol="0" address="1012223434" date="1548857971596" type="1" subject="null" body="... by the time you want a ride. &#55357;&#56841;&#10;" toa="null" sc_toa="null" service_center="null" read="1" status="-1" locked="0" date_sent="0" readable_date="Jan 30, 2019 9:19:31 AM" contact_name="Mom" />'''
      doc = SimplifiedDoc(html).getElementByTag('sms')
      print (doc)
      

      结果:

      {'tag': 'sms', 'protocol': '0', 'address': '1012223434', 'date': '1548857971596', 'type': '1', 'subject': 'null', 'body': '... by the time you want a ride. &#55357;&#56841;&#10;', 'toa': 'null', 'sc_toa': 'null', 'service_center': 'null', 'read': '1', 'status': '-1', 'locked': '0', 'date_sent': '0', 'readable_date': 'Jan 30, 2019 9:19:31 AM', 'contact_name': 'Mom'}
      

      可以获取SimplifiedDochere的例子

      【讨论】:

        猜你喜欢
        • 2013-04-27
        • 1970-01-01
        • 1970-01-01
        • 2017-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-11
        相关资源
        最近更新 更多