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

时间:2015-08-11 14:39:05

标签: xml xslt xsl-fo

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

我试图瞄准像<xsl:number level="multiple" format="1.1." count="someNode | document(@href)/someOtherNode">之类的东西,但在'count'函数中,不可能使用'document()'函数。因此,必须有另一种方法来访问存储在其他“.xml”文档中的元素。

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

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

这是我想要的文件结构:

  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. 每个手册的
  4. 章节
    <map id="X000264" xml:lang="de-DE"> <topicref href="A.2+X000265.ditamap"/> </map>
  5. 内容(。dita)或 SUB-Chapters (。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>
  6. 所有这些文档都包含几个我想要计算和轻松访问的节点(例如,以防止过度使用文档(@ ...)功能。

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

    <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副本。然后,我可以轻松读取存储的变量节点树,而不必手动遍历所有文档。当然,我可以很容易地计算出特定类型的所有节点。

    提前致谢。

3 个答案:

答案 0 :(得分:1)

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

但是由于你省略了select属性,我假设你在计算上下文节点。除非上下文节点位于您所指的文档中,否则无法对其进行计数,因为该模式必须与当前节点匹配。如果上下文节点已经在您所指的文档中,则可以省略模式中的document函数(保留模式的其余部分),它将“正常工作”。

如果您试图计算模式无法捕获但需要选择表达式的内容,则应使用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来自其他文档,则必须确保当前匹配选择的顺序正确。默认情况下,选择多个文档具有实现定义的顺序。

简而言之,我认为您建议的方法很好。我怀疑它是否具有性能优势(因为您正在创建所有内容的副本),但只是让您的解决方案找到时间。

答案 1 :(得分:0)

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

  1. 创建存储在变量中的撰写文档(请参阅here
  2. 现在我可以根据变量来应用模板

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

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

答案 2 :(得分:0)

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

  1. 扩展的地图结构部分仅由topicref元素组成(在您的情况下)。
  2. 从地图部分引用的主题正文部分。
  3. 通常,TOC是由地图结构部分中的样式表通过计算topicref元素层次结构生成的。

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

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