2012-04-27 6 views
6

私が変数を持っているとします。$a$b$c$dがあります。私は最小(最大)の値を取得したいと思います。これに対する私の典型的なXSLT 1.0のアプローチは、私のXSLT 1.0プロセッサ、しかし 変数から一番小さい値を選択する方法は?

<xsl:variable name="minimum"> 
    <xsl:for-each select="$a | $b | $c | $d"> 
    <xsl:sort 
     select="." 
     data-type="number" 
     order="ascending" /> 
    <xsl:if test="position()=1"><xsl:value-of select="." /></xsl:if> 
    </xsl:for-each> 
</xsl:variable> 

である私は与えられた値の最小値(最大値)を計算することができますどのように

runtime error: file stylesheet.xslt line 106 element for-each
The 'select' expression does not evaluate to a node set.

と不平を言いますか?もちろん


、私は<xsl:when>文の長いシリーズを使用して、すべての組み合わせをチェックし、私はむしろ小さいソリューションが欲しいことができます。

+0

主な問題は、私が思うに、数字がノードではないということです。 – cHao

+0

私は主な問題は、XSLT 1.0では、 'select'の式がノード集合に評価されなければならないということです。 (http://www.w3.org/TR/xslt#for-each) –

答えて

5

変数は静的に次のようなものは、XSLT 1.0で行うことができ、その後、値(動的に計算されていない)を定義している場合:(この変換は、任意のXML文書に適用されると

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:variable name="vA" select="3"/> 
<xsl:variable name="vB" select="1"/> 
<xsl:variable name="vC" select="9"/> 
<xsl:variable name="vD" select="5"/> 

<xsl:template match="/"> 
    <xsl:for-each select= 
     "document('')/*/xsl:variable 
     [contains('|vA|vB|vC|vD|', concat('|', @name, '|'))] 
      /@select 
     "> 
     <xsl:sort data-type="number" order="ascending"/> 

     <xsl:if test="position() = 1"> 
     Smallest: <xsl:value-of select="."/> 
     </xsl:if> 
     <xsl:if test="position() = last()"> 
     Largest: <xsl:value-of select="."/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

ありません)を使用し、望んでいた、正しい結果が製造される:

Smallest: 1 
    Largest: 9 

II。さて、変数が動的に定義されているとします。。この変換は、以下のXML文書に適用される場合

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common"> 
<xsl:output method="text"/> 

<xsl:variable name="vA" select="number(/*/*[3])"/> 
<xsl:variable name="vB" select="number(/*/*[1])"/> 
<xsl:variable name="vC" select="number(/*/*[9])"/> 
<xsl:variable name="vD" select="number(/*/*[5])"/> 

<xsl:template match="/"> 
    <xsl:variable name="vrtfStore"> 
     <num><xsl:value-of select="$vA"/></num> 
     <num><xsl:value-of select="$vB"/></num> 
     <num><xsl:value-of select="$vC"/></num> 
     <num><xsl:value-of select="$vD"/></num> 
    </xsl:variable> 

    <xsl:for-each select="ext:node-set($vrtfStore)/*"> 
     <xsl:sort data-type="number" order="ascending"/> 

     <xsl:if test="position() = 1"> 
     Smallest: <xsl:value-of select="."/> 
     </xsl:if> 
     <xsl:if test="position() = last()"> 
     Largest: <xsl:value-of select="."/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

私たちは、この(しかしxxx:node-set()拡張機能を必要とする)のような何かを行うことができます

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

正しい結果が生成されます。

Smallest: 1 
    Largest: 9 
+0

文書( '')はXSLT XML自体を指していますか?それを再解析する必要がありますか?私は学習者のもう一つのすばらしいトリック、ありがとう。 +1 –

+0

@PavelVeller:これはXSLTスタイルシート自体にインラインデータを持ち、別のファイルではない場合によく使用されます。はい、再解析は実行時に行われ、これはあまり効率的ではありません。ソリューションの第2の部分もご覧になることをお勧めします。 –

+0

2番目の部分はトリック、ありがとう。私の変数は、入力ツリー上でより複雑な式の最小値なので、確かに静的ではありません。 – bitmask

1

私は(私は2.0を使用)1.0でこれをしなければならなかったことがありませんが、あなたはこれを行うことができます:

<xsl:variable name="minimum"> 
    <xsl:choose> 
     <xsl:when test="$b > $a and $c > $a and $d > $a"><xsl:value-of select="$a"/></xsl:when> 
     <xsl:when test="$a > $b and $c > $b and $d > $b"><xsl:value-of select="$b"/></xsl:when> 
     <xsl:when test="$b > $c and $a > $c and $d > $c"><xsl:value-of select="$c"/></xsl:when> 
     <xsl:when test="$b > $d and $c > $d and $a > $d"><xsl:value-of select="$d"/></xsl:when> 
    </xsl:choose> 
    </xsl:variable> 

は、しかし、より良い方法があるはずはずです。

+0

私の考えは正確です。私が言ったように、私はすでにこれを緊急時計画として持っています。しかしそれはいいものではないし、確かに拡大もしない。 – bitmask

+0

@bitmask - あなたはあなたがこれを行うことができると言ったあなたの質問の最後の段落を完全に逃しました。うまくいけば誰か(おそらく@DimitreNovatchev)ははるかに良い解決策を持つでしょう。 –

3

このXSLT 1.0ソリューションは、再帰的テンプレートを使用して区切られた値リストを解析し、リストから最小値/最大値を返します。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:variable name="a" select="'3'"/> 
    <xsl:variable name="b" select="'1'"/> 
    <xsl:variable name="c" select="'9'"/> 
    <xsl:variable name="d" select="'5'"/> 

    <xsl:template match="/"> 
     <xsl:text>&#xa;Smallest: </xsl:text> 
     <xsl:call-template name="min"> 
      <xsl:with-param name="values" select="concat($a,',',$b,',',$c,',',$d)"/>  
     </xsl:call-template> 

     <xsl:text>&#xa;Largest: </xsl:text> 
     <xsl:call-template name="max"> 
      <xsl:with-param name="values" select="concat($a,',',$b,',',$c,',',$d)"/>  
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="min"> 
     <xsl:param name="values" /> 
     <xsl:param name="delimiter" select="','"/> 
     <xsl:param name="min"/> 

     <xsl:variable name="currentValue" > 
      <xsl:choose> 
       <xsl:when test="contains($values, $delimiter)"> 
        <xsl:value-of select="substring-before($values,$delimiter)"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$values"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:variable name="minimumValue"> 
      <xsl:choose> 
       <xsl:when test="$min and $min > $currentValue"> 
        <xsl:value-of select="$currentValue"/> 
       </xsl:when> 
       <xsl:when test="$min"> 
        <xsl:value-of select="$min"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$currentValue" /> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:choose> 
      <xsl:when test="substring-after($values,$delimiter)"> 
       <xsl:call-template name="min"> 
        <xsl:with-param name="min" select="$minimumValue" /> 
        <xsl:with-param name="values" select="substring-after($values,$delimiter)" /> 
        <xsl:with-param name="delimiter" select="$delimiter"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$minimumValue" /> 
      </xsl:otherwise> 
     </xsl:choose>     
    </xsl:template> 


    <xsl:template name="max"> 
     <xsl:param name="values" /> 
     <xsl:param name="delimiter" select="','"/> 
     <xsl:param name="max"/> 

     <xsl:variable name="currentValue" > 
      <xsl:choose> 
       <xsl:when test="contains($values, $delimiter)"> 
        <xsl:value-of select="substring-before($values,$delimiter)"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$values"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:variable name="maximumValue"> 
      <xsl:choose> 
       <xsl:when test="$max and $currentValue > $max"> 
        <xsl:value-of select="$currentValue"/> 
       </xsl:when> 
       <xsl:when test="$max"> 
        <xsl:value-of select="$max"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$currentValue" /> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 

     <xsl:choose> 
      <xsl:when test="substring-after($values,$delimiter)"> 
       <xsl:call-template name="max"> 
        <xsl:with-param name="max" select="$maximumValue" /> 
        <xsl:with-param name="values" select="substring-after($values,$delimiter)" /> 
        <xsl:with-param name="delimiter" select="$delimiter"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$maximumValue" /> 
      </xsl:otherwise> 
     </xsl:choose>     
    </xsl:template> 
</xsl:stylesheet> 

実行、次の出力を生成します。

Smallest: 1 
Largest: 9 
関連する問題