Книга: 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…". А чтобы понять работу образца шага, необходимо понять работу деятельности трех составных частей — осей, условий узлов и предикатов, которыми мы и займемся в следующих разделах.

Оглавление книги


Генерация: 0.039. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз