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

基于自定义Node类迭代生成XML:如何闭合含子节点的元素?

迭代法实现带闭合标签的XML树转换

你的代码目前仅输出了节点的开始标签(叶子节点的自闭合标签是正确的),但非叶子节点缺少对应的</node>闭合标签。核心问题在于栈仅记录了待处理的节点,没有区分节点是首次处理(输出开始标签)还是处理完子节点后需要输出闭合标签。

解决思路

给栈中的每个元素增加一个状态标记,记录该节点是否已经输出过开始标签。通过两次入栈的方式实现非叶子节点的完整标签输出:

  1. 首次弹出未标记的节点:输出开始标签,将节点标记为「已处理开始标签」后重新压入栈,再逆序压入所有子节点(利用栈后进先出的特性,保证子节点按原顺序输出)。
  2. 再次弹出已标记的节点:输出闭合标签。

修改后的代码

def to_xml(node, indent='\t') -> str:
    xml = ''
    # 栈元素格式:(节点实例, 是否已输出开始标签)
    stack = [(node, False)]
    
    while stack:
        current_node, is_processed = stack.pop()
        
        tabs = indent * current_node.get_tab_count()
        if not is_processed:
            # 首次处理:输出开始标签
            if len(current_node.children) == 0:
                # 叶子节点直接输出自闭合标签
                xml += f'{tabs}<node />\n'
            else:
                # 非叶子节点输出开始标签,标记后重新入栈,等待子节点处理完成
                xml += f'{tabs}<node>\n'
                stack.append((current_node, True))
                # 逆序压入子节点,保证弹出顺序与原children顺序一致
                for child in reversed(current_node.children):
                    stack.append((child, False))
        else:
            # 处理完子节点后,输出闭合标签
            xml += f'{tabs}</node>\n'
    
    return xml

关键细节说明

  • 状态标记:通过is_processed区分节点的处理阶段,完美解决非叶子节点「先开后闭」的标签逻辑。
  • 子节点逆序入栈:栈是后进先出结构,将子节点逆序压入后,弹出顺序会与原children列表顺序一致,保证XML结构的正确性。
  • 叶子节点优化:直接输出自闭合标签,无需二次入栈处理闭合标签,减少冗余操作。

修正后的示例输出

<node>
        <node />
        <node />
        <node />
        <node />
        <node>
                <node />
                <node />
                <node />
        </node>
        <node />
        <node />
        <node />
</node>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:35:27