基于XML与XSLT生成LaTeX Forest结构图表的实现困境及多根节点区分方案咨询
解决XSLT转换XML到LaTeX Forest的父子节点挂载与多图表区分问题
我来帮你搞定这个XSLT的问题,核心就是要实现递归匹配父子节点,同时让每个<structure>标签对应独立的结构图表,不会互相干扰。下面一步步给你讲清楚怎么改:
核心思路
- 区分独立图表:每个
<structure>是一个独立的树,我们只需要在每个结构内部找它自己的根节点(@parent='0'且@caller='true'),然后从根节点开始递归生成子树,自然就不会和其他结构的节点混在一起。 - 高效查找子节点:用XSLT的
<xsl:key>索引所有节点的parent属性,这样可以快速找到任意节点的子节点,比每次用../dbk:structentry[@parent=current()/@id]效率高很多,尤其是节点多的时候。 - 递归生成树结构:写一个递归模板,处理当前节点后,自动调用它的所有子节点,生成Forest需要的嵌套方括号格式。
修改后的完整XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dbk="http://docbook.org/ns/docbook"> <!-- 定义key:通过parent属性查找子节点 --> <xsl:key name="child-by-parent" match="dbk:structentry" use="@parent"/> <!-- 处理每个structure节点,生成完整的LaTeX环境 --> <xsl:template match="dbk:structure"> <text>\begin{center}
</text> <xsl:apply-templates select="dbk:caption"/> <text>\rule[5pt]{0.8\textwidth}{0.4pt}
</text> <text>
\begin{forest}</text> <!-- 只处理当前结构下的根节点 --> <xsl:apply-templates select="dbk:structentry[@parent = '0' and @caller = 'true']"/> <text>\end{forest}</text> <text>
\end{center}</text> </xsl:template> <!-- 处理caption,生成加粗标题 --> <xsl:template match="dbk:caption"> <text>\textbf{<xsl:value-of select="."/>}
</text> </xsl:template> <!-- 递归处理structentry节点,生成Forest的嵌套结构 --> <xsl:template match="dbk:structentry"> <!-- 隧道参数:传递缩进值,让生成的代码更易读 --> <xsl:param name="indent" select="''" tunnel="yes"/> <!-- 输出换行和当前缩进 --> <text>
<xsl:value-of select="$indent"/></text> <!-- 输出当前节点内容 --> <text>[{<xsl:value-of select="."/>}</text> <!-- 根节点添加fill=white属性 --> <xsl:if test="@parent = '0' and @caller = 'true'"> <text>,fill=white</text> </xsl:if> <!-- 递归处理当前节点的子节点(限定在当前结构内) --> <xsl:apply-templates select="key('child-by-parent', @id, ../)"> <xsl:with-param name="indent" select="concat($indent, ' ')" tunnel="yes"/> </xsl:apply-templates> <!-- 如果有子节点,换行后再闭合方括号,保持缩进对齐 --> <xsl:if test="key('child-by-parent', @id, ../)"> <text>
<xsl:value-of select="$indent"/></text> </xsl:if> <text>]</text> </xsl:template> </xsl:stylesheet>
关键部分解释
<xsl:key>的使用:
这个索引会把所有dbk:structentry节点按@parent属性分组,当我们用key('child-by-parent', @id, ../)查找时,第三个参数../限定了只在当前节点的父节点(也就是<structure>)范围内查找子节点,完美解决了多结构之间的节点混淆问题。递归模板与缩进:
用tunnel="yes"的参数传递缩进值,让生成的LaTeX代码和你示例里的格式化版本完全一致,层次清晰,方便调试和阅读。根节点的处理:
只在每个<structure>内部查找自己的根节点,每个结构生成独立的forest环境,自然区分不同的图表。
测试效果
当你输入两个独立的<structure>时,生成的LaTeX会是两个分开的center+forest块,每个块对应自己的树结构,根节点Root 1和Root 2各自的子树完全独立,不会交叉。
内容的提问来源于stack exchange,提问作者SolidMark
相关产品推荐
相关产品推荐

