如何基于文本与格式规则生成合法HTML字符串?(Python实现)
问题:生成带合法HTML标签的文本
给定文本字符串和格式规则,用Python生成符合要求的合法HTML字符串。示例如下:
text = 'ABCDEFGHIJ' format_rules = { 'bold': [(0,4)], 'italics': [(2,6)] } # 预期输出:<b>AB<i>CD</i></b><i>EF</i>GHIJ
注意:需要在索引4处先闭合</i>,再重新打开<i>,才能保证HTML标签合法嵌套。
解决步骤
核心思路是把格式规则转换成事件序列,再通过维护标签栈来处理嵌套和闭合逻辑:
- 转换格式为事件:将每个格式的起止区间拆分为「打开标签」和「关闭标签」事件,每个事件包含索引、标签类型、事件类型(打开/关闭)。
- 排序事件:按事件发生的索引排序,若索引相同,关闭事件优先处理(避免标签交叉)。
- 遍历事件生成HTML:维护当前文本位置、活跃标签栈,依次处理每个事件:
- 先添加当前位置到事件索引之间的纯文本;
- 处理打开/关闭事件,通过栈来管理标签的嵌套,遇到关闭事件时,若目标标签不在栈顶,需先闭合上层标签,处理完后再重新打开未结束的标签。
实现代码
def generate_html(text, format_rules): # 定义标签映射 tag_map = { 'bold': ('<b>', '</b>'), 'italics': ('<i>', '</i>') } # 生成事件列表:(index, tag_type, event_type) events = [] for tag_type, ranges in format_rules.items(): for start, end in ranges: events.append((start, tag_type, 'open')) events.append((end, tag_type, 'close')) # 排序事件:先按索引,索引相同则close事件优先 events.sort(key=lambda x: (x[0], 0 if x[2] == 'close' else 1)) result = [] current_pos = 0 active_tags = [] # 栈结构,记录当前打开的标签 for event in events: idx, tag_type, event_type = event # 添加当前位置到事件索引之间的文本 if idx > current_pos: result.append(text[current_pos:idx]) current_pos = idx if event_type == 'open': # 添加打开标签,压入栈 result.append(tag_map[tag_type][0]) active_tags.append(tag_type) else: # 处理关闭标签:找到目标标签在栈中的位置 try: tag_idx = active_tags.index(tag_type) except ValueError: continue # 标签未打开,忽略 # 先闭合栈顶到目标标签的所有标签 closed_tags = [] while active_tags: current_tag = active_tags.pop() result.append(tag_map[current_tag][1]) closed_tags.append(current_tag) if current_tag == tag_type: break # 重新打开除了目标标签之外的标签(逆序,因为之前是弹出的顺序) closed_tags.reverse() for t in closed_tags[1:]: result.append(tag_map[t][0]) active_tags.append(t) # 添加剩余的文本 if current_pos < len(text): result.append(text[current_pos:]) return ''.join(result) # 测试示例 text = 'ABCDEFGHIJ' format_rules = {'bold': [(0,4)], 'italics': [(2,6)]} output = generate_html(text, format_rules) print(output) # 输出:<b>AB<i>CD</i></b><i>EF</i>GHIJ
代码解释
- 事件转换:把每个格式的
(start, end)拆成两个事件,比如bold: (0,4)会生成(0, 'bold', 'open')和(4, 'bold', 'close')。 - 事件排序:确保事件按索引顺序处理,同索引下关闭事件先执行,避免出现
<b><i></b></i>这种交叉嵌套的错误。 - 标签栈处理:
- 打开标签时直接压栈并添加开始标签;
- 关闭标签时,先弹出栈中直到目标标签的所有标签并闭合,再把未结束的标签重新打开,保证后续文本的格式继续生效。
- 文本拼接:每次处理事件前,先把当前位置到事件索引的纯文本加入结果,最后处理剩余文本。
内容的提问来源于stack exchange,提问作者ndnchapathi69
相关产品推荐
相关产品推荐

