Календарь с использованием XML
Календарь с использованием XMLМорда: СтандартнаяСераяЗеленая Главная / Портфель / Календарь с использованием XML Запомнить № 16:
Календарь с использованием XMLОпубликовано:
21 ноября 2002Изменено:
8 марта 2003 | UPDATE: В связи с ошибками содержащимися в предыдущем варианте этого примера, пример был серьёзно переделан и вместо двух неправильных вариантов кода, приведён один, — правильный.Первое, с чего хочу начать, — это собственно XML, формируемый парсером. Он имеет следующий вид (ноябрь 2002):
<month>
<month_year
month="11"
month_title="ноябрь"
next_month="12"
prev_month="10"
year="2002"
next_year="2003"
prev_year="2001"
hit="1"
/>
<weekdays>
<day title="Пн"/>
<day title="Вт"/>
<day title="Ср"/>
<day title="Чт"/>
<day title="Пт"/>
<day title="Сб"/>
<day title="Вс"/>
</weekdays>
<week>
<day d="0"/>
<day d="0"/>
<day d="0"/>
<day d="0"/>
<day d="1"/>
<day d="2"/>
<day d="3" f="1"/>
</week>
<week>
<day d="4"/>
<day d="5"/>
<day d="6" f="1" hit="1"/>
<day d="7"/>
<day d="8"/>
<day d="9"/>
<day d="10" in="1"/>
</week>
...
</month>
Или графически (сгенерировано XML Spy) это будет выглядеть так:Думаю особо объяснять тут нечего, расскажу лишь о назначении некоторых атрибутов. in — появляется у дня если этот день является текущим днем, f — появляется у дня, за который были материалы, hit — этот день/месяц выбран пользователем. Да и вы наверно уже обратили внимание что элементов week может быть несколько, сколько? — информация к размышлению.Информация о том, за какой месяц выводить календарь передаются коду класса через параметр конструктора. Параметр должен быть хэшем следующей структуры:
$date_user[
$.day(2)
$.month(10)
$.year(2002)
]
Т.е. если данные берутся из строки запроса, хэш можно инициализировать следующим образом:
$date_user[
$.day(^form:d.int(0))
$.month(^form:m.int(0))
$.year(^form:y.int(0))
]
Если при создании экземпляра класса ему передаётся хэш с нулевыми ключами, выводится календарь на текущий месяц текущего года.Далее код класса:
#######
# Calendar class
@CLASS
calendar
#######
@init[date_user]
# получение текущей даты
$date_now[^date::now[]]
^if($date_user.year && $date_user.month){
$d($date_user.day)
$m($date_user.month)
$y($date_user.year)
}{
$d($date_now.day)
$m($date_now.month)
$y($date_now.year)
}
# Инициал. хэш показывающий какой период времени передан
# при создании экземпляра класса
$self.date_user[$date_user]
# вызов метода для создания специфических для языка переменных
# по-умолчанию для русского, если нужен другой язык, сделать
# класс производный от этого и переопределить в нем только один
# метод @i18n[]
^i18n[]
# определение переменных месяца и года для пред. месяца календаря
$calendar_month_prev[^date::create($y;$m)]
^calendar_month_prev.roll[month](-1)
$prev_m($calendar_month_prev.month)
$prev_y($calendar_month_prev.year)
# определение переменных месяца и года для след. месяца календаря
$calendar_month_next[^date::create($y;$m)]
^calendar_month_next.roll[month](+1)
$next_m($calendar_month_next.month)
$next_y($calendar_month_next.year)
# the hash of publications(files)
$days_of_files[
^hash::sql{
SELECT
DAYOFMONTH(date_field),
some_field
FROM
some_table
WHERE
MONTH(date_field) = $m and
YEAR(date_field) = $y
}[$.distinct(1)]
]
#######
# Метод, в котором определяются специфические для разных языков
# параметры календаря
@i18n[]
# the hash of local calendar (month and day names)
$calendar_locale[
$.month_names[
$.1[Январь]
$.2[Февраль]
$.3[Март]
$.4[Апрель]
$.5[Май]
$.6[Июнь]
$.7[Июль]
$.8[Август]
$.9[Сентябрь]
$.10[Октябрь]
$.11[Ноябрь]
$.12[Декабрь]
]
$.day_names[
$.0[Пн]
$.1[Вт]
$.2[Ср]
$.3[Чт]
$.4[Пт]
$.5[Сб]
$.6[Вс]
]
]
$month[$calendar_locale.month_names.$m]
$calendar_month[^date:calendar[rus]($y;$m)]
#######
@xml[]
$result[
<month>
^month_year[]
^weekdays[]
^week[]
</month>
]
#######
# формирование тега для года и месяца
@month_year[][hit]
^if(
$date_user.day ||
(
$date_now.month == $date_user.month &&
$date_now.year == $date_user.year &&
$date_user.day
)
){
$hit[]
}{
$hit[hit="1"]
}
<month_year
month="$m"
month_title="$month"
next_month="$next_m"
prev_month="$prev_m"
year="$y"
next_year="$next_y"
prev_year="$prev_y"
$hit
/>
#######
# тег названий дней недели
@weekdays[]
<weekdays>
^for[i](0;6){
<day title="$calendar_locale.day_names.$i"/>
}
</weekdays>
#######
# формирование тегов для каждой недели месяца
# day - день месяца, может быть нулем, если начало/конец
# первой/последней недели месяца не приходятся на понедельник/воскресенье
@week[][day;in;f;hit]
^calendar_month.menu{
<week>
^for[i](0;6){
$day($calendar_month.$i)
# формирование атрибута текущего дня
^if(
$date_now.day == $day &&
$date_now.month == $date.month &&
$date_now.year == $date.year
){
$in[in="1"]
}{
$in[]
}
# формирование атрибута нахождения в данном дне
^if($day == $date.day){
$hit[hit="1"]
}{
$hit[]
}
# формирование атрибута наличия материалов за день
^if($days_of_files.$day){
$f[f="1"]
}{
$f[]
}
<day d="$day" $in $f $hit/>
}
</week>
}
Для получения XML кода календаря нужно сформировать объект конструктором init $object[^calendar::init[$date_user]] далее вызовом ^object.xml[] получаем XML календаря.Преобразуем полученный XML в HTML:
$date_user[
$.day(^form:d.int(0))
$.month(^form:m.int(0))
$.year(^form:y.int(0))
]
$object[^calendar::init[$date_user]]
$calendar_xml[^xdoc::create{^object.xml[]}]
$calendar_html[^$calendar_xml.transform[calendar.xsl]]
^calendar_html.string[
$.method[html]
$.indent[no]
]
Пример стилевой таблицы calendar.xsl:
<?xml version="1.0" encoding="windows-1251"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- переменные начальных значений месяца и года календаря -->
<xsl:variable name="start_year">2002</xsl:variable>
<xsl:variable name="start_month">2</xsl:variable>
<xsl:template match="month">
<table cellpadding="4" cellspacing="3" width="100%">
<tr>
<td
bgcolor="white"
align="center"
width="16%"
>
<xsl:call-template name="prev_month"/>
</td>
<td
bgcolor="white"
align="center"
colspan="5"
width="68%"
>
<xsl:choose>
<xsl:when test="week/*/@in">
<strong>
<xsl:call-template name="month_year_link"/>
</strong>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="month_year_link"/>
</xsl:otherwise>
</xsl:choose>
</td>
<td bgcolor="" align="center" width="16%">
<xsl:call-template name="next_month"/>
</td>
</tr>
<tr>
<xsl:apply-templates select="weekdays"/>
</tr>
<xsl:for-each select="week">
<tr>
<xsl:call-template name="week"/>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<!-- ссылка на предыдущий месяц -->
<xsl:template name="prev_month">
<xsl:choose>
<xsl:when
test="
month_year/@prev_year < $start_year
"
>
<<
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when
test="
month_year/@prev_month < $start_month and
month_year/@prev_year = $start_year
"
>
<<
</xsl:when>
<xsl:otherwise>
<a
href="{month_year/@prev_year}-{month_year/@prev_month}.html"
style="text-decoration: none;"
>
<<
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- ссылка на следующий месяц -->
<xsl:template name="next_month">
<xsl:choose>
<xsl:when test="week/*/@in">
>>
</xsl:when>
<xsl:otherwise>
<a
href="{month_year/@next_year}-{month_year/@next_month}.html"
style="text-decoration: none;"
>
>>
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- ссылка на текущий месяц -->
<xsl:template name="month_year_link">
<xsl:choose>
<xsl:when test="month_year/@hit">
<xsl:call-template name="month_year"/>
</xsl:when>
<xsl:otherwise>
<a href="{month_year/@year}-{month_year/@month}.html">
<xsl:call-template name="month_year"/>
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- название месяца и года -->
<xsl:template name="month_year">
<xsl:value-of select="month_year/@month_title"/>
<xsl:text> </xsl:text>
<xsl:value-of select="month_year/@year"/>
</xsl:template>
<!-- названия дней недели -->
<xsl:template match="weekdays">
<xsl:for-each select="day">
<td
align="center"
width="16%"
bgcolor="#eeeeee"
>
<xsl:choose>
<xsl:when test="position() != 7">
<xsl:value-of select="@title"/>
</xsl:when>
<xsl:otherwise>
<span style="color: red">
<xsl:value-of select="@title"/>
</span>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</xsl:template>
<!-- вывод недель месяца -->
<xsl:template name="week">
<xsl:for-each select="day">
<td align="center" width="16%">
<xsl:attribute name="bgcolor">
<xsl:choose>
<xsl:when test="@in">
#ffcc00
</xsl:when>
<xsl:otherwise>
white
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:choose>
<xsl:when test="position() != 7">
<xsl:call-template name="day"/>
</xsl:when>
<xsl:otherwise>
<span style="color: red">
<xsl:call-template name="day"/>
</span>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</xsl:template>
<!-- вывод дней -->
<xsl:template name="day">
<xsl:choose>
<xsl:when test="@hit">
<strong><xsl:call-template name="day_value"/></strong>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="no_hit"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- вывод невыбранных дней -->
<xsl:template name="no_hit">
<xsl:choose>
<xsl:when test="@f">
<a href="{//*/@year}-{//*/@month}-{@d}.html">
<xsl:call-template name="day_value"/>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="day_value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="day_value">
<xsl:choose>
<xsl:when test="@d = 0"/>
<xsl:when test="@d > 9">
<xsl:value-of select="@d"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>0</xsl:text><xsl:value-of select="@d"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Этот календарь легко преобразуется в требуемый вид для другого языка, например английского. Для этого необходимо создать класс производный от класса calendar в котором переопределяется всего лишь один метод ^i18n[], например для английского языка:
#######
@CLASS
calendar_eng
#######
@USE
calendar.p
#######
@BASE
calendar
#######
# Метод, в котором определяются специфические для разных языков
# параметры календаря
@i18n[]
# the hash of local calendar (month and day names)
$calendar_locale[
$.month_names[
$.1[January]
$.2[February]
$.3[March]
$.4[April]
$.5[May]
$.6[June]
$.7[July]
$.8[August]
$.9[September]
$.10[October]
$.11[November]
$.12[December]
]
$.day_names[
$.0[Su]
$.1[Mo]
$.2[Tu]
$.3[We]
$.4[Th]
$.5[Fr]
$.6[Sa]
]
]
$month[$calendar_locale.month_names.$m]
$calendar_month[^date:calendar[eng]($y;$m)]
Ну и далее вместо класса calendar подключайте и используйте calendar_eng:
$object[^calendar_eng::init[]]
$calendar_xml[<?xml version="1.0" encoding="$request:charset"?>
^xdoc::create{^object.xml[]}]
$calendar_html[^$calendar_xml.transform[calendar_eng.xsl]]
^calendar_html.string[
$.method[html]
$.indent[no]
]
Да и ещё, — в английском языке первый день недели не понедельник а воскресенье, поэтому стилевую таблицу необходимо подправить(переопределить в ней пару шаблонов). Текст calendar_eng.xsl:
<?xml version="1.0" encoding="windows-1251"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:import href="calendar.xsl"/>
<xsl:template match="weekdays">
<xsl:for-each select="day">
<td
bgcolor="#eeeeee"
align="center"
width="16%"
>
<xsl:choose>
<xsl:when test="position() != 1">
<xsl:value-of select="@title"/>
</xsl:when>
<xsl:otherwise>
<span style="color: red">
<xsl:value-of select="@title"/>
</span>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</xsl:template>
<xsl:template name="week">
<xsl:for-each select="day">
<td align="center" width="16%">
<xsl:attribute name="bgcolor">
<xsl:choose>
<xsl:when test="@in">
#ffcc00
</xsl:when>
<xsl:otherwise>
white
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:choose>
<xsl:when test="position() != 1">
<xsl:call-template name="day"/>
</xsl:when>
<xsl:otherwise>
<span style="color: red">
<xsl:call-template name="day"/>
</span>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Разумеется можно и не получать HTML из XML не отходя от кассы, — в случае если полностью вся страница/сайт формируется сначала в XML'е и затем преобразуется в HTML, это делать совсем не надо. Надо просто вставить вызов ^object.xml[] в требуемое место, ну и затем в нужном xsl файле подключать calendar.xsl и ловить им элемент month в требуемом месте.Ну вот и всё, ничего сложного я надеюсь. Работающий пример смотрите … сами знаете где смотреть :).Загрузить пример: calendar.zip (Дата: 2.8.2003 Размер: 4.18 Kб)<< № 15 | Содержание | № 17 >>Из последнего№ 24 Работаем с .htpasswd 08.11.2003 (Изменено: 10.01.2004)№ 23 Самодокументирование парсерного кода 14.09.2003№ 22 Работаем с RSS 21.02.2003№ 21 Топологическая сортировка 16.02.2003№ 20 Установка 3-го парсера на хостинге 350mb.ru 12.02.2003ПолезноеParser 3Parser.ruXMLRaleigh.ruXML Spy IDEZvon.orgГлавная / Портфель / Календарь с использованием XML Запомнить Информация о сервереАвторРегистрация/настройки
содержание | 2 | бизнес будущего - обучение у лидеров: товары будущего. самообучение - суть бизнеса, высокое качество, Присоедниться к мечте: открыть свой бизнес
Используются технологии
uCoz