在第一次出现时插入图像
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 版本的可读性差得多。
我有一个 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 版本的可读性差得多。