如何为fo:block批量应用样式属性并保留自定义属性(XSL:FO)
解决XSL:FO中fo:block样式属性冗余的方案
方法一:使用xsl:attribute-set定义复用样式
这是XSL:FO官方推荐的样式复用方式,语法简洁且原生支持。
- 先定义属性集,把同一类样式的属性打包:
<!-- 在XSLT根节点下定义属性集 --> <xsl:attribute-set name="h2-font-style"> <xsl:attribute name="font-size">16pt</xsl:attribute> <xsl:attribute name="letter-spacing">0.1em</xsl:attribute> <xsl:attribute name="font-weight">bold</xsl:attribute> <!-- 可添加其他需要复用的文本样式属性 --> </xsl:attribute-set>
- 使用时直接引用属性集,同时保留添加自定义属性的能力:
<fo:block xsl:use-attribute-sets="h2-font-style" margin-left="10mm"> 这里是标题内容 </fo:block>
- 若需要同时应用多个属性集,用空格分隔即可:
xsl:use-attribute-sets="h2-font-style common-block-style" - 自定义属性会覆盖属性集中的同名属性(若存在冲突)。
方法二:自定义模板封装fo:block
如果需要更灵活的动态逻辑(比如根据参数切换样式),可以用模板封装:
- 定义带参数的模板:
<xsl:template name="styled-block"> <xsl:param name="style-type" select="'default'"/> <xsl:param name="custom-attributes" as="attribute()*" select="()"/> <fo:block> <!-- 根据样式类型设置对应属性 --> <xsl:if test="$style-type = 'h2'"> <xsl:attribute name="font-size">16pt</xsl:attribute> <xsl:attribute name="letter-spacing">0.1em</xsl:attribute> <xsl:attribute name="font-weight">bold</xsl:attribute> </xsl:if> <xsl:if test="$style-type = 'h1'"> <xsl:attribute name="font-size">20pt</xsl:attribute> <xsl:attribute name="letter-spacing">0.2em</xsl:attribute> <xsl:attribute name="font-weight">900</xsl:attribute> </xsl:if> <!-- 应用自定义属性 --> <xsl:copy-of select="$custom-attributes"/> <!-- 传递子内容 --> <xsl:apply-templates/> </fo:block> </xsl:template>
- 调用模板时传入参数和自定义属性:
<xsl:call-template name="styled-block"> <xsl:with-param name="style-type" select="'h2'"/> <xsl:with-param name="custom-attributes"> <xsl:attribute name="margin-left">10mm</xsl:attribute> </xsl:with-param> <xsl:text>这里是标题内容</xsl:text> </xsl:call-template>
方法三:XSLT 2.0+ 自定义函数生成属性节点
如果想要接近你设想的函数调用形式,可以用XSLT 2.0及以上版本的自定义函数返回属性序列:
- 定义函数(需先声明自定义命名空间):
<!-- 在XSLT头部添加命名空间声明 --> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:my="http://example.com/my-functions"> <xsl:function name="my:applyFontStyle" as="attribute()*"> <xsl:param name="style-type" as="xs:string"/> <xsl:choose> <xsl:when test="$style-type = 'h2'"> <xsl:attribute name="font-size">16pt</xsl:attribute> <xsl:attribute name="letter-spacing">0.1em</xsl:attribute> <xsl:attribute name="font-weight">bold</xsl:attribute> </xsl:when> <xsl:when test="$style-type = 'h1'"> <xsl:attribute name="font-size">20pt</xsl:attribute> <xsl:attribute name="letter-spacing">0.2em</xsl:attribute> <xsl:attribute name="font-weight">900</xsl:attribute> </xsl:when> <xsl:otherwise> <!-- 默认样式 --> <xsl:attribute name="font-size">12pt</xsl:attribute> </xsl:otherwise> </xsl:choose> </xsl:function>
- 使用时复制函数返回的属性:
<fo:block margin-left="10mm"> <xsl:copy-of select="my:applyFontStyle('h2')"/> 这里是标题内容 </fo:block>
方案选型建议
- 优先用
xsl:attribute-set:原生支持、语法简洁、性能最优,适合固定样式的复用。 - 模板封装适合需要动态逻辑或复杂参数控制的场景。
- 自定义函数适合追求函数式写法的场景,但需要XSLT 2.0+环境支持。
内容的提问来源于stack exchange,提问作者Ambidex
相关产品推荐
相关产品推荐

