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

如何使用ElementTree编辑并保留XML中的CDATA段?

编辑XML中CDATA内容并保留CDATA标记的方案

问题场景

处理包含CDATA的XML文件时,使用Python标准库xml.etree.ElementTree解析并修改CDATA内容后,输出的XML会丢失CDATA标记,导致原有的HTML格式被转义成普通文本。需要修改目标标签内的CDATA内容,同时保留CDATA格式输出。

示例输入XML片段:

<question type="multichoice">
    <name>
      <text>decimal to binary 1</text>
    </name>
    <questiontext format="html">
      <text><![CDATA[<p dir="ltr" style="text-align: left;">Convert the following number from decimal to binary:</p><p dir="ltr" style="text-align: left;">248<sub>10</sub></p>]]></text>
    </questiontext>
    <generalfeedback format="html">
      <text></text>
    </generalfeedback>
    <defaultgrade>1.0000000</defaultgrade>
...
</question>

解决方案

方案一:基于Python标准库实现

通过自定义序列化函数,让ElementTree在输出时保留CDATA标记:

import xml.etree.ElementTree as ET

# 重写XML序列化逻辑,保留CDATA格式
def serialize_with_cdata(write, elem, encoding, qnames, namespaces):
    # 针对目标text标签处理CDATA
    if elem.tag == 'text' and elem.text and elem.text.startswith('<![CDATA[') and elem.text.endswith(']]>'):
        # 提取CDATA内容并按原格式输出
        cdata_content = elem.text[9:-3]
        write(f"<{elem.tag}><![CDATA[{cdata_content}]]></{elem.tag}>".encode(encoding))
    else:
        # 其他标签使用默认序列化逻辑
        ET._serialize_xml(write, elem, encoding, qnames, namespaces)

# 替换ElementTree的默认序列化方法
ET._serialize['xml'] = serialize_with_cdata

# 解析输入XML
tree = ET.parse('input.xml')
root = tree.getroot()

# 定位到questiontext下的text标签
target_text = root.find('.//questiontext/text')

# 修改CDATA内容:提取内部内容,修改后重新包裹CDATA标记
original_content = target_text.text[9:-3]
modified_content = original_content.replace('248<sub>10</sub>', '255<sub>10</sub>')
target_text.text = f'<![CDATA[{modified_content}]]>'

# 写入输出XML
tree.write('output.xml', encoding='utf-8', xml_declaration=True)

方案二:使用lxml库(更简洁)

lxml原生支持CDATA节点,处理起来更直观:

from lxml import etree

# 解析XML文件
tree = etree.parse('input.xml')
root = tree.getroot()

# 找到目标text标签
target_text = root.find('.//questiontext/text')

# lxml会自动将CDATA解析为CDATA对象,直接修改内容即可
new_content = target_text.text.replace('248<sub>10</sub>', '255<sub>10</sub>')
target_text.text = etree.CDATA(new_content)

# 保存修改后的XML
tree.write('output.xml', encoding='utf-8', xml_declaration=True)

说明

  • 方案一依赖Python标准库,无需额外安装包,适合环境受限的场景;
  • 方案二需要先安装lxml库(pip install lxml),代码更简洁,处理CDATA的逻辑更原生。

内容的提问来源于stack exchange,提问作者Amit Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:55:27