=> Главная База Знаний Xslt Формальное определение образцов выбора


Формальное определение образцов выбора

Формальное определение образцов выбора

Определение образцов выбора приводится также в рекомендации XSLT W3C. Образцы выбора определяются в терминах выражений XPath следующим образом: «Синтаксис для образцов является подмножеством для выражений [XPath]. В частности, пути расположения, удовлетворяющие определенным ограничениям, могут использоваться как образцы. Выражение, в то же время являющееся образцом, всегда вычисляется в объект типа набора узлов. Узел удовлетворяет образцу, если узел является членом результата вычисления образца как выражения по отношению к возможному контексту; возможный контекст — это контекст, контекстный узел которого был выбран, или один из его предков».

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

Что в действительности это означает? Это значит, что когда нужно проверить, удовлетворяет ли узел образцу, сначала следует применить образец как выражение XPath к самому узлу, затем применить его последовательно ко всем его предкам, вплоть до корневого узла. Если какой-либо полученный при этом набор узлов будет содержать сам узел, узел удовлетворяет образцу. Такой порядок действий имеет смысл потому, что образцы выбора пишутся для применения к текущему узлу или его дочерним узлам.

СЛЕДСТВИЯ ФОРМАЛЬНОГО ОПРЕДЕЛЕНИЯ ОБРАЗЦОВ ВЫБОРА

Приведенное определение образцов в терминах выражений XPath довольно очевидно, но существуют следствия, которые сразу не видны. Например, хотя функция node() определена как функция, выбирающая любой узел, при использовании ее в качестве образца, "node()", в действительности она представляется как "child::node()", как вы увидите позже в этой главе. Помимо прочего, это означает, что образец "node()" может выбирать только дочерние узлы — он никогда не выберет корневой узел. Отметьте также, что нет образцов, которые бы могли выбрать узлы объявлений пространств имен.

W3C дает формальное определение образцов выбора в нотации расширенных форм Бэкуса-Наура (РБНФ), при помощи которой написана и спецификация XML. Объяснение этой грамматики можно найти по адресу www.w3.org/TR/REC-xml (раздел 6). Здесь я привожу формальное определение образцов только для справки. (Разъяснению этого формального определения посвящена целая глава.) В следующем списке приведены используемые здесь лексемы нотации РБНФ:

• 

::=
означает «определяется как»;

• 

+
означает «один или больше»;

• 

*
означает «ноль или больше»;

• 

|
означает «или»;

• 

-
означает «не»;

• 

?
означает «необязательно».

Далее приведено настоящее, формальное определение образцов выбора W3C; когда элемент заключен в одиночные кавычки, как

'child'
или
'::'
, это значит, что элемент должен появиться в образце буквально (как "
child::NAME
"), — такие элементы называются литералами, Literal:

Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern

LocationPathPattern ::= '/' RelativePathPattern?

 | IdKeyPattern ('/' | '//') RelativePathPattern?

 | '//'? RelativePathPattern

IdKeyPattern ::= 'id' '(' Literal ')' | 'key' '(' Literal '.' Literal ')'

RelativePathPattern ::= StepPattern | RelativePathPattern '/' StepPattern

 | RelativePathPattern '//' StepPattern

StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate*

ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier

 | ('child' | 'attribute') '::'

Определения NodeText (текстового узла) и Predicate (предиката) приводятся в спецификации XPath (

Expr
соответствует выражению XPath, a
NCName
и
QName
были определены в начале главы 2, «Создание и применение таблиц стилей»):

NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')'

Predicate ::= '[' PredicateExpr ']'

PredicateExpr ::= Expr

AbbreviatedAxisSpecifier ::= '@'?

NameTest :: = '*' | NCName ':' '*' | QName

NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'

Как вы можете видеть, все это больше походит на какой-то код. Давайте начнем его расшифровывать. Во-первых, образец (pattern) состоит из одного (или более) образца пути расположения (location path pattern). Образец пути расположения, в свою очередь, состоит из одного или нескольких образцов шага (step pattern), разделенных / или //, или одним (несколькими) образцом шага в объединении с функциями

id
и
key
(выбирающими элементы с определенными идентификаторами или ключами).

Образцы шага являются строительными блоками шаблонов: в одном пути можно использовать несколько шагов, разделяя их символами / или //, как в образце "

PLANET/*/ NAME
", в котором три шага: "
PLANET
", "
*
" и "
NAME
". Если вы начнете сам образец с символа /, он будет называться абсолютным, так как вы указали образец от корневого узла (как в "
/PLANETS/PLANET
" или "
//PLANET
"); иначе образец называется относительным и применяется начиная с контекстного узла (как в "
PLANET
").

Затем образец шага состоит из оси, условия узла и предикатов (которых может и не быть). Например, в выражении

child::PLANET[position()=5]
,
child
— это имя оси,
PLANET
— условие узла, a
[position()=5]
— это предикат. (Предикаты всегда заключены в квадратные скобки.) Образцы можно создавать при помощи одного или более образцов шага, как, например, образец
/child::PLANET/child::NAME
, который выбирает элементы
<NAME>
, дочерние по отношению к родителю
<PLANET>
.

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

step-pattern1/step-pattern2/step-pattern3
…". А чтобы понять работу образца шага, необходимо понять работу деятельности трех составных частей — осей, условий узлов и предикатов, которыми мы и займемся в следующих разделах.