如何在DITA OT插件的XSLT中跨模板调用变量值
如何在DITA-OT XSLT中传递
output-class变量到map根模板 要把set-output-class模板里计算好的output-class相关变量传递给匹配/*[df:class(., 'map/map')]的模板,有两种实用方案,我结合你的代码示例详细说明:
方案一:直接在map根模板中获取值(最简单)
既然目标模板是处理map根元素,你可以直接在该模板内部重用set-output-class里的逻辑来获取对应的输出类值,不需要修改原有set-output-class模板。
修改你的目标map模板,新增变量来获取值:
<xsl:template match="/*[df:class(., 'map/map')]"> <xsl:param name="doDebug" as="xs:boolean" tunnel="yes" select="false()"/> <!-- 新增:获取当前map元素的output-class值,重用set-output-class里的逻辑 --> <xsl:variable name="map-output-class"> <!-- 先调用get-output-class mode获取基础值 --> <xsl:apply-templates select="." mode="get-output-class"/> <!-- 如果需要包含draft修订的内容,加上set-output-class里的draft-revs逻辑 --> <xsl:if test="$DRAFT = 'yes'"> <xsl:text> </xsl:text> <xsl:for-each select="*[contains(@class, ' ditaot-d/ditaval-startprop ')]/revprop"> <xsl:value-of select="@val"/> <xsl:text> </xsl:text> </xsl:for-each> </xsl:if> </xsl:variable> <!-- 现在可以直接使用$map-output-class变量了 --> <xsl:message>Debug: Map output class is '<xsl:value-of select="normalize-space($map-output-class)"/>'</xsl:message> <xsl:variable name="effectiveCoverGraphicUri" as="xs:string"> <xsl:apply-templates select="." mode="get-cover-graphic-uri"/> </xsl:variable> <!-- FIXME: Add mode to get effective front cover topic URI so we can generate <guide> entry for the cover page. Also provides extension point for synthesizing the cover if it's not explicit in the map. --> <xsl:apply-templates select="." mode="report-parameters"> <xsl:with-param name="effectiveCoverGraphicUri" select="$effectiveCoverGraphicUri" as="xs:string" tunnel="yes"/> <!-- 如果需要传递给report-parameters模板,直接加参数即可 --> <xsl:with-param name="map-output-class" select="normalize-space($map-output-class)"/> </xsl:apply-templates> <!-- 你的后续原代码 --> <xsl:variable name="graphicMap" as="element()"> <xsl:apply-templates select="." mode="generate-graphic-ma <!-- 继续原逻辑即可 --> </xsl:template>
这种方案的好处是不需要改动原有set-output-class模板,直接在需要的地方获取值,适合只在map根模板中使用该值的场景。
方案二:使用隧道参数传递(更灵活)
如果需要在多个模板之间传递这个值,或者set-output-class被多个地方调用时统一传递,XSLT的**隧道参数(tunnel parameters)**是最佳选择——它可以自动穿过中间模板,不需要每个中间模板都显式传递参数。
步骤1:修改set-output-class模板,添加隧道参数支持
<xsl:template match="*" mode="set-output-class"> <xsl:param name="default"/> <!-- 新增:控制是否传递输出类的隧道参数,默认关闭 --> <xsl:param name="enable-output-class-tunnel" as="xs:boolean" tunnel="yes" select="false()"/> <xsl:variable name="output-class"> <xsl:apply-templates select="." mode="get-output-class"/> </xsl:variable> <xsl:variable name="draft-revs"> <!-- 原代码不变 --> <xsl:if test="$DRAFT = 'yes'"> <xsl:for-each select="*[contains(@class, ' ditaot-d/ditaval-startprop ')]/revprop"> <xsl:value-of select="@val"/> <xsl:text> </xsl:text> </xsl:for-each> </xsl:if> </xsl:variable> <xsl:variable name="using-output-class"> <!-- 原代码不变 --> <xsl:choose> <xsl:when test="string-length(normalize-space($output-class)) > 0"><xsl:value-of select="$output-class"/></xsl:when> <xsl:when test="string-length(normalize-space($default)) > 0"><xsl:value-of select="$default"/></xsl:when> </xsl:choose> <xsl:if test="$draft-revs != ''"> <xsl:text> </xsl:text> <xsl:value-of select="normalize-space($draft-revs)"/> </xsl:if> </xsl:variable> <!-- 新增:如果启用隧道参数,传递最终的using-output-class值 --> <xsl:if test="$enable-output-class-tunnel"> <xsl:param name="resolved-output-class" select="normalize-space($using-output-class)" tunnel="yes"/> </xsl:if> <!-- 原代码的class属性输出部分不变 --> <xsl:variable name="ancestry"> <xsl:if test="$PRESERVE-DITA-CLASS = 'yes'"> <xsl:apply-templates select="." mode="get-element-ancestry"/> </xsl:if> </xsl:variable> <xsl:variable name="outputclass-attribute"> <xsl:apply-templates select="@outputclass" mode="get-value-for-class"/> </xsl:variable> <xsl:if test="string-length(normalize-space(concat($outputclass-attribute, $using-output-class, $ancestry))) > 0"> <xsl:attribute name="class"> <xsl:value-of select="$ancestry"/> <xsl:if test="string-length(normalize-space($ancestry)) > 0 and string-length(normalize-space($using-output-class)) > 0"><xsl:text> </xsl:text></xsl:if> <xsl:value-of select="$using-output-class"/> <xsl:if test="string-length(normalize-space(concat($ancestry, $using-output-class))) > 0 and string-length(normalize-space($outputclass-attribute)) > 0"><xsl:text> </xsl:text></xsl:if> <xsl:value-of select="$outputclass-attribute"/> </xsl:attribute> </xsl:if> </xsl:template>
步骤2:修改目标map模板,启用隧道参数并接收值
<xsl:template match="/*[df:class(., 'map/map')]"> <xsl:param name="doDebug" as="xs:boolean" tunnel="yes" select="false()"/> <!-- 接收隧道参数 --> <xsl:param name="resolved-output-class" tunnel="yes"/> <!-- 调用set-output-class时启用隧道参数传递 --> <xsl:apply-templates select="." mode="set-output-class"> <xsl:with-param name="default" select="''"/> <xsl:with-param name="enable-output-class-tunnel" select="true()" tunnel="yes"/> </xsl:apply-templates> <!-- 使用传递过来的变量 --> <xsl:if test="$doDebug"> <xsl:message>Debug: Resolved map output class: '<xsl:value-of select="$resolved-output-class"/>'</xsl:message> </xsl:if> <xsl:variable name="effectiveCoverGraphicUri" as="xs:string"> <xsl:apply-templates select="." mode="get-cover-graphic-uri"/> </xsl:variable> <!-- 可以继续把值传递给其他模板 --> <xsl:apply-templates select="." mode="report-parameters"> <xsl:with-param name="effectiveCoverGraphicUri" select="$effectiveCoverGraphicUri" as="xs:string" tunnel="yes"/> <xsl:with-param name="map-output-class" select="$resolved-output-class" tunnel="yes"/> </xsl:apply-templates> <!-- 你的后续原代码 --> <xsl:variable name="graphicMap" as="element()"> <xsl:apply-templates select="." mode="generate-graphic-ma <!-- 继续原逻辑 --> </xsl:template>
这种方案适合需要在多个模板间传递该值的场景,隧道参数会自动跳过中间的模板调用,直接传递到接收的模板。
结合你提供的DITA示例,比如pubmap里的<mainpubtitle outputclass="book">,get-output-class会处理这个值,最终传递到map模板的变量里。
内容的提问来源于stack exchange,提问作者User515
相关产品推荐
相关产品推荐

