- PR -

XSLTで日付による分岐をするには

1
投稿者投稿内容
noteZ
会議室デビュー日: 2006/07/22
投稿数: 9
投稿日時: 2007-02-20 01:06
XMLのデータをXSLTで加工して以下のような事をして、ホームページ内に
表示させたいのですが、初心者の為、具体的な方法が分からないが現状です。
お知恵を拝借させて下さい。_o_

■やりたいこと
data.xmlには、各データ群の要素内に登録日時の子要素があります。
現在の日付と登録日時の差分をとり、2日以内に登録された内容は、
赤で表示の上、行頭に特定の画像をつける、
3日以上7日以内に登録された内容は赤色で表示し画像は無し、
8日以上30日以内に登録された内容は黄色で表示、
31日以上3ヶ月以内に登録された内容は青色で表示、
それより古い内容は、黒で表示するという風にしたいのですが、
XSLTで現在の日付を取得し、かつ日付が何日以上何日以下という
評価をするにはどのようにしたらよいのかという所で悩んでいます。

■試そうとした事1
<xsl:script></xsl:script> というのを使えば、javascriptで
処理した戻り値を使って分岐させるとかでできそうな気もしますが
javascrptの経験がなく何から手をつけてよいのか分からず行き詰まり

■試そうとした事2
xslt 2.0 というのを使うと、dates and times とかいう機能で、
javascript無しでも、if文の評価して分岐をすれば、できるのかな
と思いましたが、日本語の解説サイトが見つからず、
英語の解説サイトを翻訳サイト経由で見ても意味がわからなくて
使用方法がわからず行き詰まり

という状態です。

日付の評価というのはどのようにしたらよいのでしょうか?
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2007-02-20 10:11
XSLT2.0 を使えるかが ポイントです、そういう条件は整ってますか。
noteZ
会議室デビュー日: 2006/07/22
投稿数: 9
投稿日時: 2007-02-20 11:20
[quote]
MMXさんの書き込み (2007-02-20 10:11) より:
XSLT2.0 を使えるかが ポイントです、そういう条件は整ってますか。
[/quote]

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
↑のversion="1.0" を "2.0" にして、日付の評価部分でXSLT2.0のコマンドを
使うだけで後はXSLT1.0が動く環境のままで使えると思っていましたが、
そんなに簡単ではないという事でしょうか?

環境としては、XMLDBサーバ等はなく、data.xmlとtemplate.xslという
ファイルをサーバに置いておき、dat.xmlからtemplate.xslを呼び出して、
htmlに変換し表示させるような感じです。
クライアント側のブラウザはIE6で、特殊なプラグインソフトとかを
インストールしなくても表示できるようにしたいです。
ひだちのいろ
会議室デビュー日: 2007/02/14
投稿数: 9
投稿日時: 2007-02-26 11:09
横レス失礼いたします。
noteZさん、初めまして。

おそらく上記の環境だと XSLT2.0 は使用できません。
IE 限定でいいなら、JScript を使う方法が残されています。

== sample.xml ==
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="sample.xsl"?>

<sample>
<data year="2007" month="2" date="26">データ1</data>
<data year="2007" month="2" date="20">データ2</data>
<data year="2007" month="1" date="30">データ3</data>
<data year="2006" month="12" date="30">データ3</data>
<data year="2005" month="12" date="30">データ4</data>
</sample>
================

== sample.xsl ==
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
<!-- 出力モード -->
<xsl:output method="html" encoding="Shift_JIS"/>

<msxsl:script language="JScript" implements-prefix="xmlns">
// 1970年1月1日0時0分0秒から現在まで経過した時間をミリ秒単位で返す。
function getNowTime()
{
var d = new Date();
return d.getTime();
}
// 1970年1月1日0時0分0秒から指定した日付まで経過した時間をミリ秒単位で返す。
function getTime(year, month, date)
{
var d = new Date(year, month-1, date);
return d.getTime();
}
// 日付の指定方法が文字列だった場合はこちらの関数「2006/12/25」とか。
function getTime2(dateStr)
{
// 正規表現を使って値を取り出す。
var result = /([0-9]{4})\\\\\\\\/([0-9]{1,2})\\\\\\\\/([0-9]{1,2})/.exec(dataStr);
var d = new Date(result[1], result[2]-1, result[3]);
return d.getTime();
}
// 日付の指定方法が文字列だった場合はこちらの関数「2006年12月25日」とか。
function getTime3(dateStr)
{
// 正規表現を使って値を取り出す、その2
var result = /([0-9]{4})年([0-9]{1,2})月([0-9]{1,2})日/.exec(dataStr);
var d = new Date(result[1], result[2]-1, result[3]);
return d.getTime();
}
</msxsl:script>

<xsl:template match="/">
<html>
<head><title>XSLTで日付による分岐をするには</title></head>
<body>
<h1>XSLTで日付による分岐をするには</h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>

<xsl:template match="data">
<xsl:choose>
<xsl:when test="xmlns:getNowTime()-xmlns:getTime(string(@year), string(@month), string(@date))<2*24*60*60*1000">
<div style="color:#ff0000">
<img style="width:2em; height:1em; border-width:1px;" alt="New!"/><xsl:value-of select="."/>(2日以内)
</div>
</xsl:when>
<xsl:when test="xmlns:getNowTime()-xmlns:getTime(string(@year), string(@month), string(@date))<7*24*60*60*1000">
<div style="color:#ff0000"><xsl:value-of select="."/>(7日以内)</div>
</xsl:when>
<xsl:when test="xmlns:getNowTime()-xmlns:getTime(string(@year), string(@month), string(@date))<30*24*60*60*1000">
<div style="color:#cc9900"><xsl:value-of select="."/>(30日以内)</div>
</xsl:when>
<xsl:when test="xmlns:getNowTime()-xmlns:getTime(string(@year), string(@month), string(@date))<120*24*60*60*1000">
<div style="color:#0000ff"><xsl:value-of select="."/>(3ヶ月以内)</div>
</xsl:when>
<xsl:otherwise>
<div><xsl:value-of select="."/>(それ以上)</div>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>
================

JScriptを使って日付を取得し、分岐そのものはXSLTの xsl:choose を使って行っています。
JScriptを使う際の要点をまとめると

・一番最初の <xsl:stylesheet ... xmlns:msxsl="urn:schemas-microsoft-com:xslt" ...> が必要。
・<msxsl:script language="JScript" implements-prefix="xmlns"> 〜 </msxsl:script> 中に関数を記述する。
・記述した関数は xmlns:関数名 で使用できる。
・関数に渡す引数が「値」の場合(ノードを直接渡したくない場合)は string(引数名) とする。

となります。
ただし、XSLT中にスクリプトを埋め込むのは、IE限定の方法です。

[ メッセージ編集済み 編集者: ひだちのいろ 編集日時 2007-02-26 11:15 ]
noteZ
会議室デビュー日: 2006/07/22
投稿数: 9
投稿日時: 2007-03-03 01:21
ひだちのいろ さん、ありがとうございます。

返信が遅れまして、すみません。

提示していただいたsample.xslを参考に当方の環境にて、
いろいろいじった結果、期待の動作をさせる事に成功しました。
ほんとうに感謝感謝です。

サンプルのままだと、大量のデータを読み込んだ場合、
xsl:when で評価する回数が多い為なのか、応答が遅いような感じ
がしたので、当方の環境では、

xmlns:getNowTime()-xmlns:getTime(string(@year), string(@month), string(@date))

この部分を xsl:param で変数にしてから xsl:when で振り分ける
という事をしましたら、気持ち早くなったようです。
(正確に測定したわけではないので気のせいかもしれませんが)

#そういう事を横道を試す前にさっさと返信しろと言われてしまうと
#「ごもっとも、ごめんなさい」と答えるしかないですが…
ひだちのいろ
会議室デビュー日: 2007/02/14
投稿数: 9
投稿日時: 2007-03-03 20:23
お役に立って何よりです。
確かに変数使った方が速いですよね。
noteZさんの書き込み見ていて思いついたのですが、テンプレートの外側で

<xsl:variable name="now" select="xmlns:getNowTime()"/>

としておいて、評価の時に$nowを使うようにすると、data毎にgetNowTime()を呼ばなくなるので、もうちょびっと早くなるかもしれません。
試してないので、目に見える効果があるかどうかは微妙なところですが、よかったらやってみてください。
1

スキルアップ/キャリアアップ(JOB@IT)