我正在创建一个xsl-fo到rtf样式表。我遇到的一个问题是将xsl-fo文档中的众多度量单位转换为缇(rtf度量单位)。
一段特殊的代码可以计算列的宽度:
<xsl:value-of select="sum(preceding-sibling:
:fo:table-column/@column-width) + @column-width"/>
...问题是/@column-width
的值可以是1in
(1英寸)到20px
(20像素)的任何值,所以当我做总和时它会失败。
我需要以某种方式将@column-width
转换为twip equivelant:
1pt = 19.95 twips, 1px = 15 twips, 1pc = 240 twips, 1in = 1440 twips, 1cm = 567 twips, 1mm = 56.7 twips, 1em = 240 twips
我可以编写一个可以进行转换的方法,但我确信有一些方法可以利用translate()
函数来更有效地完成这项工作。
请注意我的xsl并不是那么好,所以如何实现这一点的例子将不胜感激
修改
我设法找到了我想要的东西,但不知道如何从上面的计算中调用这个模板:
<xsl:template match="@*" mode="convert-to-twips">
<xsl:variable name="scaling-factor">
<xsl:choose>
<xsl:when test="contains (., 'pt')">19.95</xsl:when>
<xsl:when test="contains (., 'px')">15</xsl:when>
<xsl:when test="contains (., 'pc')">240</xsl:when>
<xsl:when test="contains (., 'in')">1440</xsl:when>
<xsl:when test="contains (., 'cm')">567</xsl:when>
<xsl:when test="contains (., 'mm')">56.7</xsl:when>
<xsl:when test="contains (., 'em')">240</xsl:when>
<!-- guess: 1em = 12pt -->
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="numeric-value"
select="translate (., '-0123456789.ptxcinme', '-0123456789.')"/>
<xsl:value-of select="$numeric-value * $scaling-factor"/>
</xsl:template>
答案 0 :(得分:3)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
xmlns:fo="some:fo" xmlns:my="my:my" >
<xsl:output method="text"/>
<my:units>
<unit name="pt">19.95</unit>
<unit name="in">1440</unit>
<unit name="cm">567</unit>
<unit name="mm">56.7</unit>
<unit name="em">240</unit>
<unit name="px">15</unit>
<unit name="pc">240</unit>
</my:units>
<xsl:variable name="vUnits" select=
"document('')/*/my:units/*"/>
<xsl:template match="/">
<xsl:apply-templates select="*/*/*/@column-width"/>
</xsl:template>
<xsl:template match="@column-width">
<xsl:variable name="vQuantity" select=
"substring(.,1, string-length() -2)"/>
<xsl:variable name="vUnit" select=
"substring(., string-length() -1)"/>
<xsl:variable name="vrtfAccumWidth">
<num>0</num>
<xsl:for-each select=
"../preceding-sibling::fo:table-column/@column-width">
<xsl:variable name="vQ" select=
"substring(.,1, string-length() -2)"/>
<xsl:variable name="vU" select=
"substring(., string-length() -1)"/>
<num>
<xsl:value-of select=
"$vQ * $vUnits[@name=$vU]"/>
</num>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select=
"$vQuantity * $vUnits[@name=$vUnit]
+
sum(ext:node-set($vrtfAccumWidth)/num)
"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
应用于以下XML文档时(因为没有提供!):
<fo:fo xmlns:fo="some:fo">
<fo:table>
<fo:table-column column-width="2pt"/>
<fo:table-column column-width="2in"/>
<fo:table-column column-width="2cm"/>
<fo:table-column column-width="2mm"/>
<fo:table-column column-width="2em"/>
<fo:table-column column-width="2px"/>
<fo:table-column column-width="2pc"/>
</fo:table>
</fo:fo>
生成想要的正确结果:
39.9
2919.9
4053.9
4167.3
4647.3
4677.3
5157.3
注意:如果fo:table-column\@column-width
的大序列需要更高效的解决方案,那么 FXSL - {{ 3}} 可以使用模板/函数 - 有关完整的代码示例,请参阅我之前问题的答案。
答案 1 :(得分:1)
您可以使用此模板来使用现有的模板:
<xsl:template match="@column-width">
<xsl:variable name="previous">
0<xsl:apply-templates select="../preceding-sibling::*[1]/@column-width" />
</xsl:variable>
<xsl:variable name="this">
<xsl:apply-templates select="." mode="convert-to-twips"/>
</xsl:variable>
<xsl:value-of select="$previous + $this" />
</xsl:template>
您可以看到,只需计算先前列的宽度,然后将其添加到当前列,这是相当简单的。您可能会注意到第一个变量中<xsl:apply-templates
指令前面有一个0;这是为了确保给变量一个有效的数字。如果没有以前的列,那么它将存储'0'而不是''。
严格地说,您可以包含现有模板的正文代替第二个变量,并在底部包含<xsl:value-of select="$previous + ($numeric-value * $scaling-factor)" />
;这完全取决于你。
答案 2 :(得分:1)
您还可以使用模板功能和xsl:call-template
。窃取@Dimitre输入示例(不要讨厌我:)我将向您展示如何将转换模板规则与xsl:call-template
一起使用。
在变换中,我迭代每个table-column
,从而收集转换后的值。要转换值,我只是调用原始模板规则(稍微调整一下)。然后我使用sum
来执行值的总和。
请注意,如果不将translate
返回的值强制转换为数字,则符合XSLT 2.0标准的处理器将返回运行时错误。
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="some:fo">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="fo:table/fo:table-column">
<xsl:variable name="twips">
<twips>
<xsl:for-each select="preceding-sibling::fo:table-column/@column-width">
<twip>
<xsl:call-template name="convert-to-twips">
<xsl:with-param name="value" select="."/>
</xsl:call-template>
</twip>
</xsl:for-each>
<twip>
<xsl:call-template name="convert-to-twips">
<xsl:with-param name="value" select="@column-width"/>
</xsl:call-template>
</twip>
</twips>
</xsl:variable>
<xsl:value-of select="sum($twips//twip)"/><xsl:text> </xsl:text>
</xsl:template>
<xsl:template name="convert-to-twips">
<xsl:param name="value"/>
<xsl:variable name="scaling-factor">
<xsl:choose>
<xsl:when test="contains ($value, 'pt')">19.95</xsl:when>
<xsl:when test="contains ($value, 'px')">15</xsl:when>
<xsl:when test="contains ($value, 'pc')">240</xsl:when>
<xsl:when test="contains ($value, 'in')">1440</xsl:when>
<xsl:when test="contains ($value, 'cm')">567</xsl:when>
<xsl:when test="contains ($value, 'mm')">56.7</xsl:when>
<xsl:when test="contains ($value, 'em')">240</xsl:when>
<!-- guess: 1em = 12pt -->
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="numeric-value"
select="number(translate ($value, '-0123456789.ptxcinme', '-0123456789.'))"/>
<xsl:value-of select="$numeric-value * $scaling-factor"/>
</xsl:template>
</xsl:stylesheet>
此变换适用于输入:
<fo:fo xmlns:fo="some:fo">
<fo:table>
<fo:table-column column-width="2pt"/>
<fo:table-column column-width="2in"/>
<fo:table-column column-width="2cm"/>
<fo:table-column column-width="2mm"/>
<fo:table-column column-width="2em"/>
<fo:table-column column-width="2px"/>
<fo:table-column column-width="2pc"/>
</fo:table>
</fo:fo>
产地:
39.9 2919.9 4053.9 4167.3 4647.3 4677.3 5157.3