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属性存在)。要实现需求,需要完整收集
方法一:遍历节点收集内容
通过遍历
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
相关产品推荐
相关产品推荐

