3

xslt ファイル内で計算を行いたいのですが、数式で平方根を実行する必要があります。可能であれば誰かが指摘してもらえますか?

ミルに感謝

4

2 に答える 2

2

FXSLsqrtのテンプレート/関数を使用できます

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

Ⅱ.XSLT 2.0 に FXSL 2.x を使用する場合:

<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 に答える