You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python解析XML时忽略文本内容中的`]]>`?

如何在Python解析XML时忽略文本内容中的]]>?

哥们,我太懂你这种踩坑的憋屈感了——当初图省事没转义文本里的特殊序列,结果现在XML里的]]>直接把各种解析器都搞懵了,报错的报错、丢内容的丢内容,确实头疼。先给你理清楚你遇到的现状,再给你两个实用的解决办法:

首先是你已经碰到的那些糟心情况:

  • 用Python标准库的xml.etree.ElementTree.fromstring直接抛错:ParseError: not well-formed (invalid token): line 1, column 25
  • 换lxml的lxml.etree.fromstring也逃不过报错:XMLSyntaxError: Sequence ']]>' not allowed in content, line 1, column 24
  • 试了lxml的recover模式,虽然能成功解析,但文本内容直接丢了,完全达不到需求

接下来给你两个可行的解决思路:

方法一:预处理XML文本(最简单直接)

因为XML解析器报错的核心原因是]]>是CDATA段的结束标记,但你的文本里平白出现了这个序列,没有对应的开头,所以我们可以在解析前把这个序列转义成普通文本,让解析器把它当成普通内容处理。

具体代码示例如下:

# 先拿到有问题的XML字符串
bad_xml = "<foo>this is some text ]]></foo>"
# 预处理:把]]>替换成转义后的形式]]&gt;
fixed_xml = bad_xml.replace("]]>", "]]&gt;")

# 用标准库解析试试
import xml.etree.ElementTree as ET
root = ET.fromstring(fixed_xml)
print(root.text)  # 输出:this is some text ]]>

# 用lxml解析也完全没问题
from lxml import etree
root = etree.fromstring(fixed_xml)
print(root.text)  # 同样能拿到完整文本

这个方法的优点是代码简单,零额外学习成本,适合你这种没有真实CDATA段的场景;如果你的XML里本来就有合法的CDATA段,那这个替换会破坏CDATA,这种情况就不建议用了,但看你的描述应该是文本误写了]]>,所以这个方法完全够用。

方法二:用SAX解析器自定义处理文本(不修改原XML)

如果你不想碰原XML字符串,那可以用Python的SAX解析器——它是逐段读取并处理XML内容的,不会因为]]>这个序列就直接报错,我们可以自己写个处理类来完整收集文本内容。

代码示例如下:

from xml.sax import handler, make_parser

class TextCollectHandler(handler.ContentHandler):
    def __init__(self):
        self.current_tag = None
        self.tag_text_map = {}
        self.text_buffer = []

    def startElement(self, name, attrs):
        # 遇到开始标签时,初始化当前标签和缓冲区
        self.current_tag = name
        self.text_buffer = []

    def characters(self, content):
        # 不管是什么内容,直接往缓冲区里加,完全不做过滤
        self.text_buffer.append(content)

    def endElement(self, name):
        # 标签结束时,把缓冲区的内容拼接起来存到字典里
        self.tag_text_map[name] = ''.join(self.text_buffer)
        self.current_tag = None

# 解析有问题的XML
bad_xml = "<foo>this is some text ]]></foo>"
parser = make_parser()
text_handler = TextCollectHandler()
parser.setContentHandler(text_handler)
parser.parseString(bad_xml)

# 拿到完整的文本内容
print(text_handler.tag_text_map['foo'])  # 输出:this is some text ]]>

这个方法的优点是完全不修改原XML内容,通过自定义逻辑绕过解析器的错误判定,灵活性更高,适合那些不能修改原XML的场景,唯一的小缺点是要自己写点SAX的处理逻辑,但代码也不算复杂。

总结一下,如果你场景简单,直接用预处理替换的方法就行;如果不想碰原XML,就用SAX解析器自定义处理,这两个方法都能帮你拿到完整的文本内容,不会再出现报错或者丢数据的问题。

备注:内容来源于stack exchange,提问作者Thomas Rambø

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 11:58:01