BeautifulSoup替换XML标签失效问题求助
问题:BeautifulSoup的replace_with替换XML标签未生效
我编写了一段BeautifulSoup4代码,用于读取当前目录下的XML文件,找到其中的ccl_tag标签,按照指定顺序重新排列内部的date_tag、req_tag等标签后,尝试用replace_with方法替换原标签。经检查new_ccl内容正确,但替换操作未生效,请问问题出在哪里?
代码如下:
import glob from bs4 import BeautifulSoup # get all ccl_tags # rearrange # replace current ccl_tag with data replaced # print to output file def rearrange_xml(input_file, output_file, tag_ordering): # Reading the data inside the xml # file to a variable under the name # data with open(input_file, "r") as f: data = f.read() # Passing the stored data inside # the beautifulsoup parser, storing # the returned object Bs_data = BeautifulSoup(data, "xml") # Finding all instances of tag # `ccl_tag` asign to "ccls" ccls = Bs_data.find_all("ccl_tag") # rearrange the ccl based on the given ordering for ccl in ccls: # declare new ccl new_ccl = BeautifulSoup() tags_to_rearrange = [] # find all tags in tag ordering which are also inside ccl for tag_name in tag_ordering: tags = ccl.find_all(tag_name) tags_to_rearrange.extend(tags) # find only the found tags to rearrage and apply to new ccl for tag in tags_to_rearrange: tag.extract() # only add the tags specified new_ccl.append(tag) print(new_ccl) # replace with doesn't work? ccl.replace_with(new_ccl) print(Bs_data.find("ccl_tag")) with open(output_file, "w") as file: file.write(Bs_data.prettify()) # Get a list of XML files in the same directory xml_files = glob.glob("*.xml") tag_ordering = [ "date_tag", "req_tag", "req2_tag", "req3_tag" ] # Rearrange each XML file for input_file in xml_files: # don't include output_ files if not input_file.startswith("output_"): output_file = f"output_{input_file}" rearrange_xml(input_file, output_file, tag_ordering)
问题原因
你创建的new_ccl是一个完整的BeautifulSoup文档对象,而非与原标签类型一致的<ccl_tag>标签。
当调用ccl.replace_with(new_ccl)时,你是在用整个文档对象替换原有的<ccl_tag>标签。BeautifulSoup不会自动将文档对象的内容包装成<ccl_tag>,反而会导致XML结构混乱,最终表现为替换未生效。另外,原代码中tag.extract()已经将子标签从原ccl_tag中移除,但后续将这些标签添加到文档对象中,替换后无法保持原有的<ccl_tag>外层结构。
解决方案
需要创建一个新的<ccl_tag>标签(而非文档对象),再将整理好的子标签添加到这个新标签中,最后用新标签替换原标签。
修改后的关键代码片段
for ccl in ccls: # 创建新的ccl_tag标签,使用当前文档环境的new_tag方法 new_ccl = Bs_data.new_tag("ccl_tag") tags_to_rearrange = [] for tag_name in tag_ordering: tags = ccl.find_all(tag_name) tags_to_rearrange.extend(tags) for tag in tags_to_rearrange: tag.extract() new_ccl.append(tag) # 用同类型的新标签替换原标签 ccl.replace_with(new_ccl)
修改说明
- 使用
Bs_data.new_tag("ccl_tag")创建的标签属于当前解析的文档环境,避免跨文档对象的兼容性问题。 - 新标签与原标签类型完全一致,替换后XML结构保持正确,原有的
<ccl_tag>会被替换成包含排序后子标签的新<ccl_tag>。
内容的提问来源于stack exchange,提问作者Prosy A.
相关产品推荐
相关产品推荐

