Python提取重复XML标签首块内容 剔除冗余块解决解析报错
问题背景
从sec.gov站点获取的XML文件存在内容重复问题:相同的XML声明+对应<feed>标签块累计重复出现约5次,同时文档末尾附带多余内容,直接解析会触发两类报错:
XML declaration allowed only at the start of the document Extra content at the end of the document
原始文件的重复块结构如下:
<?xml version="1.0" encoding="ISO-8859-1" ?> <feed xmlns="http://www.w3.org/2005/Atom"> <author> <email>webmaster@sec.gov</email> <name>Webmaster</name> </author> <company-info> <addresses> <address type="mailing"> <city>CAMBRIDGE</city> <state>MA</state> </address> </company-info> </feed>
最初尝试用正则提取首个XML声明的代码如下,但执行后会匹配到全部5个XML声明,达不到仅保留首个完整XML块的预期:
finalXMLString = request.content.decode('utf-8') xmlPattern = '(<\?xml.*\?\>){1}' parsedXMLTag = re.search(xmlPattern, finalXMLString) print(parsedXMLTag.group(1))
目标效果:仅保留首次出现的XML声明,以及其对应的完整<feed>标签内容,剔除后续所有重复XML块和末尾多余内容。
可行解决方案
方案1:正则匹配截取首个完整块(轻量快速,适配当前固定结构场景)
之前正则失效的核心原因是.*默认是贪婪匹配,且没有匹配到第一个</feed>闭合标签就截止,调整正则规则,匹配从首个XML声明开始,到第一个</feed>闭合标签结束的所有内容即可:
import re finalXMLString = request.content.decode('utf-8') # 非贪婪匹配:从首个XML声明开始,到第一个</feed>标签截止,re.DOTALL保证.可以匹配换行符 match_result = re.search(r'<\?xml.*?</feed>', finalXMLString, flags=re.DOTALL) if match_result: valid_xml = match_result.group() # 输出验证通过的有效XML内容 print(valid_xml)
注意:该方案适配当前feed块无嵌套同名feed标签的场景,匹配效率高不需要额外依赖;如果解码出现乱码,可以将
decode('utf-8')替换为decode('ISO-8859-1'),和XML声明中标注的文件编码保持一致。
方案2:逐行扫描截断(无正则转义问题,逻辑直观)
不需要写复杂正则,逐行遍历内容,遇到第二个XML声明行就直接截断,再补全最后缺失的</feed>闭合标签即可:
finalXMLString = request.content.decode('utf-8') lines = finalXMLString.splitlines() keep_lines = [] xml_declare_count = 0 for line in lines: stripped_line = line.strip() # 统计XML声明出现次数,遇到第二次就终止遍历 if stripped_line.startswith('<?xml'): xml_declare_count +=1 if xml_declare_count >1: break keep_lines.append(line) # 拼接内容,补全闭合的feed标签(如果截断时没带上的话) valid_xml = '\n'.join(keep_lines).rstrip() if not valid_xml.endswith('</feed>'): valid_xml += '\n </feed>' print(valid_xml)
原正则方案失效原因
之前编写的匹配规则存在两个核心问题,导致结果不符合预期:
- 正则中
.*默认采用贪婪匹配模式,会跨内容块匹配到最远的符合规则的片段,而非停在第一个匹配结果位置 - 规则仅匹配XML声明标签,没有将匹配范围延伸到对应
<feed>块的闭合标签,也没有设置截断后续重复内容的逻辑
内容的提问来源于stack exchange,提问作者Brent Heigold
相关产品推荐
相关产品推荐

