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

如何在BeautifulSoup嵌套XML标签间强制换行,无需美化重解析?

如何让BeautifulSoup生成的嵌套XML标签自动带换行符?

我需要测试一套(反)序列化代码的对称性,发现用BeautifulSoup手动创建嵌套XML标签时,内部标签与外层标签之间没有换行符,导致和原始解析的标签序列化结果不一致,无法直接通过==判断相等。有没有办法不用先美化再重解析的繁琐操作,直接让生成的标签在嵌套时自动添加换行符?

示例代码

import bs4
from bs4 import BeautifulSoup

# 原始解析的标签,带有换行符
tag_string = "<OUTER>\n<INNER/>\n</OUTER>"
tag = BeautifulSoup(tag_string, "xml").find("OUTER")

print(tag)
# 输出:
# <OUTER>
# <INNER/>
# </OUTER>

# 手动创建的嵌套标签,无换行符
new_tag = bs4.Tag(name="OUTER")
new_tag.append(bs4.Tag(name="INNER", can_be_empty_element=True))

print(tag == new_tag)  # 输出:False
print(new_tag)
# 输出:
# <OUTER><INNER/></OUTER>

当前繁琐解决方案

为实现序列化对称,我不得不先美化输出、处理换行符,再重新解析:

new_tag = BeautifulSoup(
    new_tag.prettify().replace("\n ", "\n"), "xml"
).find("OUTER")

print(tag == new_tag)  # 输出:True
print(new_tag)
# 输出:
# <OUTER>
# <INNER/>
# </OUTER>

需求背景

  • 我用专属测试数据将数千个标签反序列化为对象
  • 开发时发现多处输入输出不匹配,这种情况不可接受——读取数据的闭源二进制程序会执行不必要的操作,仅当数据库与XML条目存在真实差异时才应触发这类操作
  • 我已修复测试数据的不匹配问题,但无法保证所有用户都能实现(反)序列化对称
  • 因此测试套件需要遍历用户数据的标签,断言输入输出完全相等,但当前美化重解析的方法过于繁琐,希望找到更优方案

优化方案

方法1:手动插入换行符节点

在添加子标签前后,手动插入NavigableString类型的换行符,让生成的标签序列化时自带换行:

import bs4
from bs4 import BeautifulSoup, NavigableString

new_tag = bs4.Tag(name="OUTER")
# 插入开头换行
new_tag.append(NavigableString("\n"))
inner_tag = bs4.Tag(name="INNER", can_be_empty_element=True)
new_tag.append(inner_tag)
# 插入结尾换行
new_tag.append(NavigableString("\n"))

print(tag == new_tag)  # 输出:True
print(new_tag)
# 输出:
# <OUTER>
# <INNER/>
# </OUTER>

方法2:封装添加子标签的逻辑

如果需要批量处理,可以自定义函数封装添加逻辑,自动插入换行:

def append_with_newline(parent_tag, child_tag):
    parent_tag.append(NavigableString("\n"))
    parent_tag.append(child_tag)
    parent_tag.append(NavigableString("\n"))

# 使用示例
new_tag = bs4.Tag(name="OUTER")
inner_tag = bs4.Tag(name="INNER", can_be_empty_element=True)
append_with_newline(new_tag, inner_tag)

print(tag == new_tag)  # 输出:True

方法3:直接对比格式化后的字符串

不需要重新解析标签,直接对比处理后的美化字符串,效率更高:

# 统一处理缩进后对比字符串
print(tag.prettify().replace("\n ", "\n") == new_tag.prettify().replace("\n ", "\n"))  # 输出:True

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:23:15