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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:35:27