lxml修改XML树:转换带rend='b'的<p>时丢失<pb>标签求助
TEI格式XML标签转换问题解决
问题场景
需要将TEI XML中所有<p rend="b">结构转换为<p><hi rend="b">...</hi></p>,同时保留原<pb n="X"/>标签。原代码处理后出现<pb>未被包含进<hi>、文本重复的问题。
原TEI XML结构
<TEI> <teiHeader/> <text> <body> <div type="chapter"> <p rend="b"><pb n="1"/>lorem ipsum...</p> <p rend="b">lorem <pb n="2"/> ipsum2...</p> <p>lorem ipsum3...</p> </div> <div type="chapter"> <p>lorem ipsum4...</p> <p rend="b">lorem ipsum5...</p> <p rend="b"><pb n="3"/> lorem ipsum6...</p> </div> </body> </text> </TEI>
原错误代码
parser = etree.XMLParser(ns_clean=True, remove_blank_text=True) root = etree.fromstring(root, parser) for item in root.findall(".//p[@rend='b']"): hi = etree.SubElement(item, "hi", rend=font_variant[variant]) hi.text = ''.join(item.itertext()) print(etree.tostring(root, pretty_print=True, xml_declaration=True))
解决方案
核心思路是将<p>的所有子节点(包括<pb>标签和文本节点)完整移动到新创建的<hi>标签中,同时清理<p>的rend属性,避免文本重复和标签丢失。
修正后的代码
from lxml import etree # 替换为你的XML内容字符串 xml_content = '''<TEI> <teiHeader/> <text> <body> <div type="chapter"> <p rend="b"><pb n="1"/>lorem ipsum...</p> <p rend="b">lorem <pb n="2"/> ipsum2...</p> <p>lorem ipsum3...</p> </div> <div type="chapter"> <p>lorem ipsum4...</p> <p rend="b">lorem ipsum5...</p> <p rend="b"><pb n="3"/> lorem ipsum6...</p> </div> </body> </text> </TEI>''' parser = etree.XMLParser(ns_clean=True, remove_blank_text=True) root = etree.fromstring(xml_content, parser) # 遍历所有rend="b"的p标签 for p in root.xpath(".//p[@rend='b']"): # 创建hi标签,复用原p的rend属性值 hi = etree.Element("hi", rend=p.get("rend")) # 把p的所有子节点(包括pb和文本)移动到hi内 while p.getchildren(): child = p.getchildren()[0] hi.append(child) # 将hi添加为p的子节点 p.append(hi) # 删除p原有的rend属性 del p.attrib["rend"] # 输出处理后的XML print(etree.tostring(root, pretty_print=True, xml_declaration=True, encoding='UTF-8').decode())
代码说明
- 用
xpath精准定位目标<p>标签,比findall适配性更强 - 创建
<hi>时直接继承原<p>的rend属性,无需依赖外部变量 - 通过循环移动子节点的方式,完整保留原
<p>内的所有内容结构(包括<pb>标签) - 移除
<p>的rend属性,完成结构转换的最后一步
处理后效果
原第一个<p>标签会转换为:
<p><hi rend="b"><pb n="1"/>lorem ipsum...</hi></p>
所有<pb>标签被正确包含在<hi>内,文本无重复,完全符合需求。
内容的提问来源于stack exchange,提问作者Tek
相关产品推荐
相关产品推荐

