使用XSL-FO Apache FOP渲染MathML时求和符号显示异常求助
问题:Apache FOP渲染MathML求和符号下限时自动换行
使用XSL-FO结合Apache FOP将MathML渲染为PDF时,多数公式显示正常,但求和符号的下限在输出PDF中被拆分为两行。尝试将MathML的display="block"改为display="inline"后,Oxygen XML Editor(Author模式)内显示正常,但生成PDF时问题仍存在。需要阻止该元素换行的可行方案。
Oxygen XML Editor显示效果

输入MathML
<disp-formula id="FD5"> <label>(5)</label> <mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" display="block" id="M144"> <mml:mrow><mml:msub><mml:mi>y</mml:mi><mml:mrow><mml:mi>i</mml:mi><mml:mo>,</mml:mo><mml:mn>1940</mml:mn></mml:mrow></mml:msub><mml:mo> </mml:mo><mml:mo>=</mml:mo><mml:mo> </mml:mo><mml:munder><mml:mo stretchy='true'>∑</mml:mo><mml:mrow><mml:mi>a</mml:mi><mml:mfenced><mml:mi>i</mml:mi></mml:mfenced><mml:mo><</mml:mo><mml:mn>64</mml:mn></mml:mrow></mml:munder><mml:mrow><mml:msub><mml:mo>µ</mml:mo><mml:mrow><mml:mi>a</mml:mi><mml:mfenced><mml:mi>i</mml:mi></mml:mfenced></mml:mrow></mml:msub><mml:mo> </mml:mo><mml:mo>×</mml:mo><mml:mo> </mml:mo><mml:msub><mml:mrow><mml:mi mathvariant="normal">RR</mml:mi></mml:mrow><mml:mrow><mml:mi>i</mml:mi><mml:mo>,</mml:mo><mml:mn>1930</mml:mn></mml:mrow></mml:msub><mml:mo> </mml:mo><mml:mo>+</mml:mo><mml:mo> </mml:mo></mml:mrow><mml:munder><mml:mo stretchy='true'>∑</mml:mo><mml:mrow><mml:mi>a</mml:mi><mml:mfenced><mml:mi>i</mml:mi></mml:mfenced><mml:mo>></mml:mo><mml:mn>64</mml:mn></mml:mrow></mml:munder><mml:mrow><mml:msub><mml:mi>γ</mml:mi><mml:mrow><mml:mi>a</mml:mi><mml:mfenced><mml:mi>i</mml:mi></mml:mfenced></mml:mrow></mml:msub><mml:mo> </mml:mo><mml:mo>×</mml:mo><mml:mo> </mml:mo><mml:msub><mml:mrow><mml:mi mathvariant="normal">RR</mml:mi></mml:mrow><mml:mrow><mml:mi>i</mml:mi><mml:mo>,</mml:mo><mml:mn>1930</mml:mn></mml:mrow></mml:msub><mml:mo> </mml:mo><mml:mo>+</mml:mo><mml:mo> </mml:mo><mml:msub><mml:mi>ε</mml:mi><mml:mrow><mml:mi>i</mml:mi><mml:mo>,</mml:mo><mml:mn>1930</mml:mn></mml:mrow></mml:msub></mml:mrow></mml:mrow> </mml:math> </disp-formula>
期望输出效果

实际生成PDF效果

现有XSL模板
<xsl:template match="mml:math"> <xsl:choose> <xsl:when test="display='block'"> <fo:block> <fo:instream-foreign-object> <xsl:element name="{local-name()}" xmlns="http://www.w3.org/1998/Math/MathML"> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:element> </fo:instream-foreign-object> </fo:block> </xsl:when> <xsl:otherwise> <fo:instream-foreign-object> <xsl:element name="{local-name()}" xmlns="http://www.w3.org/1998/Math/MathML"> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:element> </fo:instream-foreign-object> </xsl:otherwise> </xsl:choose> </xsl:template>
解决方案建议
1. 为求和下限添加不可换行约束
在MathML的求和下限mrow中添加linebreak="nobreak"属性,强制阻止内部换行:
<mml:mrow linebreak="nobreak"> <mml:mi>a</mml:mi> <mml:mfenced><mml:mi>i</mml:mi></mml:mfenced> <mml:mo><</mml:mo> <mml:mn>64</mml:mn> </mml:mrow>
如果需要通过XSL自动处理,新增模板匹配mml:munder/mml:mrow,自动注入该属性:
<xsl:template match="mml:munder/mml:mrow"> <mml:mrow linebreak="nobreak"> <xsl:apply-templates select="@* | node()"/> </mml:mrow> </xsl:template>
2. 调整FO容器的换行属性
在fo:instream-foreign-object外层的fo:block或直接在fo:instream-foreign-object上设置wrap-option="no-wrap",限制外部容器的换行行为:
<fo:block wrap-option="no-wrap"> <fo:instream-foreign-object> <!-- MathML内容 --> </fo:instream-foreign-object> </fo:block>
或针对block类型的Math单独设置:
<xsl:when test="display='block'"> <fo:block wrap-option="no-wrap"> <fo:instream-foreign-object> <!-- ... --> </fo:instream-foreign-object> </fo:block> </xsl:when>
3. 升级Apache FOP版本
部分旧版FOP对MathML的布局支持存在缺陷,升级到最新稳定版(如2.8+)可能已修复此类换行异常问题。
4. 调整求和符号的布局属性
给munder标签添加accent="false"属性,强制FOP使用更严格的水平布局规则:
<mml:munder accent="false"> <mml:mo stretchy='true'>∑</mml:mo> <mml:mrow>...</mml:mrow> </mml:munder>
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

