1

XSLT1.0を使用しています

次のようなXMLドキュメントのどこにでもある可能性のある特定の「num」要素を持つxmlがあるとします:-

<elem1>
  <num>24</num>
</elem1>
<elem2>
  <description>
    <num>18</num>
  </description>
</elem2>
<elem3>
  <elem1>
    <num>36</num>
  </elem1>
</elem3>

に変換したい:-

<elem1>
  <gcd multiple="4">6</gcd>
</elem1>
<elem2>
  <description>
    <gcd multiple="3">6</gcd>
  </description>
</elem2>
<elem3>
  <elem1>
    <gcd multiple="6">6</gcd>
  </elem1>
</elem3>

これで、次のような2つの要素のgcdを計算できるテンプレートができました:-

<xsl:template name="gcd">
  <xsl:param name="x"/>
  <xsl:param name="y"/>
  <!-- snipping code to compute gcd that goes here -->
</xsl:template>

gcdのこのテンプレートを考えると、次のようにnum要素をループするようなことをしなければならないと思います:-

<xsl:variable name="global_gcd">
  <xsl:for-each select="//ns0:num">
    <!-- something probably goes here --> 
    <!-- say a temporary value x=0 initially -->
    <!-- and then x = gcd (x, value of current node) -->
  </xsl:for-each>
</xsl:variable>

そして、「num」のテンプレートでこの変数を使用して、属性とともに目的の「gcd」要素を生成できるとされています。それも私にできます。

上記のループはどのようになりますか?for-eachでない場合、2つの要素に対して有効なgcdテンプレートがすでにあると仮定して、XMLドキュメント内のすべての「num」要素のgcdを実際にどのように計算しますか?

すべての「num」要素を兄弟などとして持っていれば、これははるかに簡単だと思いますが、残念ながらそうではありません。これらのいずれか2つの間のツリー関係は、潜在的に任意である可能性があります。私が知っている唯一のことは、それらがすべて同じ名前を持っているということです。

4

1 に答える 1

3

XSLTは関数型言語であるため、更新可能な変数の概念はありません。変数は作成時に値が設定され、その値を後で変更することはできません。純粋なXSLTでこれを行う必要がある場合は、ループではなく再帰的なテンプレートとして問題を再定式化する必要があります

<xsl:template name="gcd">
  <xsl:param name="nodes" />
  <xsl:choose>
    <xsl:when test="count($nodes) = 0">0</xsl:when>
    <xsl:otherwise>
      <xsl:variable name="gcdOfRest">
        <xsl:call-template name="gcd">
          <xsl:with-param name="nodes" select="$nodes[position() > 1]" />
        </xsl:call-template>
      </xsl:variable>
      <!-- existing logic goes here, calculating GCD between number($nodes[1])
           and number($gcdOfRest) -->
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

このテンプレートを呼び出して、 param//ns0:numとして渡します。nodes

ただし、拡張関数を記述してプラグインするオプションがある場合は、それがより効率的かもしれません。

于 2012-09-25T16:36:10.110 に答える