You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于文本与格式规则生成合法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标签合法嵌套。

解决步骤

核心思路是把格式规则转换成事件序列,再通过维护标签栈来处理嵌套和闭合逻辑:

  1. 转换格式为事件:将每个格式的起止区间拆分为「打开标签」和「关闭标签」事件,每个事件包含索引、标签类型、事件类型(打开/关闭)。
  2. 排序事件:按事件发生的索引排序,若索引相同,关闭事件优先处理(避免标签交叉)。
  3. 遍历事件生成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
代码解释
  1. 事件转换:把每个格式的(start, end)拆成两个事件,比如bold: (0,4)会生成(0, 'bold', 'open')和(4, 'bold', 'close')。
  2. 事件排序:确保事件按索引顺序处理,同索引下关闭事件先执行,避免出现<b><i></b></i>这种交叉嵌套的错误。
  3. 标签栈处理:
    • 打开标签时直接压栈并添加开始标签;
    • 关闭标签时,先弹出栈中直到目标标签的所有标签并闭合,再把未结束的标签重新打开,保证后续文本的格式继续生效。
  4. 文本拼接:每次处理事件前,先把当前位置到事件索引的纯文本加入结果,最后处理剩余文本。

内容的提问来源于stack exchange,提问作者ndnchapathi69

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 16:27:43