2016-07-08 6 views
2

私はこのようなソートsophiscatedを持っている::実行-ソート

 <xsl:perform-sort select="$nodes"> 
     <xsl:sort select="if (p:isPreform(.) and not(p:getPreformPart(., $nodes))) then 1 else 0"/> 
     <xsl:sort select="p:getTargetPart(., $nodes)/../@pos"/> 
     <xsl:sort select="if (sort:isGroupElement(p:getTargetPart(., $nodes), $subsectionId)) then 
           sort:getGroupId(p:getTargetPart(., $nodes), $subsectionId) 
          else 
           p:getTargetPart(., $nodes)/@name"/> 
     <xsl:sort select="if (sort:isGroupElement(p:getTargetPart(., $nodes), $subsectionId)) then 0 else 1"/> 
     <xsl:sort select="replace(p:getTargetPart(., $nodes)/@number, '[А-Я]+$','')"/> 
     <xsl:sort select="if (p:isPreform(.)) then 1 else 0"/> 
     <xsl:sort select="@number"/> 
    </xsl:perform-sort> 

あなたが内部の繰り返し構造を見ることができます。どのように私はこれをリファクタリングすることができますか?仕様それが事実であれば内部変数を宣言することはできませ - 同じフラグメントは、次のようになります。たぶん私は何かを逃し

 <xsl:perform-sort select="$nodes"> 
     <xsl:variable name="isPreform" select="p:isPreform(.)" as="xs:boolean"/> 
     <xsl:variable name="target" select="p:getTargetPart(., $nodes)" as="element()"/> 
     <xsl:variable name="isGrouped" select="sort:isGroupElement($target, $subsectionId)" as="xs:boolean"/> 

     <xsl:sort select="if ($isPreform and not(p:getPreformPart(., $nodes))) then 1 else 0"/> 
     <xsl:sort select="$target/../@pos"/> 
     <xsl:sort select="if ($isGrouped) then sort:getGroupId($target, $subsectionId) else $target/@name"/> 
     <xsl:sort select="if ($isGrouped) then 0 else 1"/> 
     <xsl:sort select="replace($target/@number, '[А-Я]+$','')"/> 
     <xsl:sort select="if ($isPreform) then 1 else 0"/> 
     <xsl:sort select="@number"/> 
    </xsl:perform-sort> 

?私は別の方法でこれを並べ替えることができますか?

事前に感謝!アンドレイ。

+0

私は変数の問題に対する解決策はありませんが、ブール条件に基づいてソートするようなところでは、 '1' /' 0'として計算されたソートキーがあります。ブール値が完璧にソート可能なので、これらの式を短縮することができます。https://www.w3.org/TR/xquery-operators/#op.booleanしたがって、($ isGroupedの場合) 'select =" then 0 else 1 "' 'select =" not($ isGrouped)) "と書かれ、他の式も同様です。 –

+0

ヒントありがとうございます。私は、一時的な構造を作成し、各ノードのための計算された一意のidとfor-each内の属性を保存し、perform-sort内でこの属性を取得してソートを行います。 –

答えて

1

おそらく私は明白ですが、<xsl:perform-sort>の中に変数を追加して妥協を模索するのではなく、次のようにすると読みやすくなります。 XSLT 2.0の作成者がこれを許可していなかった理由の1つは、おそらく複雑さを抑えることでした。したがって、<xsl:apply-templates>の本体の内部では許可されていないのと同じように、シーケンスコンストラクタは<xsl:perform-sort>の本体として許可されませんでした。

私が使用(および使用するすべての人を励ます)のようなものを考え、この

ここ
<xsl:perform-sort select="$nodes"> 
     <xsl:sort select="f:key1(., $nodes)"/> 
     <xsl:sort select="f:key2(., $nodes)"/> 
     <xsl:sort select="f:key3(., $nodes, $subsectionId)"/> 
     <xsl:sort select="f:key4(., $nodes, $subsectionId)""/> 
     <xsl:sort select="f:key5(., $nodes))"/> 
     <xsl:sort select="f:key6(.)"/> 
     <xsl:sort select="@number"/> 
    </xsl:perform-sort> 

私はそれが自然に理解できるだろうというような機能f:keyN()ために意味のある名前を持っているだろうかソートするためのルールあります。

繰り返し式は、別の関数によって実装される候補であり、必要に応じて他の関数によって呼び出されます。したがって、冗長性は避けることができ、回避されます。これは、抽象化と呼ばれる主要なプログラミング原則です。

+1

XSLT 3.0のxsl:sortの前にxsl:variableを許可して、少し時間を費やしましたが、驚くほど複雑になりました(入力シーケンスの各項目に対して変数を計算する必要があります:元の値を保持すべきかどうか?)私たちは、メモ機能を使用して要件を満たすことができると判断しました。 –

+0

@MichaelKay:まったく!実装されていれば、これはXSLTの中で最も醜い機能でした。 –

関連する問題