DITA 中的 TOC - 计算不同文档中的节点

TOC in DITA - Count nodes in different documents

如何使用 xsl:number 函数访问和计算链接 xml 文档中的节点?[​​=16=]

我正在尝试瞄准 <xsl:number level="multiple" format="1.1." count="someNode | document(@href)/someOtherNode"> 之类的目标,但在 'count' 函数中无法使用 'document()' 函数。因此,必须有另一种方法来访问存储在其他 '.xml' - documents.

中的元素

编辑
据我了解,我必须创建一个 我的整个节点结构的临时副本 以获得第一性能和第二可读性(当然还有第三 - 可访问性)。

我的想法:我想将整个嵌套节点树存储在一个可读变量中。因此我必须创建一个变量并将所有节点及其内容复制到其中。

这是我想要的文件结构:

  1. Root 文档 .XML 包含所有特定语言的文档作为 ditamaps
    <map> <navref mapref="de-DE/A.2+X000263.ditamap"/> <navref mapref="en-US/A.2+X000263.ditamap"/> <navref mapref="es-ES/A.2+X000263.ditamap"/> </map>
  2. 特定语言手册 (.ditamap) - 可能有多个文档
    <bookmap id="X000263" xml:lang="de-DE"> <chapter href="A.2+X000264.ditamap"/> </bookmap>
  3. 每个手册的章节
    <map id="X000264" xml:lang="de-DE"> <topicref href="A.2+X000265.ditamap"/> </map>
  4. 目录 (.dita) 或 子章节 (.ditamap)
    <map id="X000265" xml:lang="de-DE"> <topicref href="A.2+X000266.dita"/> <topicref href="A.2+X000269.dita"/> <topicref href="A.2+X000267.ditamap"/> </map>

所有这些文档都包含几个节点,我想计算这些节点并轻松访问它们(例如,为了防止过度使用 document(@...) 函数。

我开始创建所有内容的临时副本,如下所示:

<xsl:variable name="spine"> <xsl:for-each select="collection('../../?select=*.xml;recursive=yes')"> <xsl:for-each select="//*"> <xsl:copy-of select="current()"/> </xsl:for-each> </xsl:for-each> </xsl:variable>

我的目标是找到一个解决方案,该解决方案仅以正确的顺序读取所有 .xml / .ditamap /.dita 文档,并为我提供所有节点的 1:1 副本和内容。然后我可以轻松读取存储的变量节点树,而不必手动遍历所有文档。当然,我可以很容易地计算出特定类型的所有节点。

提前致谢。

在 XSLT 3.0 中,您可以在模式中使用 doc 函数(count 属性是一种模式),但我怀疑这对您是否有帮助。

但是由于您省略了 select 属性,我假设您正在计算上下文节点。除非上下文节点在你引用的文档中,否则没有办法统计它,因为模式必须匹配当前节点。如果上下文节点已经在您引用的文档中,您可以省略模式中的 document 函数(保留模式的其余部分),它将 "just work".

如果您尝试计算模式无法捕获的内容,但需要 select 表达式,那么您应该使用 count 表达式的组合手动创建数字。由于我不知道你的输入文件,所以我真的不能举个例子。

编辑(编辑后)

<xsl:for-each select="//*">
   <xsl:copy-of select="current()"/>
</xsl:for-each>

不要这样做(对不起粗体;)。这具有创建每个后代元素的副本的效果。即:

输入:

<root>
   <child>
      <deeper>
   </child>
</root>

会产生这样的输出(注意每个后代是如何被再次复制的):

<root>
   <child>
      <deeper/>
   </child>
</root>
<child>
   <deeper/>
</child>
<deeper/>

事实上,按照这些思路应该足够了(我添加了原始 URI,可能有助于调试):

<xsl:variable name="spine">
    <xsl:for-each select="collection('../../?select=*.xml;recursive=yes')">
        <doc original-href="{base-uri()}">
            <!-- assuming you do not need any comments in the root of the document -->
            <xsl:copy-of select="/*"/>
        </doc>
    </xsl:for-each>
</xsl:variable>

如果你不做副本,我想你还是可以得到你想要的,但是就像上面说的,你可能需要自己做一些计算。

我没有提到的事情:如果你想计算来自多个来源的节点,并且它们仅在元素名称上有所不同,那么只写 count="someNode | someOtherNode" 可能就足够了。但是,如果 someOtherNode 来自不同的文档,那么您必须确保当前匹配的 selection 的顺序正确。默认情况下,selecting 多个文档具有实现定义的顺序。

总之,我觉得你建议的方法很好。我怀疑它是否具有性能优势(因为您正在创建所有内容的副本),但只需花点时间找出您的解决方案。

经过一些研究和对 Whosebug 的另一个请求后,我得到了满足我需要的可行解决方案。以下描述了我现在处理这种情况的方式:

  1. 创建一个组合文档(参见)存储在一个变量
  2. 现在我可以像这样根据变量应用模板了

    <xsl:apply-templates select="$myVar/document/*"/>

  3. 有了这个,我可以轻松地访问和计算这个 单一来源 文档中存在的每个节点(据我所知,这不容易计算不在单个文档中的节点)

使用DITA-OT(http://www.dita-ot.org/)从根文档(map)制作复合中间文件。 DITA-OT 的 "preprocess" 和 "TopicMerge" 处理将生成以下结构化合并中间文件:

  1. 扩展的地图结构部分仅由 topicref 元素组成(在您的情况下)。
  2. 从地图部分引用的主题正文部分。

通常,TOC 是由样式表从地图结构部分通过计算 topicref 元素层次结构生成的。

从您的示例中,我注意到根地图由 navref 元素组成。 navref 引用不会从其 DITA 定义中解析。使用 mapref 元素而不是 navref 将解析引用,引用的内容将包含到合并的中间文件中。

这是完成您的要求的最方便的方法。