Главная » XSLT » Определение светских и церковных праздников

0

Задача

Требуется узнать, является ли заданная дата праздничной.

Решение

К первому типу праздников относятся те, которые каждый год отмечаются в один тот же день. Например, определить абсолютную дату Дня независимости в США совсем просто:

<xsl:template name="ckbk:independence-day"> <xsl:param name="year"/>

<xsl:call-template name="ckbk:date-to-absolute-day"> <xsl:with-param name="month" select="7"/> <xsl:with-param name="day" select="4"/> <xsl:with-param name="year" select="$year"/> </xsl:call-template> </xsl:template>

Ко второму типу относятся праздники, отмечаемые в один и тот же день неде­ли, отсчитываемой от начала или конца месяца. Такие даты можно проверить с помощью следующей утилиты, которая обертывает шаблон k-day-on-or- before-abs-day из рецепта 4.8:

<xsl:template name="ckbk:n-th-k-day">

<!– n-ое вхождение k в данном месяце –>

<!– Если n положительно, отсчет ведется от начала месяца, иначе — от конца–> <xsl:param name="n"/>

<!– k – день недели (0 = воскресенье) –> <xsl:param name="k"/>

<xsl:param name="month"/> <xsl:param name="year"/>

<xsl:choose>

<xsl:when test="$n > 0">

<xsl:variable name="k-day-on-or-before"> <xsl:variable name="abs-day">

<xsl:call-template name="ckbk:date-to-absolute-day"> <xsl:with-param name="month" select="$month"/> <xsl:with-param name="day" select="7"/> <xsl:with-param name="year" select="$year"/>

</xsl:call-template> </xsl:variable>

<xsl:call-template name="ckbk:k-day-on-or-before-abs-day"> <xsl:with-param name="abs-day" select="$abs-day"/> <xsl:with-param name="k" select="$k"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="$k-day-on-or-before + 7 * ($n – 1)"/> </xsl:when> <xsl:otherwise>

<xsl:variable name="k-day-on-or-before"> <xsl:variable name="abs-day"> <xsl:call-template name="ckbk:date-to-absolute-day"> <xsl:with-param name="month" select="$month"/> <xsl:with-param name="day">

<xsl:call-template name="ckbk:last-day-of-month"> <xsl:with-param name="month" select="$month"/> <xsl:with-param name="year" select="$year"/> </xsl:call-template> </xsl:with-param>

<xsl:with-param name="year" select="$year"/> </xsl:call-template> </xsl:variable>

<xsl:call-template name="ckbk:k-day-on-or-before-abs-day" <xsl:with-param name="abs-day" select="$abs-day"/> <xsl:with-param name="k" select="$k"/> </xsl:call-template> </xsl:variable>

<xsl:value-of select="$k-day-on-or-before + 7 * ($n + 1)"/> </xsl:otherwise> </xsl:choose> </xsl:template>

Здесь предполагается использование григорианского календаря. Если вам нужно вычислять относительные даты в других календарях, придется написать соответствующий шаблон самостоятельно.

Теперь легко решить задачу для таких праздников, как День труда и День по­миновения в США (соответственно первый понедельник сентября и последний понедельник мая):

<xsl:template name="ckbk:labor-day"> <xsl:param name="year"/>

<xsl:call-template name="ckbk:n-th-k-day"> <xsl:with-param name="n" select="1"/> <xsl:with-param name="k" select="1"/>

<xsl:with-param name="month" select="9"/> <xsl:with-param name="year" select="$year"/> </xsl:call-template> </xsl:template>

<xsl:template name="ckbk:memorial-day"> <xsl:param name="year"/>

<xsl:call-template name="ckbk:n-th-k-day"> <xsl:with-param name="n" select="-1"/> <xsl:with-param name="k" select="1"/> <xsl:with-param name="month" select="5"/> <xsl:with-param name="year" select="$year"/> </xsl:call-template> </xsl:template>

Хотя дни перехода на летнее и зимнее время в США – не праздники, их тоже легко вычислить:

<xsl:template name="ckbk:day-light-savings-start"> <xsl:param name="year"/>

<xsl:call-template name="ckbk:n-th-k-day"> <xsl:with-param name="n" select="1"/> <xsl:with-param name="k" select="0"/> <xsl:with-param name="month" select="4"/> <xsl:with-param name="year" select="$year"/> </xsl:call-template> </xsl:template>

<xsl:template name="ckbk:day-light-savings-end"> <xsl:param name="year"/>

<xsl:call-template name="ckbk:n-th-k-day"> <xsl:with-param name="n" select="-1"/> <xsl:with-param name="k" select="0"/> <xsl:with-param name="month" select="10"/> <xsl:with-param name="year" select="$year"/> </xsl:call-template> </xsl:template>

Обсуждение

Рассмотреть все светские и церковные праздники в каждой стране и в каждом году невозможно. Однако их можно разбить на две категории: отмечаемые каж­дый год в один и тот же день (например, День независимости в США) и отмечае­мые в некоторый день недели, отсчитываемой от начала или конца определенного месяца (например, День труда в США). Даты церковных праздников часто легко определяются в соответствующем им календаре, но с трудом вычисляются в дру­гих календарных системах. Например, в восточной православной церкви Рождество отмечается 25 декабря по юлианскому календарю. Следовательно, по григорианско­му календарю православное рождество иногда празднуется в начале года, иногда в конце, а иногда не празднуется вовсе. Поскольку мы не в состоянии обсудить все церковные праздники для всех религий, заинтересованному читателю предлагается обратиться к справочным материалам, упомянутым в начале этой главы.

Отбор и обход – Введение

Любая сколько-нибудь интересная задача в XSLT подразумевает выполнение двух взаимосвязанных операций: определение того, какие узлы XML-документа следует посетить (отбор), и в каком порядке (обход). Задача отбора решается в ос­новном средствами языка XPath, который описывается отдельной спецификацией, тесно связанной с XSLT. Обход реализуется встроенными в XSLT конструкциями и зависит от того, как вы организуете шаблоны, в которых эти конструкции ис­пользуются.

Знатоки XSLT вряд ли найдут что-то новое для себя в этой главе. И все же она важна по двум причинам. Во-первых, в ней изложены идеи, которые отличают XSLT от других языков программирования. Именно на них спотыкаются нович­ки, делающие первые попытки овладеть XSLT. Во-вторых, представленные при­меры – это кирпичики, из которых строятся более сложные рецепты в последую­щих главах. Практически все, что делается на языке XSLT, включает в том или ином виде отбор и обход. Если прибегнуть к аналогии с кулинарией, то умение приготовить хороший коричневый основной соус – необходимое условие приго­товления соуса эспаньоль!1 Эта глава содержит рецепты различных вариантов «основного соуса», которыми вы должны овладеть в совершенстве, прежде чем переходить к более сложным приложениям XSLT.

Хотя примеры в этой главе довольно просты, ее нельзя считать руководством по XPath или XSLT. Читатель должен быть знаком с основами XPath, изложенными в главе 1. Предполагается также, что вы знаете о правилах обработки по умолчанию, применяемых в XSLT, и о том, как XSLT решает, какой шаблон обрабатывать далее. Если вам нужна дополнительная информация по этим темам, рекомендую книгу Майкла Кэя XSLT Programmer’s Reference (Wrox Press, 2004) или Эвана Ленца XSLT 1.0 Pocket Reference (O’Reilly, 2005). В этой главе различия между XSLT 1.0 и 2.0 не будут обсуждаться так подробно, как в предыдущих. Объясняется это тем, что в версии XSLT 1.0 средства выражения описываемых операций и так доста­точно развиты. Исключение составляют случаи, когда отбор основывается на по­строении групп узлов, связанных между собой условиями, не выражаемыми в терминах иерархической организации XML-документа. Так, желанным допол­нением стала новая команда xsl:for-each-group.

В некоторых примерах из этой главы применяется терминология, характерная для алгоритмов работы с древовидными структурами. Новичкам, возможно, не вполне ясно, какое отношение деревья имеют к XML. Ответ прост: XML можно рассматривать как язык описания деревьев, а XSLT – как язык обработки описанных таким образом деревьев. Вообще-то, процессор XSLT может обрабатывать также входные данные, представленные не в виде XML-документа; надо лишь «убедить» процессор в том, что это дерево, воспользовавшись SAX-драйвером. Майкл Кэй демонстрирует такую тех­нику в книге XSLT Programmer’s Reference (Wrox Press, 2001). Похожие примеры приво­дит Эрик М. Бурке (Eric M. Burke) в книгеJava and XSLT (O’Reilly, 2001). Так или ина­че, за примерами из этой главы стоит важная идея о том, что взгляд на задачу с точки зрения деревьев открывает несколько полезных приемов обработки XML.

В примерах ниже мы опираемся на следующие два тестовых документа. Что­бы не повторяться в каждом рецепте, я привожу их в примерах 5.1 и 5.2.

Пример 5.1. SalesByPerson.xml

<?xml version="1.0" encoding="UTF-8"?>

<salesBySalesperson>

<salesperson name="John Adams" seniority="1"> <product sku="10000" totalSales="10000.00"/> <product sku="20000" totalSales="50000.00"/> <product sku="25000" totalSales="920000.00"/> </salesperson>

<salesperson name="Wendy Long" seniority="5">

<product sku="10000" totalSales="990000.00"/> <product sku="20000" totalSales="150000.00"/> <product sku="30000" totalSales="5500.00"/> </salesperson>

<salesperson name="Willie B. Aggressive" seniority="10"> <product sku="10000" totalSales="1110000.00"/> <product sku="20000" totalSales="150000.00"/> <product sku="25000" totalSales="2920000.00"/>

<product sku="30000" totalSales="115500.00"/> <product sku="70000" totalSales="10000.00"/> </salesperson>

<salesperson name="Arty Outtolunch" seniority="10"/> </salesBySalesperson>

Пример 5.2. orgchart.xml

<?xml version="1.0" encoding="UTF-8"?> <employee name="Jil Michel" sex="female">

<employee name="Nancy Pratt" sex="female">

<employee name="Phill McKraken" sex="male"/> <employee name="Ima Little" sex="female">

<employee name="Betsy Ross" sex="female"/> </employee> </employee>

<employee name="Jane Doe" sex="female">

<employee name="Walter H. Potter" sex="male"/> <employee name="Wendy B.K. McDonald" sex="female" <employee name="Craig F. Frye" sex="male"/> <employee name="Hardy Hamburg" sex="male"/> <employee name="Rich Shaker" sex="male"/> </employee> </employee>

<employee name="Mike Rosenbaum" sex="male">

<employee name="Cindy Post-Kellog" sex="female"> <employee name="Allen Bran" sex="male"/> <employee name="Frank N. Berry" sex="male"/> <employee name="Jack Apple" sex="male"/> </employee>

<employee name="Oscar A. Winner" nsex="male"> <employee name="Jack Nickolas" sex="male"> <employee name="R.P. McMurphy" sex="male"/> </employee>

<employee name="Tom Hanks" sex="male">

<employee name="Forest Gump" sex="male"/> <employee name="Andrew Beckett" sex="male" </employee>

<employee name="Susan Sarandon" sex="female"> <employee name="Helen Prejean" sex="female"/ </employee> </employee> </employee> </employee>

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии