3

我想在 xslt 文件中做一些计算,并且需要在公式中做一些平方根。有人可以指出是否可能以及如何请?

感谢磨坊

4

2 回答 2

2

可以使用FXSLsqrt的模板/功能

一、在 XSLT 1.0 中:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:import href="sqrt.xsl"/>

  <!-- To be applied on any source xml. 
       This also tests the within() function 
  -->

  <xsl:output indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="/">
     sqrt(0.25): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="0.25"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(1): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="1"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(2): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="2"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(9): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="9"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(16): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="16"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>
     sqrt(25): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="25"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>
     sqrt(36): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="36"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(49): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="49"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(64): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="64"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(81): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="81"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(100): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="100"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>

     sqrt(121): 
     <xsl:call-template name="sqrt">
        <xsl:with-param name="N" select="121"/>
        <xsl:with-param name="Eps" select="0.00001"/>
     </xsl:call-template>
  </xsl:template>

</xsl:stylesheet>

当将此转换应用于任何 XML 文档(未使用)时,将产生所需的正确结果

 sqrt(0.25): 
 0.5000000795866174

 sqrt(1): 
 1.0000000464611474

 sqrt(2): 
 1.4142156862745097

 sqrt(9): 
 3.0000000000393214

 sqrt(16): 
 4.0000001858445895
 sqrt(25): 
 5.000000000016778
 sqrt(36): 
 6.000000002793968

 sqrt(49): 
 7.000000094930961

 sqrt(64): 
 8.000001273385879

 sqrt(81): 
 9.000009415515176

 sqrt(100): 
 10.000000000107445

 sqrt(121): 
 11.000000001323027

二、将 FXSL 2.x 用于 XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:f="http://fxsl.sf.net/">
  <xsl:import href="../f/func-sqrt.xsl"/>
  <xsl:import href="../f/func-map.xsl"/>
  <xsl:import href="../f/func-standardXpathFunctions.xsl"/>
    <xsl:output method="text"/>

 <xsl:template match="/">
     <xsl:value-of  separator="&#xA;" select=
     "f:map(f:round-half-to-even(f:sqrt(2, 0.000001)),
            0 to 13
          )
   "/>
 </xsl:template>
</xsl:stylesheet>

当将此转换应用于任何 XML 文档(未使用)时,将产生所需的正确结果

1
1.4
1.41
1.414
1.4142
1.41421
1.414214
1.4142136
1.41421356
1.414213562
1.4142135624
1.41421356237
1.414213562375
1.4142135623747
于 2012-10-05T12:37:17.577 回答
2

如果您使用的是 XSLT 2.0,则问题已排序——请参阅 Dimitre 的回答。如果您使用的是 XSLT 1.0,实际上在生产环境中,我仍然会选择 Dimitre 的答案。在商业上,最好使用经过测试的库而不是重新发明轮子。

但是,我认为您的问题实施独立解决方案可能会很有趣。它是!

给定这一堆值来找到...的根源

<squares>
  <square>0</square>
  <square>0.25</square>
  <square>1</square>
  <square>9</square>
  <square>10</square>
</squares>

...当输入到此 XSLT 1.0 样式表时...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="verysmall" select="0.00001" />
<xsl:template match="/">
 <roots>
   <xsl:apply-templates select="*/square"/>
  </roots>
</xsl:template>

<xsl:template match="square">
  <root>
    <xsl:call-template name="root">
      <xsl:with-param name="x" select="." />
    </xsl:call-template>  
  </root>
</xsl:template>

<xsl:template name="root">
  <xsl:param name="x"/><!-- Assume x >= 0 -->
  <xsl:choose>
    <xsl:when test="$x > 1">
      <xsl:call-template name="iterate-root">
        <xsl:with-param name="x" select="$x" />
        <xsl:with-param name="H" select="$x" />
        <xsl:with-param name="L" select="0" />
      </xsl:call-template>  
    </xsl:when>  
    <xsl:when test="($x = 1) or ($x &lt;= 0)">
      <xsl:value-of select="$x" />
    </xsl:when>  
    <xsl:otherwise>
      <xsl:variable name="inv-root">
        <xsl:call-template name="iterate-root">
          <xsl:with-param name="x" select="1 div $x" />
          <xsl:with-param name="H" select="1 div $x" />
          <xsl:with-param name="L" select="0" />
        </xsl:call-template>
      </xsl:variable>
      <xsl:value-of select="1 div $inv-root" />
    </xsl:otherwise>  
  </xsl:choose>
</xsl:template>

<xsl:template name="iterate-root">
  <xsl:param name="x"/> <!-- Assume x > 1 -->
  <xsl:param name="H"/> <!-- High estimate -->
  <xsl:param name="L"/> <!-- Low estimate -->
  <xsl:variable name="M" select="($H + $L) div 2" />
  <xsl:variable name="g" select="($M * $M - $x) div $x" />
  <xsl:choose>
    <xsl:when test="(($g &lt; $verysmall) and ((- $g) &lt; $verysmall)) or
                    (($H - $L) &lt; $verysmall)">
      <xsl:value-of select="$M"/>
    </xsl:when>
    <xsl:when test="$g > 0">
      <xsl:call-template name="iterate-root">
        <xsl:with-param name="x" select="$x" />
        <xsl:with-param name="H" select="$M" />
        <xsl:with-param name="L" select="$L" />
      </xsl:call-template>  
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="iterate-root">
        <xsl:with-param name="x" select="$x" />
        <xsl:with-param name="H" select="$H" />
        <xsl:with-param name="L" select="$M" />
      </xsl:call-template>  
    </xsl:otherwise>
  </xsl:choose>  
</xsl:template>

</xsl:stylesheet>

...产生近似解...

<roots>
  <root>0</root>
  <root>0.5</root>
  <root>1</root>
  <root>2.999988555908203</root>
  <root>3.1622695922851562</root>
</roots>

笔记

该技术使用分而治之来找到方程 f(y) = y*y - x 的根,它出现在 x 的平方根处。该技术可能仅对实现优化的尾端递归的 XSLT 处理器相当有效。

于 2012-10-05T14:37:55.470 回答