xsl 转换/翻译模板

发布于 2024-11-09 10:08:25 字数 1683 浏览 0 评论 0 原文

我正在创建一个 xsl-fo 到 rtf 样式表。我遇到的问题之一是将 xsl-fo 文档中的众多测量单位转换为缇(rtf 测量单位)。

一段特定的代码计算列的宽度:

<xsl:value-of select="sum(preceding-sibling:
   :fo:table-column/@column-width) + @column-width"/>

...问题是 /@column-width 的值可以是从 1in(1 英寸)到 < code>20px(20像素),所以当我求和时它会失败。

我需要以某种方式将 @column-width 转换为缇等值: 1pt = 19.95 缇,1px = 15 缇,1pc = 240 缇,1in = 1440 缇,1cm = 567 缇,1mm = 56.7 缇,1em = 240 缇

我也许可以写一个可以做到的方法转换,但我相信有一些使用 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>

I am creating an xsl-fo to rtf style sheet. One of the problems I have is to convert the numerous units of measure in a xsl-fo document to twips (rtf unit of measure).

One particular piece of code caluclates the widths of the columns:

<xsl:value-of select="sum(preceding-sibling:
   :fo:table-column/@column-width) + @column-width"/>

...problem being the value of /@column-width could be anything from 1in(1 inch) to 20px(20 pixels), so when I do the sum it will fail.

I need to somehow convert @column-width to a 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

I can probably write a method that can do the conversion, but I am convinced there is some way to make use of the translate() function to do this much more efficiantly.

Please take note that my xsl is not all that great, so an example of how to achieve this will be appreciated

EDIT

I managed to find something I want, but have no idea how to call this template from the above calculation:

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云淡风轻 2024-11-16 10:08:25

此转换

<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 - scanl 可以使用模板/函数 - 请参阅我的回答您上一个问题的完整代码示例。

This transformation:

<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>

when applied on the following XML document (as none was provided!):

<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>

produces the wanted, correct result:

39.9
2919.9
4053.9
4167.3
4647.3
4677.3
5157.3

Notice: If a more efficient solution is needed for a big sequence of fo:table-column\@column-width, then the FXSL - scanl template/function can be used -- see my answer to your previous question for a complete code example.

甜心小果奶 2024-11-16 10:08:25

您可以使用此模板来利用现有的模板:

<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>

正如您所看到的,它相当简单,只需计算前一列的宽度,然后将其添加到当前一列即可。您可能会注意到第一个变量中的 指令前面有一个 0;这是为了确保为变量提供了有效的数字。如果没有前面的列,那么它将存储“0”而不是“”。

严格来说,您可以包含现有模板的主体来代替第二个变量,并使用 位于底部;这完全取决于你。

You can use this template to make use of the existing one you have:

<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>

It's fairly straightforward as you can see, simply calculating the width of previous columns, then adding it to the current one. You'll probably notice there's a 0 in front of the <xsl:apply-templates instruction in the first variable; that's to make sure that a valid number is given to the variable. If there are no previous columns, then it'll store '0' instead of ''.

Strictly speaking, you could include the body of your existing template in place of the second variable, and have <xsl:value-of select="$previous + ($numeric-value * $scaling-factor)" /> at the bottom; that's entirely up to you.

老旧海报 2024-11-16 10:08:25

您还可以使用模板函数和 xsl:call-template。窃取 @Dimitre 输入示例(别恨我:)我将向您展示如何将转换模板规则与 xsl:call-template 一起使用。

在转换中,我迭代每个表列,从而收集转换后的值。要转换该值,我只是调用您的原始模板规则(稍作调整)。然后我使用 sum 来计算值的总和。

请注意,如果您不将 translate 返回的值转换为数字,XSLT 2.0 兼容处理器将返回运行时错误。


XSLT 2.0Saxon-B 9.0.0.4J 下测试

<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 

You can also go with a template function and xsl:call-template. Stealing @Dimitre input example (don't hate me :) I show you how you can use your conversion template rule with xsl:call-template.

In the transform I iterate on each table-column thus gathering the converted values. To convert the value I'm just calling your original template rule (a bit tuned). Then I use sum to perform the sum of the values.

Note that an XSLT 2.0 compliant processor will return a runtime error if you don't cast the value returned by translate to a number.


XSLT 2.0 tested under Saxon-B 9.0.0.4J

<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>

This transform applied on the input:

<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>

Produces:

39.9 2919.9 4053.9 4167.3 4647.3 4677.3 5157.3 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文