在第一次出现时插入图像

Insert image on first occurence

我有一个 xml 文档,看起来像这样:

<chapter>
    <para>Just a random text<cross-ref refid="1234">Abb. 1.0</cross-ref>Some more text</para>
    <section-title>Title</section-title>
    <para>and more text text ext<cross-ref refif="1234">Abb 1.0</cross-ref>more more more</para>
</chapter>

如您所见,段落内有两个 cross-ref 元素。它们基本上无处不在,并且在某种程度上由它们的 refid(但不是唯一的)标识。我目前正在尝试做的是在第一次出现的位置插入图像(基于 refid),同时将文本保留为标题。其他每一次出现(不是第一次出现)都应该只是包含插入图像的内部 basic-link 的内联文本。 我目前的解决方案是:

  <xsl:template match="cross-ref">
    <xsl:choose>
      <xsl:when test="position() = 1">
        <fo:block text-align="center" id="{@refid}">
          <xsl:variable name="refVar" select="@refid"/>
          <xsl:variable name="imageName" select="/chapter/floats/figure[@id=$refVar]/link/@locator" />
          <fo:external-graphic src="url({concat($imageName, '.jpg')})" />
          <fo:block text-align="center" xsl:use-attribute-sets="lit-para">
            <xsl:value-of select="current()" />
          </fo:block>
        </fo:block>
      </xsl:when>

      <xsl:otherwise>
        <fo:basic-link internal-destination="{@refid}">
          <xsl:value-of select="current()" />
        </fo:basic-link>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

它在某些情况下确实有效,但由于 position() 并不总是 1,因此某些图像无法正确插入。我有哪些选择? 谢谢!

编辑:我应该澄清一下。应该在 "new" refid 第一次出现时插入图像。因此。每个 refid 只有一个图像,每个其他 cross-ref 具有相同 refid 的元素指向该图像

您必须更改 xsl:when 中的测试,以便它仅在每个 @ref-id 值的第一次出现时为真;换句话说,您必须检查前面的 cross-ref 元素是否没有相同的 @ref-id:

<xsl:when test="not(preceding::cross-ref[@ref-id = current()/@ref_id])">
...

如果您使用 XSLT 2.0 或 XSLT 3.0,如果您添加 xsl:key 作为顶级元素:

<xsl:key name="cross-ref" match="cross-ref" use="@refid" />

那么您可以将 xsl:when 更改为:

<xsl:when test=". is key('cross-ref', @refid)[1]">

这是有效的,因为 key() returns 个文档顺序中的节点 (https://www.w3.org/TR/xslt20/#keys)。这可能比使用 preceding 轴更快(在大型文档上),但为了确保您必须使用 XSLT 处理器在文档上 运行 对其进行测试。

如果您使用的是 XSLT 1.0,则必须使用类似 Meunchian 分组的技巧:

<xsl:when test="count(. | key('cross-ref', @refid)[1]) = 1">

但这比 XSLT 2.0 版本的可读性差得多。