在使用Python处理XML数据时,CDATA节点是经常会遇到的特殊内容类型。CDATA的全称是Character Data,它的作用是让XML解析器跳过对其中内容的解析,直接将其作为纯文本处理,通常用来存放包含小于号、大于号、&等特殊字符的内容,或者是多行文本、代码段等。
什么是CDATA节点
CDATA节点在XML中的语法格式是<![CDATA[内容]]>,比如下面的XML片段中就包含了CDATA节点:
<note>
<content><![CDATA[这是一段包含<特殊符号>的内容,不需要解析器处理]]></content>
</note>
如果不做特殊处理,Python默认的XML解析器会直接忽略CDATA的标记,把其中的内容当作普通文本处理,有时候甚至会出现解析异常,所以需要针对性处理。
使用标准库ElementTree处理CDATA
Python内置的xml.etree.ElementTree模块默认的解析器不支持CDATA,不过我们可以通过自定义TreeBuilder和解析器来实现CDATA的识别。
自定义CDATA识别的Builder
首先继承ElementTree的TreeBuilder,重写相关的处理方法,让它能识别CDATA节点:
import xml.etree.ElementTree as ET
class CDATABuilder(ET.TreeBuilder):
def comment(self, text):
# 处理注释,这里不扩展,返回空避免报错
return super().comment(text)
def start(self, tag, attrs):
return super().start(tag, attrs)
def data(self, data):
# 普通文本数据直接处理
return super().data(data)
def end(self, tag):
return super().end(tag)
# 自定义解析器,支持CDATA
class CDATAParser(ET.XMLParser):
def __init__(self):
super().__init__(target=CDATABuilder())
self._parser.CommentHandler = self.target.comment
# 注册CDATA的处理方法
self._parser.CDATAHandler = self.target.data
读取XML中的CDATA内容
使用自定义的解析器来解析包含CDATA的XML文件,就可以正常获取CDATA中的内容:
# 待解析的XML内容
xml_content = """<?xml version="1.0" encoding="utf-8"?>
<root>
<item>
<name>测试项</name>
<desc><![CDATA[描述内容包含<test>标签,不需要解析]]></desc>
</item>
</root>"""
# 使用自定义解析器解析
parser = CDATAParser()
root = ET.fromstring(xml_content, parser=parser)
# 获取desc标签的内容,CDATA内容会被正常读取
desc_text = root.find("item/desc").text
print(desc_text) # 输出:描述内容包含<test>标签,不需要解析
使用lxml库处理CDATA
第三方库lxml对XML的支持更完善,默认就可以处理CDATA节点,使用起来更简单。
安装lxml
首先通过pip安装lxml库:
pip install lxml
读取和修改CDATA内容
使用lxml的etree模块解析XML时,CDATA内容会被自动识别,我们可以通过text属性直接获取,也可以修改CDATA的内容:
from lxml import etree
# 解析XML内容
xml_data = """<root>
<content><![CDATA[原始CDATA内容]]></content>
</root>"""
root = etree.fromstring(xml_data.encode("utf-8"))
# 获取CDATA内容
content_elem = root.find("content")
print(content_elem.text) # 输出:原始CDATA内容
# 修改CDATA内容
content_elem.text = "修改后的CDATA内容"
# 输出修改后的XML,会保留CDATA标记
print(etree.tostring(root, encoding="unicode"))
# 输出:<root>
# <content><![CDATA[修改后的CDATA内容]]></content>
# </root>
两种方法的对比
两种处理方式的区别如下:
| 方式 | 优点 | 缺点 |
|---|---|---|
| 自定义ElementTree解析器 | 无需安装第三方库,纯标准库实现 | 需要自定义代码,适配成本较高 |
| lxml库 | 开箱即用,支持更多XML特性,性能更好 | 需要额外安装第三方依赖 |
注意事项
- 处理XML时要注意编码问题,避免中文或者特殊字符出现乱码。
- 如果不需要保留CDATA标记,只是获取文本内容,两种方式的text属性都可以直接拿到纯文本,不需要额外处理。
- 生成包含CDATA的XML时,使用lxml会更方便,ElementTree默认不会主动生成CDATA标记,需要额外处理。
CDATA节点的核心作用是避免特殊字符被XML解析器误解析,根据实际需求选择合适的处理方式即可,大部分场景下使用lxml可以更高效地完成任务。
PythonXMLCDATA节点ElementTree修改时间:2026-06-28 14:18:36