2016-05-24 13 views
0

XSLTの値を増減するには、カウンタを使用します。 Apache Xalanを使用してこれを達成することができましたが、現在はSaxonを使用して同じことを達成したいと考えています。Saxonを使用して、XSLTのグローバル変数をインクリメントまたはデクリメント

Xalanのための私のXSLTスクリプトは次のようになります。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:lxslt="http://xml.apache.org/xslt" 
       xmlns:result="http://www.example.com/results" 
       extension-element-prefixes="result"> 

    <lxslt:component prefix="result" functions="incr dcr"> 
     <lxslt:script lang="javascript"> 
      var count = 0; 
      function incr() { 
       count++; 
       return count; 
      } 

      function dcr() { 
       count--; 
       return count; 
      } 
     </lxslt:script> 
    </lxslt:component> 

    <xsl:template match="/"> 
     a)<xsl:value-of select="result:incr()"/> 
     b)<xsl:value-of select="result:incr()"/> 
     c)<xsl:value-of select="result:dcr()"/> 
    </xsl:template> 

</xsl:stylesheet> 

期待出力は次のようになります。

a)1 
b)2 
c)1 

------------------------- my use case using saxon ------------------- 
This is my sample data.xml file. I want to transform this to html file. 

<entity> 
    <record>10</record> 
    <record>15</record> 
    <record>19</record> 
    <record>7</record> 
    <record>4</record> 
    <record>14</record> 
    <record>24</record> 
<entity> 

I want to implement a counter for line-number and want to increment the counter and print the line-number 
my expected outputs: 

case 1: If record values > 14, then my output should have line-number with value as. 
line-num value  
    1  15 
    2  19 
    3  24 

case 2 : If record values < 14, then my output should have line-number with value as. 
line-num value  
    1   10 
    2   7 
    3   4 

My other use case : 

<entity> 
    <record>10</record> 
    <record>15</record> 
    <record>19</record> 
    <record>7</record> 
    <record>20</record> 
    <record>14</record> 
    <record>24</record> 
    <entity> 
     <record>30</record> 
     <record>3</record> 
    </entity> 
</entity> 
<entity> 
    <record>5</record> 
    <record>17</record> 
    <record>19</record> 
    <record>6</record> 
    <record>70</record> 
    <record>9</record> 
    <record>35</record> 
    <entity> 
     <record>15</record> 
     <record>2</record> 
    </entity> 
</entity> 


This is my other use case, first <entity> record value > 15 and in second <entity> record value < 10, and my <entity> can grow bigger where i have to show only some record based on condition. 

line-num value 
    1  19 
    2  20 
    3  24 
    4  30 
    5  5 
    6  6 
    7  2 

答えて

1

私の知る限りではサクソンにJavascriptを使用する方法はありません。

あなたはサクソン9(EEまたはPE)で割り当て可能と変更変数を使用したい場合、あなたは

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:saxon="http://saxon.sf.net/" 
    xmlns:mf="http://example.com/mf" 
    extension-element-prefixes="saxon" 
    exclude-result-prefixes="xs saxon mf" 
    version="2.0"> 

    <xsl:variable name="counter" as="xs:integer" select="0" saxon:assignable="yes"/> 

    <xsl:function name="mf:incr" as="xs:integer"> 
     <saxon:assign name="counter" select="$counter + 1"/> 
     <xsl:sequence select="$counter"/> 
    </xsl:function> 

    <xsl:function name="mf:decr" as="xs:integer"> 
     <saxon:assign name="counter" select="$counter - 1"/> 
     <xsl:sequence select="$counter"/> 
    </xsl:function> 

    <xsl:template match="/" name="main"> 
     a)<xsl:value-of select="mf:incr()"/> 
     b)<xsl:value-of select="mf:incr()"/> 
     c)<xsl:value-of select="mf:decr()"/> 
    </xsl:template> 

</xsl:stylesheet> 

を使用することができますが、副作用を導入しようとする試みにしかしhttp://saxonica.com/html/documentation/extensions/instructions/assign.htmlでの警告や注意事項を参照してください。質問を編集してXML入力と目的の出力を説明し、そのようなカウンタ変数が必要だと思われる理由を考えてみましょう。割り当て可能な変数を使用する代わりに、純粋なXSLT 2.0ソリューションを表示できます。あなたの処理するための要件と番号特定の入力要素、スタイルシート

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:output indent="yes"/> 

    <xsl:template match="entity"> 
     <root> 
      <xsl:apply-templates select="record[. > 14]"/> 
      <xsl:apply-templates select="record[. &lt; 14]"/> 
     </root> 
    </xsl:template> 

    <xsl:template match="record"> 
     <xsl:copy> 
      <line-num> 
       <xsl:value-of select="position()"/> 
      </line-num> 
      <value> 
       <xsl:value-of select="."/> 
      </value> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

として

<entity> 
    <record>10</record> 
    <record>15</record> 
    <record>19</record> 
    <record>7</record> 
    <record>4</record> 
    <record>14</record> 
    <record>24</record> 
</entity> 

出力

<root> 
    <record> 
     <line-num>1</line-num> 
     <value>15</value> 
    </record> 
    <record> 
     <line-num>2</line-num> 
     <value>19</value> 
    </record> 
    <record> 
     <line-num>3</line-num> 
     <value>24</value> 
    </record> 
    <record> 
     <line-num>1</line-num> 
     <value>10</value> 
    </record> 
    <record> 
     <line-num>2</line-num> 
     <value>7</value> 
    </record> 
    <record> 
     <line-num>3</line-num> 
     <value>4</value> 
    </record> 
</root> 

他のオプションは、例えば使用された入力に対して実行xsl:number count="entity[. &lt; 14]"

最新の要件については、処理したい要素を選択する限り、それでもposition()を使用して処理できると思います。サクソン拡張命令を使用して(サクソン9のようなXSLT 2.0プロセッサーで)入力に

<root> 
    <entity> 
     <record>10</record> 
     <record>15</record> 
     <record>19</record> 
     <record>7</record> 
     <record>20</record> 
     <record>14</record> 
     <record>24</record> 
     <entity> 
      <record>30</record> 
      <record>3</record> 
     </entity> 
    </entity> 
    <entity> 
     <record>5</record> 
     <record>17</record> 
     <record>19</record> 
     <record>6</record> 
     <record>70</record> 
     <record>9</record> 
     <record>35</record> 
     <entity> 
      <record>15</record> 
      <record>2</record> 
     </entity> 
    </entity> 
</root> 

出力を適用するスタイルシート

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

    <xsl:output method="text"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="/root/entity[1]//record[. > 15], /root/entity[2]//record[. &lt; 10]"/> 
    </xsl:template> 

    <xsl:template match="record"> 
     <xsl:value-of select="concat(position(), ' ', ., '&#10;')"/> 
    </xsl:template> 

</xsl:stylesheet> 

ジャバスクリプトなし

1 19 
2 20 
3 24 
4 30 
5 5 
6 6 
7 9 
8 2 
+0

ありがとうございました。 –

+0

私は昨日サクソンの文書を読み、それを理解してサンプルを試しました。 –

+0

"割り当て可能な変数を使用するのではなく、純粋なXSLT 2.0のソリューションを表示できることを願っています。"、カウンタを制御して、整数値のインクリメント/デクリメントを行いたい。 –

0

、。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:saxon="http://saxon.sf.net/" 
       extension-element-prefixes="saxon" 
       exclude-result-prefixes="saxon"> 
    <xsl:variable name="i" select="0" saxon:assignable="yes"/> 
    <xsl:template match="/"> 
     a) <xsl:value-of select="$i"/> 
      <saxon:assign name="i" select="$i+1"/> 
     b) <xsl:value-of select="$i"/> 
      <saxon:assign name="i" select="$i+2"/> 
     c) <xsl:value-of select="$i"/> 
      <saxon:assign name="i" select="$i+3"/> 
     d) <xsl:value-of select="$i"/> 
    </xsl:template> 
</xsl:stylesheet> 
+0

リンク:http://www.saxonica.com/documentation9.5/extensions/instructions/assign.html –

1

(問題の拡大説明への対応)

理解する重要なことは、この問題はドキュメント順に、record要素の一連の処理を必要とすることです。これは、xsl:for-eachまたはxsl:apply-templatesを使用してプロセッサに依存しない方法では達成できないことを意味します。これは、一度に1つずつ要素を順番に処理することは保証されていない(Saxonの最近のバージョン、 multi-threadingを使用して要素を並列に処理し、仕様で許可されていれば、グローバル変数を無効に更新しようとします)。

要素を順番に処理する古典的な方法は、head-tail再帰を使用することです。record要素のシーケンスをパラメータとして、現在の行番号を第2のパラメータとしてとるテンプレートまたは関数を記述します。レコードのリストが空でない場合は、(a)リスト内の最初のrecordを処理し、(b)リストの残りの部分を処理するために再帰的に呼び出して、行番号の新しい値を渡します。

初めてこの方法でコードを書くのはちょっと心苦しいかもしれませんが、すぐに自然になります。

XSLT 3.0には、従来のループのような新しい構造のxsl:iterateがあります。xsl:iterateボディを入力すると、そのパラメータの初期値が渡され、ループの次の繰り返しが繰り返されるたびにパラメータの新しい値を設定することができます。

+0

私はレコード要素がchildren.pleasであることができる別のユースケースを持っていました。これについてのあなたの考えを提供してください。私の質問の「私の他のユースケース:」セクションで利用できます。 –

+0

申し訳ありませんが、人が質問に新しい補足物を追加し続けているとき、SOはうまくいくとは思いません。それは後で誰かがスレッドに従うことを非常に困難にし、他の人が何が変わったのかを見ることは困難です。新しい質問をして、オリジナルを参照してください。 –

関連する問題