首次出现时插入图像

时间:2016-03-03 18:37:10

标签: xslt xsl-fo apache-fop

我有一个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),同时将文本保持为标题。每个其他出现(不是第一个)应该只是包含插入图像的内部基本链接的内联文本。 我目前的解决方案是:

  <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,因此某些图像未正确插入。我有什么选择? 谢谢!

编辑:我应该澄清一下。图像应该在第一次出现时插入新的&#34; refid。从而。每个refid只有一个图片,而每个其他cross-ref元素都有refid个指向该图片

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

如果您使用的是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()按文档顺序(https://www.w3.org/TR/xslt20/#keys)返回节点。这可能比使用preceding轴更快(在大型文档上),但是要确保您必须通过使用XSLT处理器运行文档来测试它。

如果你正在使用XSLT 1.0,那么你必须使用类似Meunchian Grouping的技巧来做这件事:

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

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