如何在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
相关产品推荐
相关产品推荐

