XSLT跨模板变量传递问题:如何在多模板间共享唯一ID
XSLT跨模板传递唯一ID的解决方案
问题背景
需要给<uicontrol>生成的容器元素分配唯一ID,并让后续对应的<codeblock>元素的链接指向该ID。但当前<uicontrol>模板内生成的ID变量因作用域限制,无法在<codeblock>模板中直接调用。
现有代码片段:
<xsl:template match="uicontrol"> <xsl:variable name="id" select="generate-id()"/> <div class="ft-expanding-block" id="{$id}"/> </xsl:template> <xsl:template match="codeblock"> <h1><span class="ft-expanding-block-link" data-target-id="{$id}"> <xsl:apply-templates/> </span></h1> </xsl:template>
对应的XML示例:
<uicontrol>Show example</uicontrol>. <codeblock> HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 { "id":"a7d67610-ceb5-4350-ba5a-746472c4f1f7", "schemas": [ "urn:scim:schemas:core:1.0", "urn:scim:schemas:com_pingone:1.0" ], </codeblock> <p class="- topic/p">The following code block should be expanded on page load with the label <uicontrol>Hide example</uicontrol>.</p> <codeblock> HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 { </codeblock>
核心问题分析
XSLT变量具有模板级作用域,<uicontrol>模板内定义的$id无法直接在<codeblock>模板中访问。同时需要明确:从XML结构看,每个<uicontrol>与后续紧跟的<codeblock>是一一对应的关联关系。
解决方案
方法1:利用generate-id()的节点唯一性实现关联
generate-id()函数对同一个节点的返回值是固定唯一的,因此可以在<codeblock>模板中直接获取对应<uicontrol>节点的ID:
<!-- uicontrol模板保持生成ID逻辑 --> <xsl:template match="uicontrol"> <xsl:variable name="id" select="generate-id()"/> <div class="ft-expanding-block" id="{$id}"> <xsl:apply-templates/> </div> </xsl:template> <!-- codeblock模板通过兄弟节点定位对应uicontrol并获取ID --> <xsl:template match="codeblock"> <!-- 获取当前codeblock之前最近的uicontrol节点 --> <xsl:variable name="target-uicontrol" select="preceding-sibling::uicontrol[1]"/> <h1> <span class="ft-expanding-block-link" data-target-id="{generate-id($target-uicontrol)}"> <xsl:apply-templates/> </span> </h1> </xsl:template>
方法2:提前存储ID到节点属性(适配复杂结构)
如果XML结构更复杂,兄弟节点关系不明确,可以将ID存储到<uicontrol>的临时属性中,后续模板直接读取:
<!-- 定义key用于快速查找uicontrol节点(可选,按需使用) --> <xsl:key name="uicontrol-by-temp-id" match="uicontrol" use="@temp-id"/> <!-- uicontrol模板生成ID并存储到临时属性 --> <xsl:template match="uicontrol"> <xsl:variable name="id" select="generate-id()"/> <xsl:copy> <xsl:attribute name="temp-id" select="$id"/> <div class="ft-expanding-block" id="{$id}"> <xsl:apply-templates/> </div> </xsl:copy> </xsl:template> <!-- codeblock模板读取对应uicontrol的临时ID --> <xsl:template match="codeblock"> <xsl:variable name="target-uicontrol" select="preceding-sibling::uicontrol[1]"/> <h1> <span class="ft-expanding-block-link" data-target-id="{$target-uicontrol/@temp-id}"> <xsl:apply-templates/> </span> </h1> </xsl:template>
内容的提问来源于stack exchange,提问作者Badiou30120
相关产品推荐
相关产品推荐

