1

我正在尝试通过 XSLT 重新创建一个结构图表,该图表具有已经预定义的格式,即它们的外观分别定义。该结构是使用 XML 编写的,但后来在库 ( https://github.com/transpect/xml2tex ) 的帮助下使用目录树样式forest包转换为 LaTeX 代码。由于它们不是讨论的主要部分,所以我不再进一步阐述它们。xml2texXproc

我所拥有的是以下形式的示例结构:

<structure>
  <structentry id="1" parent="0" caller="true">Root</structentry>
  <structentry id="2" parent="1" caller="false">Child 1 of ID 1 (Root)</structentry>
  <structentry id="3" parent="1" caller="false">Child 2 of ID 1 (Root)</structentry>
  <structentry id="4" parent="1" caller="false">Child 3 of ID 1 (Root)</structentry>
  <structentry id="5" parent="4" caller="false">Child 1 of ID 4</structentry>
  <structentry id="6" parent="5" caller="false">Child 1 of ID 5</structentry>
</structure>

理想情况下,输出应采用以下形式:

[{Root},fill=white[{Child 1 of ID 1 (Root)}][{Child 2 of ID 1 (Root)}][{Child 3 of ID 1 (Root)}[{Child 1 of ID 4}[{Child 1 of ID 5}]]]]

或者为了便于阅读:

[{Root},fill=white
  [{Child 1 of ID 1 (Root)}]
  [{Child 2 of ID 1 (Root)}]
  [{Child 3 of ID 1 (Root)}
    [{Child 1 of ID 4}
      [{Child 1 of ID 5}]
    ]
  ]
]

然后在视觉上看起来像这样:

样本结构

因此,我试图通过匹配的 id 将节点置于其父节点之下。也就是说,任何具有的节点都parent='1'应该是具有的节点的子节点id='1'

我有以下转换,它使用“dbk”(DocBook)命名空间来定义输入 XML 中的节点。由于我对 XML、XSLT 和 XPath 还很陌生,所以在xsl:template match="dbk:structentry". 如果需要任何其他信息,我很乐意更新它们。

  <template context="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"/>
    <text>\end{forest}</text>
    <text>&#xa;\end{center}</text>
  </template>

  <xsl:template match="dbk:caption">
    \textbf{<xsl:value-of select="."/>}&#xa;
  </xsl:template>
  
  <xsl:template match="dbk:structentry">
    <xsl:choose>
    <xsl:when test="@parent eq '0' and @caller eq 'true'">
      [{<xsl:value-of select="."/>},fill=white<xsl:apply-templates select="@parent eq '1'">]
    </xsl:when>
    <xsl:otherwise>
      [{<xsl:value-of select="."/>}]
    </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

更新

一个新问题是如何区分图表的一个根条目和另一个图表的根条目?这是2个结构的示例:

结构一:

<structure>
  <structentry id="1" parent="0" caller="true">Root 1</structentry>
  <structentry id="2" parent="1" caller="false">Child 1 of ID 1 (Root 1)</structentry>
  <structentry id="3" parent="1" caller="false">Child 2 of ID 1 (Root 1)</structentry>
  <structentry id="4" parent="1" caller="false">Child 3 of ID 1 (Root 1)</structentry>
  <structentry id="5" parent="4" caller="false">Child 1 of ID 4</structentry>
  <structentry id="6" parent="5" caller="false">Child 1 of ID 5</structentry>
</structure>

结构二:

<structure>
  <structentry id="7" parent="0" caller="true">Root 2</structentry>
  <structentry id="8" parent="7" caller="false">Child 1 of ID 7 (Root 2)</structentry>
  <structentry id="9" parent="7" caller="false">Child 2 of ID 7 (Root 2)</structentry>
  <structentry id="10" parent="7" caller="false">Child 3 of ID 7 (Root 2)</structentry>
  <structentry id="11" parent="10" caller="false">Child 1 of ID 10</structentry>
  <structentry id="12" parent="11" caller="false">Child 1 of ID 11</structentry>
</structure>
4

1 回答 1

3

好吧,编写将产生您显示的结果的 XSLT 样式表并不难:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>

<xsl:key name="child" match="structentry" use="@parent" />

<xsl:template match="/structure">
    <xsl:apply-templates select="key('child', 0)"/>
</xsl:template>

<xsl:template match="structentry">
    <xsl:text>[{</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>}</xsl:text>
    <xsl:if test="@parent=0">,fill=white</xsl:if>
    <xsl:apply-templates select="key('child', @id)"/>
    <xsl:text>]</xsl:text>
</xsl:template>

</xsl:stylesheet>

我很难判断这是否适合您的整体计划。


添加:

如果您的 XML 文档有多个structure元素,但 id 在整个文档范围内是唯一的,您可以简单地更改指令:

<xsl:apply-templates select="key('child', 0)"/>

至:

<xsl:apply-templates select="key('child', 0, .)"/>

将键的范围限制为当前structure元素。这是假设您的处理器支持 XSLT 2.0 或更高版本。在 XSLT 1.0 中,您需要使用:

<xsl:apply-templates select="structentry[@parent=0]"/>

效率较低,因为这些parent值已经被索引。


当然,您需要:

<xsl:template match="structure">

没有领先/

于 2021-09-29T14:09:20.073 回答