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

基于XML与XSLT生成LaTeX Forest结构图表的实现困境及多根节点区分方案咨询

解决XSLT转换XML到LaTeX Forest的父子节点挂载与多图表区分问题

我来帮你搞定这个XSLT的问题,核心就是要实现递归匹配父子节点,同时让每个<structure>标签对应独立的结构图表,不会互相干扰。下面一步步给你讲清楚怎么改:

核心思路

  1. 区分独立图表:每个<structure>是一个独立的树,我们只需要在每个结构内部找它自己的根节点(@parent='0'且@caller='true'),然后从根节点开始递归生成子树,自然就不会和其他结构的节点混在一起。
  2. 高效查找子节点:用XSLT的<xsl:key>索引所有节点的parent属性,这样可以快速找到任意节点的子节点,比每次用../dbk:structentry[@parent=current()/@id]效率高很多,尤其是节点多的时候。
  3. 递归生成树结构:写一个递归模板,处理当前节点后,自动调用它的所有子节点,生成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}&#xa;</text>
    <xsl:apply-templates select="dbk:caption"/>
    <text>\rule[5pt]{0.8\textwidth}{0.4pt}&#xa;</text>
    <text>&#xa;\begin{forest}</text>
    <!-- 只处理当前结构下的根节点 -->
    <xsl:apply-templates select="dbk:structentry[@parent = '0' and @caller = 'true']"/>
    <text>\end{forest}</text>
    <text>&#xa;\end{center}</text>
  </xsl:template>

  <!-- 处理caption,生成加粗标题 -->
  <xsl:template match="dbk:caption">
    <text>\textbf{<xsl:value-of select="."/>}&#xa;</text>
  </xsl:template>

  <!-- 递归处理structentry节点,生成Forest的嵌套结构 -->
  <xsl:template match="dbk:structentry">
    <!-- 隧道参数:传递缩进值,让生成的代码更易读 -->
    <xsl:param name="indent" select="''" tunnel="yes"/>
    
    <!-- 输出换行和当前缩进 -->
    <text>&#xa;<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>&#xa;<xsl:value-of select="$indent"/></text>
    </xsl:if>
    <text>]</text>
  </xsl:template>
</xsl:stylesheet>

关键部分解释

  1. <xsl:key>的使用:
    这个索引会把所有dbk:structentry节点按@parent属性分组,当我们用key('child-by-parent', @id, ../)查找时,第三个参数../限定了只在当前节点的父节点(也就是<structure>)范围内查找子节点,完美解决了多结构之间的节点混淆问题。

  2. 递归模板与缩进:
    用tunnel="yes"的参数传递缩进值,让生成的LaTeX代码和你示例里的格式化版本完全一致,层次清晰,方便调试和阅读。

  3. 根节点的处理:
    只在每个<structure>内部查找自己的根节点,每个结构生成独立的forest环境,自然区分不同的图表。

测试效果

当你输入两个独立的<structure>时,生成的LaTeX会是两个分开的center+forest块,每个块对应自己的树结构,根节点Root 1和Root 2各自的子树完全独立,不会交叉。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:43:11