Выбрать главу

□ .. — выберет родительский узел контекстного узла; этот шаг выборки эквивалентен шагу parent::node();

□ namespace::*[contains(., 'XML')] — выберет узлы пространств имен, которые ассоциируются с контекстным узлом, и строковое значение (URI) которых содержит подстроку 'XML'. Этот шаг выборки эквивалентен шагу namespace::*[contains(self::node(), 'XML')];

□ preceding-sibling::*[@*] — выберет все братские узлы контекстного узла, которые предшествуют ему, являются элементами и содержат, по крайней мере, один атрибут;

□ *[not(self::para)] — выберет все дочерние элементы контекстного узла, кроме элементов para;

□ *[para or chapter] — выберет все дочерние элементы контекстного узла, которые имеют хотя бы один дочерний элемент para или chapter;

□ *[para and chapter] — выберет все дочерние элементы контекстного узла, которые имеют хотя бы один дочерний элемент para и хотя бы один дочерний элемент chapter;

□ *[para][chapter] — выберет все дочерние элементы контекстного узла, которые имеют хотя бы один дочерний элемент para и хотя бы один дочерний элемент chapter; этот шаг выборки равносилен *[para and chapter], однако в общем случае это неверно;

□ *[* or @*] — выберет все дочерние элементы, содержащие атрибуты или элементы;

□ *[not(* or @*)] — выберет все дочерние элементы, не содержащие ни атрибутов, ни элементов;

□ *[@name or @href] — выберет все дочерние элементы контекстного узла, имеющие хотя бы один из атрибутов name или href;

□ @*[count(.|../@href) != count(../@href)] — выберет все атрибуты контекстного узла, кроме атрибутов href;

□ [local-name() != 'href'] — выберет все атрибуты контекстного узла, кроме атрибутов href; это выражение практически аналогично предыдущему (за тем исключением, что в этом способе не учитываются пространства имен).

Примеры путей выборки:

□ / — выберет корневой узел документа;

□ /* — выберет элемент, находящийся в корне документа (элемент документа);

□ ancestor::body/a — выберет все элементы а, принадлежащие всем предкам-элементам body контекстного узла;

□ /ancestor::body/a — выберет все элементы а, принадлежащие всем предкам-элементам body корневого узла (это будет пустое множество);

□ //ancestor::body/a — выберет все элементы а, принадлежащие всем предкам-элементам body корневого узла и потомков корневого узла; иными словами, путь //ancestor::body выбирает элементы body, являющиеся предками каких-либо узлов документа, шаг a — дочерние узлы этих элементов; это выражение равносильно выражению //body[node()]/a;

□ preceding::а/@b — выберет атрибуты b элементов а, предшествующих контекстному узлу;

□ /doc/chapter — выберет элементы chapter, принадлежащие элементам doc, которые находятся в корне документа;

□ //doc/chapter — выберет элементы chapter, которые находятся в любом элементе doc документа;

□ doc/chapter — выберет элементы chapter, которые находятся в дочерних элементах doc контекстного узла;

□ self::node()[ancestor::body[1]] — выберет множество, состоящее из контекстного узла, если во множестве его предков body есть первый элемент (иначе — пустое множество); это выражение равносильно выражению self::node()[ancestor::body], поскольку если ancestor::body — непустое множество, то у него будет первый элемент;

□ *[contains(name(), 'ody')]/*[contains(name(),'able')] — выберет множество элементов, в имени которых присутствует строка "able" при условии, что они принадлежат дочерним элементам контекстного узла, в имени которых присутствует строка "ody";

□ *[last()]/preceding-sibling::*[2] — выберет второй с конца дочерний элемент контекстного узла. Это выражение равносильно *[last()-2];

□ */@* — выберет все атрибуты всех дочерних элементов контекстного узла;

□ //* [local-name(.) = 'body'] — выберет все элементы body текущего документа вне зависимости от их пространств имен.

Паттерны

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

Чаще всего паттерны применяются в элементе xsclass="underline" template в атрибуте match. Шаблоны такого типа будут выполняться только для тех узлов, которые удовлетворяют заданному образцу. Например, следующий шаблон будет выполняться только для элементов body, принадлежащих элементу html:

<xsclass="underline" template match="html/body">

 ...

</xsclass="underline" template>

Кроме этого, паттерны применяются при нумерации и при определениях ключей.

Паттерны являются сильно упрощенными путями выборки. Единственные оси, которые могут использоваться в паттернах, — это child, attribute и descendant-or-self, причем ось навигации descendant-or-self может быть указана только в сокращенном виде оператором "//". То, что в паттернах используются только оси атрибутов и узлов-потомков, позволяет XSLT-процессорам значительно оптимизировать процесс сопоставления узла заданному образцу — ведь теперь даже в самом худшем сценарии не нужно метаться по всему документу, выбирая узлы, содержащиеся в тех или иных осях навигации. Правда, оператор "//" остается не менее опасным — при его проверке может понадобиться перебрать всех предков текущего узла, что может быть весьма и весьма затруднительно (хотя и проще, чем перебор всех потомков).

Хоть паттерны и выглядят как пути выборки, на самом деле механизм их работы несколько иной. Они не выбирают множество узлов, как таковое, они проверяют узлы на соответствие образцу, который они определяют. Это в принципе эквивалентно выбору множества и проверке узла на вхождение в него, но, как правило, так не делается, поскольку такая проверка потребовала бы слишком больших затрат времени. Гораздо дешевле в этом смысле воспользоваться тем фактом, что синтаксис паттернов упрощен, и осей не так много для того, чтобы создать более эффективный алгоритм проверки соответствия узлов. Например, для того чтобы проверить соответствие некоторого узла, назовем его X, паттерну body/a, совершенно необязательно вычислять путь выборки body/a и затем проверять, входит ли узел X в полученное множество. Достаточно проверить, является ли именем узла "a", а именем его родителя (если он, конечно, есть) — "body".

Образцы для сравнения могут состоять из одного или нескольких паттернов, которые перечисляются через знак "|". Для того чтобы соответствовать такому перечислению в целом, узел должен соответствовать хотя бы одному из паттернов, входящих в него. Здесь тоже есть определенная аналогия с множествами, оператор "|" означает как бы объединение: узел входит в объединение множеств, если он входит хотя бы в одно из объединяемых множеств. Но, конечно же, и здесь упрощенный синтаксис играет свою роль для оптимизации — оперировать множествами, выбираемыми каждым из паттернов, было бы очень неэкономно.