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

LXML解析含注释标签仅获注释前文本,如何将全部内容转为CDATA?

如何将XML标签内所有内容(含注释)包裹到CDATA中?

给定原始XML:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <tag>
    some data
    <!-- some data2 -->
    <!-- some data2 -->
    some data
  </tag>
</root>

使用lxml的etree解析时,仅通过tag.text只能获取注释前的文本,执行以下代码后:

from lxml import etree

parser = etree.XMLParser()
#parser = etree.XMLParser(remove_comments=True)
tree = etree.parse("./data.xml", parser)
root = tree.getroot()

for tag in root.findall("tag"):
    tag.text = etree.CDATA(tag.text)

tree.write("./result.xml",
           encoding = "utf-8",
           xml_declaration = True)

生成的XML仅注释前的文本被转为CDATA,注释及后续文本未被处理:

<?xml version='1.0' encoding='UTF-8'?>
<root>
  <tag><![CDATA[
    some data
    ]]><!-- some data2 -->
    <!-- some data2 -->
    some data
  </tag>
</root>

解决方案

问题核心是tag.text仅对应内第一个文本节点,而标签中还包含注释节点和后续的文本节点(这些文本节点以子节点的tail属性存在)。要实现需求,需要完整收集内的所有内容,再将其包裹到CDATA中。

方法一:遍历节点收集内容

通过遍历的所有子节点,拼接开头文本、子节点序列化内容、子节点后的文本,得到完整内部内容:

from lxml import etree

# 保留空白文本,避免原有格式丢失
parser = etree.XMLParser(remove_blank_text=False)
tree = etree.parse("./data.xml", parser)
root = tree.getroot()

for tag in root.findall("tag"):
    # 收集<tag>内的全部内容
    full_content = tag.text or ""
    for child in tag:
        # 序列化子节点(如注释)为字符串
        full_content += etree.tostring(child, encoding="utf-8").decode("utf-8")
        # 添加子节点后的文本内容
        full_content += child.tail or ""
    
    # 清空<tag>原有所有子节点和文本
    tag.clear()
    # 将完整内容放入CDATA
    tag.text = etree.CDATA(full_content)

# 写入结果,保留格式化
tree.write("./result.xml",
           encoding="utf-8",
           xml_declaration=True,
           pretty_print=True)

方法二:序列化节点提取内容

将节点直接序列化为字符串,通过正则提取内部内容,实现更简洁:

from lxml import etree
import re

parser = etree.XMLParser(remove_blank_text=False)
tree = etree.parse("./data.xml", parser)
root = tree.getroot()

for tag in root.findall("tag"):
    # 序列化<tag>节点为字符串
    tag_str = etree.tostring(tag, encoding="utf-8").decode("utf-8")
    # 提取<tag>标签内的所有内容(兼容带属性的<tag>)
    match = re.search(r'<tag[^>]*>(.*?)</tag>', tag_str, re.DOTALL)
    if match:
        full_content = match.group(1)
        # 清空<tag>并设置CDATA内容
        tag.clear()
        tag.text = etree.CDATA(full_content)

tree.write("./result.xml",
           encoding="utf-8",
           xml_declaration=True,
           pretty_print=True)

最终效果

两种方法执行后,都会生成符合要求的XML:

<?xml version='1.0' encoding='UTF-8'?>
<root>
  <tag><![CDATA[
    some data
    <!-- some data2 -->
    <!-- some data2 -->
    some data
  ]]></tag>
</root>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 19:44:56