СЛЕДСТВИЯ ФОРМАЛЬНОГО ОПРЕДЕЛЕНИЯ ОБРАЗЦОВ ВЫБОРА
Приведенное определение образцов в терминах выражений 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') '::'
Определения 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'
Как вы можете видеть, все это больше походит на какой-то код. Давайте начнем его расшифровывать. Во-первых,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
…'. А чтобы понять работу образца шага, необходимо понять работу деятельности трех составных частей — осей, условий узлов и предикатов, которыми мы и займемся в следующих разделах.
Образцы шага, часть 1: оси образца
Оси — первая часть образцов шага. Например, в образце шага child::NAME
, ссылающемся на элемент <NAME>
, дочерний по отношению к контекстному узлу, child
называется осью. У образцов две оси:
• ось attribute
содержит атрибуты контекстного узла;
• ось child
содержит детей контекстного узла. Если ось явно не задана, ось child
будет осью по умолчанию.
При помощи осей можно задать шаг расположения (location path) или путь, как в следующем примере, в котором ось child
используется для задания выбора дочерних узлов контекстного узла, элемента <PLANET>
:
<xsl:template match='PLANET'>
<HTML>
<CENTER>
<xsl:value-of select='child::NAME'/>
</CENTER>
<CENTER>
<xsl:value-of select='child::MASS'/>
</CENTER>
<CENTER>
<xsl:value-of select='child::DAY'/>
</CENTER>
</HTML>
</xsl:template>
Рассмотрим ряд примеров применения осей:
• child::PLANET
. Возвращает дочерние элементы <PLANET>
контекстного узла;
• child::*
. Возвращает все дочерние элементы контекстного узла (* выбирает только