使用 XML 创建结构图并通过 LaTeX 呈现
Posted
技术标签:
【中文标题】使用 XML 创建结构图并通过 LaTeX 呈现【英文标题】:Creating a structural chart using XML and rendered via LaTeX 【发布时间】:2021-11-21 10:34:01 【问题描述】:我正在尝试通过 XSLT 使用已经预定义的格式重新创建结构图表,即它们的外观单独定义。该结构是使用 XML 编写的,但后来在 xml2tex
的帮助下使用目录树样式的 forest
包转换为 LaTeX 代码,Xproc
库 (https://github.com/transpect/xml2tex)。由于它们不是讨论的主要部分,所以我不再详细说明它们。
我所拥有的是以下形式的示例结构:
<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>\begincenter
</text>
<xsl:apply-templates select="dbk:caption"/>
<text>\rule[5pt]0.8\textwidth0.4pt
</text>
<text>
\beginforest</text>
<xsl:apply-templates select="dbk:structentry"/>
<text>\endforest</text>
<text>
\endcenter</text>
</template>
<xsl:template match="dbk:caption">
\textbf<xsl:value-of select="."/>

</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 个结构的示例:
结构1:
<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>
结构2:
<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>
【问题讨论】:
我已经发布了一个答案 - 但一般来说,应该关闭这样的问题。 @michael.hor257k:不能自救并不是一件坏事。恭喜获得 100K。 @kjhughes 谢谢。我们这边见。 【参考方案1】:嗯,编写一个 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">
没有前导/
。
【讨论】:
您的解决方案效果很好!我需要做的唯一更改是match="structentry"
到match="dbk:structentry"
(因为我提到我使用dbk
命名空间作为输入)和key('child', 0)
到key('child', '0')
。另外我忘了提到拥有caller="true"
的人将拥有fill=white
。无论如何,我做了那个改变,一切看起来都很完美。谢谢!
嘿,@michael.hor257k 当一个结构图和另一个结构图共享相同的 id 时,它们似乎确实存在冲突。假设所有条目都有不同的 id,我如何真正区分每个结构图表的第一个条目(根节点)?
答案取决于您的处理器支持的 XSLT 版本。
P.S.请编辑您的问题并显示具有 2 个结构的 XML 示例。
查看这里如何确定:***.com/a/25245033/3016153以上是关于使用 XML 创建结构图并通过 LaTeX 呈现的主要内容,如果未能解决你的问题,请参考以下文章
在Delphi中,使用TreeView创建结构树,何种方法最好?