如何用Tcl tdom将HTML的<br>标签替换为DITA兼容的<?linebreak?>
用Tcl tdom将HTML的
<br>替换为DITA的<?linebreak?>处理方案 需求与问题
我需要将一段HTML字符串转换为兼容DITA的XML,核心要求是把HTML里的<br>标签替换为DITA的<?linebreak?>处理指令。
输入HTML:
<p>Line with following newline<br>Line with two following newlines<br><br>Line with no following newline</p>
期望输出:
<p>Line with following newline<?linebreak?>Line with two following newlines<?linebreak?><?linebreak?>Line with no following newline</p>
我用Tcl tdom写了代码,但取消注释#$node appendXML "<?linebreak?>"后脚本直接报错,代码如下:
package require tdom set xml {<p>Line with following newline<br>Line with two following newlines<br><br>Line with no following newline</p>} puts "Input:" puts "$xml" set doc [dom parse -html -keepEmpties $xml] set root [$doc documentElement] foreach node [$root getElementsByTagName br] { $node delete #$node appendXML "<?linebreak?>" } puts "Output:" puts [$doc asXML -indent none]
我熟悉Tcl但刚接触tdom,求解决方法,或者DITA中保留换行的其他可行方案。
解决方法
问题根源
- 先调用
$node delete后,节点已从DOM树中移除,此时再调用appendXML必然报错 <?linebreak?>是XML处理指令,不能直接用appendXML拼接字符串添加,需要用tdom的标准API创建合法的处理指令节点
修正后的代码
package require tdom set xml {<p>Line with following newline<br>Line with two following newlines<br><br>Line with no following newline</p>} puts "Input:" puts "$xml" set doc [dom parse -html -keepEmpties $xml] set root [$doc documentElement] # 先收集所有br节点到列表,避免遍历过程中DOM结构变化导致漏处理 set br_nodes [$root getElementsByTagName br] foreach node $br_nodes { # 创建<?linebreak?>处理指令节点 set linebreak_pi [$doc createProcessingInstruction "linebreak"] # 在原br节点位置插入处理指令 $node insertBefore $linebreak_pi # 删除原有br节点 $node delete } puts "Output:" puts [$doc asXML -indent none]
代码解释
- 提前收集
<br>节点:如果直接在遍历过程中修改DOM,会导致部分节点被跳过,提前存入列表能避免这个问题 - 用标准API创建处理指令:
createProcessingInstruction是tdom操作XML处理指令的规范方式,能保证生成的XML结构合法 - 先插入再删除:确保处理指令精准替换原
<br>的位置,不会打乱原有文本的顺序
DITA换行的其他可选方案
- 使用
<linebreak/>元素:部分DITA版本支持这个元素作为段落内换行的替代方案,语法更贴近常规XML标签 - 拆分段落:如果允许调整文档结构,可以把原段落拆分为多个
<p>标签,用块级元素实现换行,但会改变原有段落结构
内容的提问来源于stack exchange,提问作者user32089
相关产品推荐
相关产品推荐

