Language detail: XSLT

Coverage: 23.31%
number of '+' ratings
contribution for coverage

Unsolved challenges

codes

Feed

Used modules

next >>

LL Golf Hole 6 - 10進数を2進数に基数変換する (Nested Flatten)
短くなった。卑怯くさいけど。

#7254のコードを利用してますが、
基数だけは弄れるようにしておきました。
1
2
3
4
<stylesheet version="2.0" xmlns="http://www.w3.org/1999/XSL/Transform">
  <import href="http://tinyurl.com/58455r"/>
  <variable name="b" select="2"/>
</stylesheet>
正攻法で。
冒頭の 変数b の値が基数で、2~10まで対応してます。

短くとか.. 勘弁してください
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<x:stylesheet version="2.0"
  xmlns:x="http://www.w3.org/1999/XSL/Transform"
  xmlns:s="http://www.w3.org/2001/XMLSchema"
  xmlns:f="http://www.w3.org/2005/xpath-functions"
  xmlns:y="uri:ja.doukaku.org:my-functions"
  >
  <x:variable name="b" as="s:integer" select="2"/>
  <x:output method="text"/>
  <x:template match="/">
    <x:for-each select="0 to 256">
      <x:value-of select="y:f(.)"/>
      <x:text>&#xA;</x:text>
    </x:for-each>
  </x:template>
  <x:function name="y:f" as="s:string">
    <x:param name="n" as="s:integer"/>
    <x:value-of select="if ($n=0) then '0' else f:string-join(f:reverse(y:g($n)),'')"/>
  </x:function>
  <x:function name="y:g" as="s:string*">
    <x:param name="n" as="s:integer"/>
    <x:if test="$n>0">
      <x:sequence select="s:string($n mod $b)"/>
      <x:sequence select="y:g($n idiv $b)"/>
    </x:if>
  </x:function>
</x:stylesheet>
LL Golf Hole 5 - 最上位の桁を数え上げる (Nested Flatten)
XPath の conditional expressions(if then else) など使ってみる。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  >

  <xsl:output method="text" />

  <xsl:variable name="goal" as="xs:string" select="'300'" />

  <xsl:template match="/" >
    <xsl:variable name="digit" as="xs:integer" select="fn:string-length($goal)" />
    <xsl:for-each select="1 to $digit">
      <xsl:variable name="d" as="xs:integer" select="." />
      <xsl:for-each select="(if (.=1) then 0 else 1)
                            to
                            (if (.=$digit) then xs:integer(fn:substring($goal,1,1)) else 9)" >
        <xsl:value-of select="." />
        <xsl:for-each select="2 to $d">
          <xsl:value-of select="0" />
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>
LL Golf Hole 1 - tinyurl.comを使ってURLを短縮する (Nested Flatten)
#6827 の前に考えてたものを出し忘れていました。
しかしやはりXSLTはGolfに向かない。
1
2
3
<html x:version="2.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
<x:value-of select="unparsed-text('http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo')"/>
</html>
LL Golf Hole 2 - 文字列に含まれる単語の最初の文字を大文字にする (Nested Flatten)
XSLTもGolfには向きませんね。
本当は改行も全部消したかったんですが、
表示がエライことになるので止めました。
入力は↓のコード自身です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<x:transform version="2.0"
xmlns:x="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:f="http://www.w3.org/2005/xpath-functions">
<x:variable name="ll2008" as="s:string">LL future</x:variable>
<x:variable name="ll2005" as="s:string">LL day and night</x:variable>
<x:output method="text"/>
<x:template match="/">
<x:apply-templates select="/x:transform/x:variable"/>
</x:template>
<x:template match="x:variable">
<x:variable name="tokens" as="s:string*">
<x:for-each select="f:tokenize(./text(),' ')">
<x:sequence select="f:concat(f:upper-case(f:substring(.,1,1)),f:substring(.,2,f:string-length(.)-1))"/>
</x:for-each>
</x:variable>
<x:value-of select="f:concat(@name,'=')"/>
<x:value-of select="string-join($tokens,' ')"/>
<x:text>&#xA;</x:text>
</x:template>
</x:transform>
設定ファイルから値を取得 (Nested Flatten)
こーゆーのが、XSLTの本来の使い方かと。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  >

  <!-- 以下のようなxml文書を渡します
  <item name="りんご" cost="200" />
  -->

  <xsl:output method="text" encoding="sjis" />

  <xsl:template match="/item" >
    <xsl:call-template name="showPrice" />
  </xsl:template>

  <xsl:template name="showPrice">
    <xsl:text>「</xsl:text>
    <xsl:value-of select="@name" />
    <xsl:text>」は</xsl:text>
    <xsl:value-of select="floor(@cost * 1.05)" />
    <xsl:text>円(税込み)です。&#xA;</xsl:text>
  </xsl:template>

</xsl:stylesheet>
/*コメント*/を取り除く (Nested Flatten)
XSLT 2.0 ならregexが使えるので、
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="my"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:value-of select="my:remove_comment('AAA')" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="my:remove_comment('AAA/*BBB*/')" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="my:remove_comment('AAA/*BBB')" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="my:remove_comment('AAA/*BBB*/CCC')" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="my:remove_comment('AAA/*BBB/*CCC*/DDD*/EEE')" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="my:remove_comment('AAA/a//*BB*B**/CCC')" />
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>

  <xsl:function name="my:remove_comment" as="xs:string">
    <xsl:param name="str" as="xs:string" />

    <xsl:value-of
      select="fn:replace($str, '/\*.*?(\*/|$)', '')" />
  </xsl:function>

</xsl:stylesheet>
アルファベットの繰り上がり (Nested Flatten)
indexが1始まりだと混乱する...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="my"
  >

  <xsl:output method="text" />

  <xsl:variable name="convert_table" as="xs:string+">
    <xsl:for-each select="1 to 26">
      <xsl:sequence
        select="fn:codepoints-to-string(
        (fn:string-to-codepoints('A')[1] + . - 1)
        )" />
    </xsl:for-each>
  </xsl:variable>
  <xsl:variable name="table_size" as="xs:integer"
    select="fn:count($convert_table)" />

  <xsl:template match="/" >
    <xsl:variable name="seq" as="xs:string*">
      <xsl:for-each select="1 to 100">
        <xsl:sequence select="my:alphabeticalize(.)" />
      </xsl:for-each>
    </xsl:variable>

    <xsl:value-of select="fn:string-join($seq, ', ')" />
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>

  <xsl:function name="my:alphabeticalize" as="xs:string">
    <xsl:param name="n" as="xs:integer" />

    <xsl:variable name="i" as="xs:integer" select="$n - 1" />

    <xsl:variable name="n_" as="xs:string"
      select="$convert_table[($i mod $table_size) + 1]" />

    <xsl:choose>
      <xsl:when test="$i idiv $table_size = 0">
        <xsl:value-of select="$n_" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of
          select="fn:concat(
          my:alphabeticalize($i idiv $table_size),
          $n_)" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>
</xsl:stylesheet>
与えられた数字のケタ数 (Nested Flatten)
負数にも対応させてみました。

出力結果:
2469 は 4 桁で、最大桁は 1000 の位です。
600 は 3 桁で、最大桁は 100 の位です。
1 は 1 桁で、最大桁は 1 の位です。
-65536 は 5 桁で、最大桁は -10000 の位です。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  >

  <xsl:output method="text" encoding="sjis" />

  <xsl:template match="/" >
    <xsl:call-template name="digit">
      <xsl:with-param name="n" select="2469" />
    </xsl:call-template>
    <xsl:call-template name="digit">
      <xsl:with-param name="n" select="600" />
    </xsl:call-template>
    <xsl:call-template name="digit">
      <xsl:with-param name="n" select="1" />
    </xsl:call-template>
    <xsl:call-template name="digit">
      <xsl:with-param name="n" select="-65536" />
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="digit">
    <xsl:param name="n" as="xs:integer" />

    <xsl:variable name="is_negative" as="xs:boolean"
      select="$n&lt;0" />

    <xsl:variable name="n_" as="xs:string">
      <xsl:choose>
        <xsl:when test="$is_negative">
          <xsl:value-of select="xs:string(-1 * $n)" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="xs:string($n)" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:value-of select="$n" />
    <xsl:text> は </xsl:text>
    <xsl:value-of select="string-length($n_)" />
    <xsl:text> 桁で、最大桁は </xsl:text>
    <xsl:if test="$is_negative">
      <xsl:text>-</xsl:text>
    </xsl:if>
    <xsl:text>1</xsl:text>
    <xsl:for-each select="1 to string-length($n_)-1">
      <xsl:text>0</xsl:text>
    </xsl:for-each>
    <xsl:text> の位です。&#xA;</xsl:text>
  </xsl:template>

</xsl:stylesheet>
年間カレンダー (Nested Flatten)
出力はシンプルなHTMLのtableで。
しかし、曜日を取得する関数を自作しなきゃいかんとわ...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="xs fn my"
  >

  <xsl:param name="n" as="xs:integer" >2008</xsl:param>

  <xsl:output method="html" />

  <xsl:template match="/" >
    <html>
      <head>
        <title><xsl:value-of select="$n" />年の年間カレンダー</title>
      </head>
      <body>
        <h1><xsl:value-of select="$n" />年の年間カレンダー</h1>
        <xsl:for-each select="1 to 12">
          <hr />
          <h2><xsl:value-of select="." />月</h2>
          <xsl:call-template name="mcalender">
            <xsl:with-param name="year" select="$n" />
            <xsl:with-param name="month" select="." />
          </xsl:call-template>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>

  <xsl:template name="mcalender">
    <xsl:param name="year" as="xs:integer" />
    <xsl:param name="month" as="xs:integer" />

    <!-- 今月1日 -->
    <xsl:variable name="first-date" as="xs:date"
      select="xs:date(
        fn:string-join(
          (my:pad($year,4),my:pad($month,2),'01'),
          '-'))" />
    <!-- 次月1日 -->
    <xsl:variable name="next-first-date" as="xs:date">
      <xsl:choose>
        <xsl:when test="$month=12">
          <xsl:value-of
            select="xs:date(
              fn:string-join(
                (my:pad($year+1,4),'01','01'),
                '-'))" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of
            select="xs:date(
              fn:string-join(
                (my:pad($year,4),my:pad($month+1,2),'01'),
                '-'))" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <!-- 今月の日数を求める -->
    <xsl:variable name="days" as="xs:integer"
      select="fn:days-from-duration($next-first-date - $first-date)" />

    <!-- 今月1日 の曜日を求める -->
    <xsl:variable name="start-day" as="xs:integer"
      select="my:get-day($first-date)" />

    <!-- カレンダーの左上の開始日 -->
    <xsl:variable name="rstart" as="xs:integer"
      select="1 - $start-day" />
    <!-- カレンダーの右下の終了日 -->
    <xsl:variable name="rend" as="xs:integer">
      <xsl:choose>
        <xsl:when test="(($days - $rstart + 1) mod 7)=0">
          <xsl:value-of select="$days - $rstart + 1" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="((($days - $rstart+1) idiv 7)+1)*7" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <table border="1">
      <xsl:call-template name="calender-header" />
      <xsl:for-each select="1 to $rend idiv 7">
        <tr>
          <xsl:for-each select="$rstart+((.-1)*7) to $rstart+(.*7)-1">
            <td>
              <xsl:choose>
                <xsl:when test="1 &lt;= . and . &lt;= $days">
                  <xsl:value-of select="." />
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text>&#160;</xsl:text>
                </xsl:otherwise>
              </xsl:choose>
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>

  <xsl:template name="calender-header">
    <tr>
      <xsl:for-each select="('日','月','火','水','木','金','土')">
        <th><xsl:value-of select="." /></th>
      </xsl:for-each>
    </tr>
  </xsl:template>

  <!-- 曜日を取得する -->
  <xsl:function name="my:get-day" as="xs:integer">
    <xsl:param name="date" as="xs:date" />
    <xsl:variable name="epoch" as="xs:date"
      select="xs:date('1970-01-01')" />

    <xsl:variable name="day" as="xs:integer"
      select="(fn:days-from-duration($date - $epoch) + 4) mod 7" />
    <xsl:choose>
      <xsl:when test="$day &lt; 0">
        <xsl:value-of select="$day + 7" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$day" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>

  <xsl:function name="my:pad" as="xs:string">
    <xsl:param name="i" as="xs:integer" />
    <xsl:param name="digit" as="xs:integer" />

    <xsl:variable name="seq" as="xs:string*">
      <xsl:for-each
        select="1 to $digit - fn:string-length(xs:string($i))">
        <xsl:sequence select="'0'" />
      </xsl:for-each>
      <xsl:sequence select="xs:string($i)" />
    </xsl:variable>

    <xsl:value-of select="fn:string-join($seq, '')" />
  </xsl:function>
</xsl:stylesheet>
与えられた文字列でピラミッド (Nested Flatten)
対象文字列はテンプレートパラメタ txt で渡してください。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  >

  <xsl:param name="txt" as="xs:string" />

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:variable name="chars" as="xs:string*">
      <xsl:for-each select="fn:string-to-codepoints($txt)">
        <xsl:sequence select="fn:codepoints-to-string((.))" />
      </xsl:for-each>
    </xsl:variable>

    <xsl:for-each select="1 to fn:count($chars)">
      <xsl:variable name="wscount" as="xs:integer"
        select="fn:count($chars)-." />
      <xsl:for-each select="1 to $wscount" >
        <xsl:text> </xsl:text>
      </xsl:for-each>
      <xsl:value-of select="fn:subsequence($chars, $wscount+1)" />
      <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
ダブル完全数 (Nested Flatten)
べたに計算してます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="my"
  >

  <xsl:output method="text" encoding="sjis" />

  <xsl:template match="/" >
    <xsl:for-each select="1 to 10000">
      <xsl:if test="fn:sum(my:get-divisors(.))=.*2">
        <xsl:value-of select="." />
        <xsl:text> はダブル完全数&#xA;</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <xsl:function name="my:get-divisors" as="xs:integer*">
    <xsl:param name="n" as="xs:integer" />

    <xsl:if test="$n&gt;1">
      <xsl:for-each select="1 to $n idiv 2">
        <xsl:if test="($n mod .)=0">
          <xsl:sequence select="." />
        </xsl:if>
      </xsl:for-each>
    </xsl:if>
  </xsl:function>

</xsl:stylesheet>
HTTPでGET (Nested Flatten)
unparsed-text() を使って。
よっぽどひねくれた実装でもない限り
GETでとってくると思います。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:value-of select="unparsed-text('http://ja.doukaku.org/feeds/comments/')" />
  </xsl:template>

</xsl:stylesheet>
リストを逆順に表示 (Nested Flatten)

XPath Functions の reverse で逆順になります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:variable name="seq" as="xs:integer*" select="(1,2,3,4,5)" />
    <xsl:for-each select="fn:reverse($seq)" >
      <xsl:value-of select="." />
      <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
隣り合う二項の差 (Nested Flatten)
ふつーに。
与えるsequenceの要素が2個未満の場合は
エラーにしちゃってます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="my"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:value-of select="my:diff((3,1,4,1,5,9,2,6,5))" />
  </xsl:template>

  <xsl:function name="my:diff" as="xs:integer*">
    <xsl:param name="seq" as="xs:integer*" />

    <xsl:if test="fn:count($seq)&lt;2">
      <xsl:message terminate="yes">
        sequence must have 2 or more elements
      </xsl:message>
    </xsl:if>

    <xsl:for-each select="2 to fn:count($seq)">
      <xsl:variable name="idx" as="xs:integer" select="." />
      <xsl:sequence select="$seq[$idx] - $seq[$idx - 1]" />
    </xsl:for-each>
  </xsl:function>
</xsl:stylesheet>
正整数のゲーデル数化? (Nested Flatten)
累乗は標準では定義されないので、自作しました。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="my"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:text>geodel(9)=</xsl:text>
    <xsl:value-of select="my:goedel(9)" />
    <xsl:text>&#xA;goedel(81)=</xsl:text>
    <xsl:value-of select="my:goedel(81)" />
    <xsl:text>&#xA;goedel(230)=</xsl:text>
    <xsl:value-of select="my:goedel(230)" />
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>

  <xsl:function name="my:goedel" as="xs:integer">
    <xsl:param name="n" as="xs:integer" />
    <xsl:if test="n&lt;=0">
      <xsl:message terminate="yes">
        n must be positive integer
      </xsl:message>
    </xsl:if>

    <xsl:variable name="n_" as="xs:string" select="xs:string($n)" />
    <xsl:variable name="primes" as="xs:integer*"
      select="my:primes(fn:string-length($n_))" />

    <xsl:variable name="elem" as="xs:integer*">
      <xsl:for-each select="fn:string-to-codepoints($n_)">
        <xsl:variable name="i" as="xs:integer"
          select="xs:integer(fn:codepoints-to-string((.)))" />
        <xsl:variable name="idx" as="xs:integer"
          select="position()" />
        <xsl:sequence select="my:power($primes[$idx],$i)" />
      </xsl:for-each>
    </xsl:variable>

    <xsl:value-of select="my:PI($elem)" />
  </xsl:function>

  <xsl:function name="my:power" as="xs:integer">
    <xsl:param name="n" as="xs:integer" />
    <xsl:param name="m" as="xs:integer" />

    <xsl:choose>
      <xsl:when test="$m=0">
        <xsl:value-of select="1" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$n*my:power($n,$m - 1)" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>

  <xsl:function name="my:primes" as="xs:integer*">
    <xsl:param name="n" as="xs:integer" />

    <xsl:sequence select="my:primes_($n,2,())" />
  </xsl:function>

  <xsl:function name="my:primes_" as="xs:integer*">
    <xsl:param name="n" as="xs:integer" />
    <xsl:param name="m" as="xs:integer" />
    <xsl:param name="r" as="xs:integer*" />

    <xsl:choose>
      <xsl:when test="$n=0">
        <xsl:sequence select="$r" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="is_prime" as="xs:boolean"
          select="fn:empty($r[($m mod .)=0])" />
        <xsl:choose>
          <xsl:when test="$is_prime">
            <xsl:variable name="r_" as="xs:integer*">
              <xsl:sequence select="$r" />
              <xsl:sequence select="$m" />
            </xsl:variable>
            <xsl:sequence select="my:primes_($n - 1,$m + 1, $r_)" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:sequence select="my:primes_($n,$m + 1, $r)" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>

  <xsl:function name="my:PI" as="xs:integer">
    <xsl:param name="seq" as="xs:integer*" />

    <xsl:choose>
      <xsl:when test="fn:empty($seq)" >
        <xsl:value-of select="0" />
      </xsl:when>
      <xsl:when test="fn:count($seq)=1">
        <xsl:value-of select="$seq[1]" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$seq[1] * my:PI(fn:subsequence($seq,2))" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>
</xsl:stylesheet>
重複する要素を取り除く (Nested Flatten)
selector ([]) が sequenceに対しても使えるので楽ですね。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:variable name="seq" as="xs:integer*"
      select="(3,1,4,1,5,9,2,6,5)" />
    <xsl:value-of
      select="$seq[fn:count(fn:index-of($seq,.))=1]" />
  </xsl:template>
</xsl:stylesheet>
文字列の反転 (Nested Flatten)
sjisっていっても多分内部ではutf-8で処理するんでしょうけど...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="sjis"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="my"
  >

  <xsl:output method="text" encoding="sjis" />

  <xsl:template match="/" >
    <xsl:value-of select="my:reverse_string('Hello')" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="my:reverse_string('こんにちは')" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:value-of select="my:reverse_string('濁点(だくてん)')" />
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>

  <xsl:function name="my:reverse_string" as="xs:string">
    <xsl:param name="s" as="xs:string" />
    <xsl:value-of select="fn:codepoints-to-string(fn:reverse(fn:string-to-codepoints($s)))" />
  </xsl:function>

</xsl:stylesheet>
九九の表示 (Nested Flatten)
素直に if を使わない。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:for-each select="1 to 9">
      <xsl:variable name="i" as="xs:integer" select="." />
      <xsl:for-each select="1 to 9">
        <xsl:value-of select="$i" />
        <xsl:text> * </xsl:text>
        <xsl:value-of select="." />
        <xsl:text> = </xsl:text>
        <xsl:variable name="elm" as="element()">
          <xsl:element name="n">
            <xsl:value-of select="$i*." />
          </xsl:element>
        </xsl:variable>
        <xsl:apply-templates select="$elm" />
        <xsl:text>&#xA;</xsl:text>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="n">
    <xsl:value-of select="." />
  </xsl:template>
  <xsl:template match="n[.&lt;10]">
    <xsl:text> </xsl:text>
    <xsl:value-of select="." />
  </xsl:template>

</xsl:stylesheet>
変形Fizz-Buzz問題 (Nested Flatten)
if すら使わずに。
# XSLTプロセッサによっては曖昧なマッチでエラーになるかも..
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  >

  <xsl:output method="text" />

  <xsl:template match="/" >
    <xsl:for-each select="1 to 20">
      <xsl:value-of select="." />
      <xsl:text> : </xsl:text>
      <xsl:variable name="elm" as="element()">
        <xsl:element name="n">
          <xsl:value-of select="." />
        </xsl:element>
      </xsl:variable>
      <xsl:apply-templates select="$elm" />
      <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="n">
    <xsl:text>hoge</xsl:text>
  </xsl:template>
  <xsl:template match="n[(. mod 3)=0]">
    <xsl:text>Fizz</xsl:text>
  </xsl:template>
  <xsl:template match="n[(. mod 5)=0]">
    <xsl:text>Buzz</xsl:text>
  </xsl:template>
  <xsl:template match="n[(. mod 3)=0 and (. mod 5)=0]">
    <xsl:text>FizzBuzz</xsl:text>
  </xsl:template>

</xsl:stylesheet>
next >>

Index

Feed

Other

Link

Pathtraq

loading...