类XML无闭合标签未知文件格式的Python验证咨询
关于自定义XML变体配置格式的疑问解答
1. 是否存在此类常见文件格式?
这种格式不属于主流标准标记/配置格式,不过它的设计逻辑和**SGML(XML的前身)**的简化写法有相似之处——SGML允许在特定场景下省略闭合标签,但这类省略规则并没有形成被广泛支持的独立标准格式。多数情况下,这类格式是软件开发者自定义的XML变体,目的是简化叶子节点的书写成本。
2. Python实现格式验证方案
2.1 验证Schema有效性(含子元素的父标签必须闭合,叶子节点无需闭合)
核心逻辑是维护一个标签栈,逐行解析内容,区分父标签(含子元素)和叶子标签(直接带值),确保所有父标签都有对应的闭合标签。
def validate_schema(file_path): tag_stack = [] # 读取文件,过滤空行和注释行,同时保存缩进量 with open(file_path, 'r', encoding='utf-8') as f: lines = [] for line in f: stripped_line = line.strip() if not stripped_line or stripped_line.startswith('#'): continue lines.append((stripped_line, len(line) - len(line.lstrip()))) for line_num, (line, indent) in enumerate(lines, 1): # 处理闭合标签 if line.startswith('</') and line.endswith('>'): close_tag = line[2:-1].strip() if not tag_stack or tag_stack[-1][0] != close_tag: return False, f"第{line_num}行:闭合标签</{close_tag}>无匹配的开始标签" tag_stack.pop() continue # 处理开始标签 if '<' in line and '>' in line: start_idx = line.index('<') end_idx = line.index('>') open_tag = line[start_idx+1:end_idx].strip() # 判断是否为叶子标签:标签后直接带内容,且下一行没有缩进更深的子标签 has_inline_value = len(line[end_idx+1:].strip()) > 0 is_parent = False if line_num < len(lines): next_line, next_indent = lines[line_num] if next_line.startswith('<') and next_indent > indent: is_parent = True if is_parent or not has_inline_value: # 父标签入栈,等待闭合 tag_stack.append((open_tag, indent)) # 检查是否有未闭合的父标签 if tag_stack: unclosed = [tag for tag, _ in tag_stack] return False, f"未闭合的父标签:{', '.join(unclosed)}" return True, "Schema验证通过"
2.2 验证所有<均有对应的>闭合
逐行检查<和>的数量匹配,且每个<都在对应的>之前出现,同时忽略注释部分的括号。
def validate_angle_brackets(file_path): with open(file_path, 'r', encoding='utf-8') as f: lines = [line.rstrip('\n') for line in f] for line_num, line in enumerate(lines, 1): # 剥离注释内容 if '#' in line: line = line[:line.index('#')] open_count = line.count('<') close_count = line.count('>') if open_count != close_count: return False, f"第{line_num}行:括号不匹配 - {open_count}个'<' vs {close_count}个'>'" # 检查括号的嵌套顺序 bracket_stack = [] for idx, char in enumerate(line): if char == '<': bracket_stack.append(idx) elif char == '>': if not bracket_stack: return False, f"第{line_num}行:位置{idx}的'>'无匹配的'<'" bracket_stack.pop() if bracket_stack: pos = bracket_stack[0] return False, f"第{line_num}行:位置{pos}的'<'无匹配的'>'" return True, "括号闭合验证通过"
组合验证入口
def validate_config(file_path): # 先验证括号闭合 bracket_valid, bracket_msg = validate_angle_brackets(file_path) print(bracket_msg) if not bracket_valid: return False # 再验证Schema schema_valid, schema_msg = validate_schema(file_path) print(schema_msg) return schema_valid # 使用示例 # validate_config("your_config_file.txt")
内容的提问来源于stack exchange,提问作者Parmandeep Chaddha
相关产品推荐
相关产品推荐

