基于自定义Node类迭代生成XML:如何闭合含子节点的元素?
迭代法实现带闭合标签的XML树转换
你的代码目前仅输出了节点的开始标签(叶子节点的自闭合标签是正确的),但非叶子节点缺少对应的</node>闭合标签。核心问题在于栈仅记录了待处理的节点,没有区分节点是首次处理(输出开始标签)还是处理完子节点后需要输出闭合标签。
解决思路
给栈中的每个元素增加一个状态标记,记录该节点是否已经输出过开始标签。通过两次入栈的方式实现非叶子节点的完整标签输出:
- 首次弹出未标记的节点:输出开始标签,将节点标记为「已处理开始标签」后重新压入栈,再逆序压入所有子节点(利用栈后进先出的特性,保证子节点按原顺序输出)。
- 再次弹出已标记的节点:输出闭合标签。
修改后的代码
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
相关产品推荐
相关产品推荐

