XSL-FO技术问题:如何根据文本宽度调整容器边框宽度
求助:Apache FOP中让带圆角边框的容器自动适配文本宽度
我在用Apache FOP处理XSL-FO时碰到个问题,想请大家帮忙看看:
我已经写了简单的样式表,给fo:block-container加了圆角边框,但这个.fo文件是通过XSLT和XML生成的,里面的文本长度完全不可预测。现在的问题是容器边框宽度是固定的,我想让FOP根据文本内容自动调整容器宽度,而不是给所有容器都用统一的固定宽度。
现有代码:
XSLT文件片段:
<fo:block-container xsl:use-attribute-sets="right-side-itens"> <fo:block-container xsl:use-attribute-sets="rounded-borders"> <fo:block> <xsl:value-of select="./tagInsideXML/@attribute" /> <!-- 示例文本:qwertyuiopasdfghjkl --> </fo:block> </fo:block-container> <!-- 其他内容 --> </fo:block-container>
外部样式文件styles.xsl片段:
<xsl:attribute-set name="right-side-itens"> <xsl:attribute name="top">35px</xsl:attribute> <xsl:attribute name="right">45px</xsl:attribute> <xsl:attribute name="text-align">end</xsl:attribute> <xsl:attribute name="font-size">10px</xsl:attribute> <xsl:attribute name="height">10cm</xsl:attribute> <xsl:attribute name="width">200px</xsl:attribute> <xsl:attribute name="position">absolute</xsl:attribute> </xsl:attribute-set> <xsl:attribute-set name="rounded-borders"> <xsl:attribute name="margin-top">2px</xsl:attribute> <xsl:attribute name="margin-right">1.8px</xsl:attribute> <xsl:attribute name="padding-right">2px</xsl:attribute> <xsl:attribute name="float">right</xsl:attribute> <xsl:attribute name="line-height">18px</xsl:attribute> <xsl:attribute name="font-size">8px</xsl:attribute> <xsl:attribute name="border">solid 1.2px #000000</xsl:attribute> <xsl:attribute name="fox:border-radius">6px</xsl:attribute> <xsl:attribute name="position">relative</xsl:attribute> <xsl:attribute name="overflow">visible</xsl:attribute> </xsl:attribute-set>
我想要的效果是:圆角边框容器能刚好包裹住里面的文本,文本短的时候容器就窄,文本长的时候容器就跟着变宽,不会出现固定宽度导致的多余空白或者文本换行的问题。
解决思路和修改方案:
核心问题在于fo:block-container默认是块级元素,会占据父容器的全部可用宽度,没法自动收缩适配内容。我们可以通过两个调整来实现需求:
- 替换容器类型:把内层的
fo:block-container换成fo:inline-container——inline-container是行内级容器,天生会根据内部内容的宽度自动调整自身宽度,完美适配这种包裹文本的场景。 - 调整样式属性:去掉不必要的浮动设置,确保容器宽度不受固定值限制。
修改后的代码:
XSLT片段:
<fo:block-container xsl:use-attribute-sets="right-side-itens"> <!-- 把block-container换成inline-container --> <fo:inline-container xsl:use-attribute-sets="rounded-borders"> <fo:block> <xsl:value-of select="./tagInsideXML/@attribute" /> <!-- 示例文本:qwertyuiopasdfghjkl --> </fo:block> </fo:inline-container> <!-- 其他内容 --> </fo:block-container>
styles.xsl中的rounded-borders属性集:
<xsl:attribute-set name="rounded-borders"> <xsl:attribute name="margin-top">2px</xsl:attribute> <xsl:attribute name="margin-right">1.8px</xsl:attribute> <xsl:attribute name="padding-right">2px</xsl:attribute> <!-- 去掉float:right,外层的text-align:end已经能让inline-container靠右对齐 --> <xsl:attribute name="line-height">18px</xsl:attribute> <xsl:attribute name="font-size">8px</xsl:attribute> <xsl:attribute name="border">solid 1.2px #000000</xsl:attribute> <xsl:attribute name="fox:border-radius">6px</xsl:attribute> <xsl:attribute name="position">relative</xsl:attribute> <xsl:attribute name="overflow">visible</xsl:attribute> <!-- 明确设置宽度自动适配内容 --> <xsl:attribute name="width">auto</xsl:attribute> </xsl:attribute-set>
额外说明:
- 外层的
right-side-itens设置了text-align:end,这个属性会让里面的inline-container自动靠右对齐,刚好替代原来的float:right效果,同时避免浮动带来的布局问题。 - 如果你的文本可能很长需要换行,可以给
fo:block添加wrap-option="wrap"属性,确保文本在容器宽度内自动换行,容器也会跟着调整高度。
内容的提问来源于stack exchange,提问作者Evandro Teixeira
相关产品推荐
相关产品推荐

