Технология XSLT — страница 2 из 66

Расширенная форма Бэкуса-Наура

Несмотря на то, что эта книга главным образом посвящена языку XSLT, в ней также описываются расширяемый язык разметки XML и язык обращения к частям ХМL-документов, называемый XPath. Подробное и точное описание этих языков невозможно без четких определений синтаксических конструкций.

Для описания синтаксиса рассматриваемых языков мы будем использовать расширенные формы Бэкуса-Наура (РФБН, или, по-английски, Extended Backus-Naur Form, EBNF). EBNF — это современная модификация методологии, которая впервые была использована для описания языка программирования Алгол-60. За прошедшие десятилетия формы Бэкуса-Наура были доработаны множеством авторов и сейчас в расширенном виде используются для описания ряда языков программирования различной степени сложности. EBNF-нотация также широко используется в технических рекомендациях Консорциума W3, которые фактически и являются стандартами рассматриваемых нами языков.

Нотация EBNF определяет язык как набор синтаксических правил, определяющих нетерминалы (конструкции языка) через терминалы (символы языка), а также другие нетерминалы. Правило состоит из двух частей, разделенных символами "

::=
":

конструкция ::= определение конструкции

В левой части правила стоит терминал определяемой конструкции, в правой — выражение, определяющее эту конструкцию. Правила EBNF также иногда называют продукциями, и мы тоже часто будем использовать этот термин, чтобы не путать эти правила с шаблонными правилами преобразований, которые главным образом и составляют преобразования в языке XSLT.

Терминалы, которые могут быть как отдельными символами, так и их последовательностями, определяются в нотации EBNF следующим образом:

#xN
, где
N
— шестнадцатеричный код, соответствует символу Unicode с кодом
N
. Например,
#х410
соответствует символу
А
кириллического алфавита (см. раздел "Использование Unicode" главы 1).

[a-zA-z]
,
[#xN-#xN]
— соответствует символу указанного интервала. К примеру,
[a-f]
соответствует любому из символов
а
,
b
,
с
,
d
,
e
,
f
.

[abc]
,
[#xN#xN#xN]
— соответствует любому из перечисленных символов. Например,
[#х410#х411#х412]
соответствует любому из символов
А
,
Б
,
В
. Символьные интервалы и перечисления могут использоваться совместно в одних квадратных скобках.

[^a-z]
,
[^#хN-#xN]
— соответствует любому символу, кроме символов указанного интервала. К примеру,
[^#х410-#x42F]
соответствует любому символу, кроме заглавных букв русского алфавита.

[^abc]
,
[^#xN#xN#xN]
— соответствует любому, кроме перечисленных символов. Например,
[^xyz]
соответствует любому символу, кроме символов
x
y
и
z
. Аналогично разрешенным интервалам и последовательностям символов, запрещенные интервалы и последовательности также могут использоваться совместно.

"строка"
— соответствует строке, которая приведена в двойных кавычках. Например,
"stylesheet"
соответствует строке
stylesheet
.

'строка'
— соответствует строке, которая приведена в одинарных кавычках. Например,
'template'
соответствует строке
template
.

Терминалы могут использоваться совместно с нетерминальными конструкциями в более сложных выражениях.

A?
означает, что выражение
A
необязательно и может быть пропущено.

A | B
соответствует либо выражению
A
, либо выражению
B
, но не им обоим одновременно (строгое "или"). Выражения такого вида называют иначе выбором.

A B
означает, что за выражением
A
следует выражение
B
. Последовательность имеет приоритет по сравнению с выбором —
A B | C D
означает последовательность выражений
A
и
B
или последовательность выражений
C
и
D
.

A - B
соответствует строке, которая соответствует выражению
A
, но не выражению
B
.

A+
означает последовательность из одного или более выражения
A
. Оператор "
+
" в EBNF старше оператора выбора,
A+ | B+
означает последовательность из одного или более выражения
A
или последовательность из одного или более выражения
B
.

A*
означает последовательность из нуля или более выражений
A
. Аналогично оператору "
+
", оператор "
*
" старше оператора выбора

(выражение)
— круглые скобки используются для группировки выражений. Выражения, заключенные в скобки, рассматриваются, как отдельная единица, которая может быть свободно использована в приведенных выше конструкциях. Например, выражение
A B C | B C | A D C | D C | C
можно переписать в виде
(A? (B | D) ) C
.

Нотация расширенных форм Бэкуса-Наура может с первого взгляда показаться очень сложной, однако, на самом деле это не так. Достаточно разобрать несколько примеров, как все встанет на свои места.

Пример

Рассмотрим реальную продукцию

Digits
языка XPath.
Digits
— это последовательность из нескольких цифр от
0
до
9
и определяется она следующим образом:

Digits ::= [0-9] +

Как правило, продукции в спецификациях языков пронумерованы для того, чтобы было легче на них ссылаться. Мы будем по возможности приводить эти номера так, как они указаны в технических рекомендациях — в квадратных скобках, например:

[31] Digits ::= [0-9]+

При помощи продукции Digits определяется такая продукция, как Number, которая соответствует числу. Число — это последовательность цифр, разделенная точкой на целую и дробную части:

[30] Number ::= Digits ('.' Digits?)?

                | '.' Digits

Чтобы лучше понять EBNF, попробуем немного упростить эту продукцию. Выражение

Digits?
внутри круглых скобок означает, что
Digits
может как присутствовать, так и быть опущенным, то есть
('.' Digits?) ?
равносильно
'.' ? | ('.' Digits)?
. Повторяя еще раз подобное упрощение с каждым из полученных выражений, в итоге преобразуем правило
Number
к виду:

Number ::= Digits

           | Digits '.' Digits

           | Digits '.'

           | '.' Digits

Следовательно, число имеет четыре варианта синтаксиса:

□ последовательность цифр, например

12345
;

□ последовательность цифр, разделенная точкой на целую и дробную части, например

3.14
;

□ последовательность цифр, заканчивающаяся точкой, например

6.
— что эквивалентно
6.0
;

□ последовательность цифр, начинающаяся точкой, например

.5
, что эквивалентно
0.5
.

Разберем еще одну продукцию языка XPath — определение литерала. Литерал в XPath — это последовательность символов, заключаемая в одинарные или двойные кавычки, которая используется в качестве строкового параметра в функциях и т.д. Единственным и вполне логичным ограничением на синтаксис литерала является то, что он не может содержать символ собственных кавычек — в этом случае непонятно, где же на самом деле литерал кончается, а где начинается (например,

'ab'cd'
).

Конструкция

Literal
задается следующим образом:

[29] Literal ::= '"' [^"]* '"'

                 | "'" [^']* "'"

В первом случае синтаксис литерала начинается двойными кавычками (

'"'
), затем идет последовательность, состоящая из любых символов, кроме двойных кавычек (
[^"]*
), затем закрывающие двойные кавычки (
'"'
). Во втором случае синтаксис имеет точно такой же вид с точностью до замены одинарных кавычек двойными и наоборот.

Другим очень часто используемым правилом является правило, определяющее пробельное пространство (англ. space или whitespace). Пробельными символами в XML-языках считаются такие символы, как табуляция, перевод строки, возврат каретки и сам пробел. Продукция

S
пробельного пространства задается, как последовательность из одного или более пробельного символа:

[3] S ::= (#х20 | #х9 | #xD | #хА)+

Как правило, EBNF-продукции языков XML-группы составлены довольно просто, но в некоторых случаях они разбиты на несколько правил, которые определены в разных частях спецификации. В таких случаях мы будем по возможности упрощать продукции, записывая их в раскрытом виде.

Обозначения

Для того чтобы текст книги был более понятен, мы будем использовать некоторые соглашения.

Прежде всего, код программ и текст XML-документов будет выделяться моноширинным шрифтом

Courier
. Листингам многих примеров будут предшествовать заголовки вида

Листинг 2.1. Входящий документ

Для того чтобы текст XML-документов был более наглядным, в листингах он будет форматироваться с пробельными отступами, например:

Еще раз повторим, что это форматирование применяется только в целях наглядности исходного кода, когда это не противоречит смыслу документа. В предыдущем случае документ на самом деле мог выглядеть как:

В тех случаях, когда позиции пробельных символов документа важны для повествования, они будут особым образом выделяться. Для обозначения пробела мы будем использовать символ "

", а для обозначения символа переноса строки — символ "
", например:

<а xmlns:d="urn:d">¶

□□

□□□□<с>¶

□□□□□□

□□□□□□¶

□□□□

□□¶

Базовые понятия или моменты, на которые следует обратить повышенное внимание, выделяются в тексте курсивом. Иностранные аббревиатуры и термины расшифровываются и переводятся в скобках, например: XSLT (от англ. extensible Stylesheet Language for Transformations — расширяемый язык стилей для преобразований). Ссылки на другие книги берутся в квадратные скобки с указанием года издания, например, [Кнут 2001]. Более точные библиографические данные можно найти в списке литературы.

Благодарности