Вставка нового узла в документ
В работах [] и [] предлагается 3 разновидности операции вставки нового узла в документ:
вставка после (insert following), добавляющая новый узел сразу же после обрабатываемого узла таким образом, что они оба имеют общий родительский узел;
вставка перед (insert preceding), добавляющая новый узел сразу же перед обрабатываемым узлом таким образом что они оба имеют общий родительский узел;
вставка внутрь (insert into), добавляющая новый узел в качестве дочернего для обрабатываемого узла, последним по порядку документа (document order []).
В терминах SXML и функционального программирования эти операции вставки узла представляют собой простую комбинацию примитивов работы над списковыми структурами данных. Так, эффект “вставки перед” и “вставки после” достигается, когда обработчик формирует список, состоящий из добавляемого в документ нового узла и обрабатываемого узла. Соответственно, если в формируемом списке новый узел идет первым, то в дереве документа он будет добавлен перед
обрабатываемым узлом (вставка перед), если вторым — то после обрабатываемого (вставка после).
С целью параметризации обработчиков новым узлом, подлежащим вставке, обработчики реализуются как возвращаемый результат функции, которая и осуществляет необходимую параметризацию. Данный подход возможен благодаря тому, что функции Scheme являются объектами первого класса. Реализация обработчиков для “вставки перед” (insert preceding) и “вставки после” (insert following) приведена ниже:
(define (insert-preceding new-node) (lambda (node) (list new-node node)))
(define (insert-following new-node) (lambda (node) (list node new-node)))
Заметим, что при параметризации каждой из записанных функций для нескольких разных значений нового узла new-node будет получено несколько разных обработчиков. Рассмотренный дизайн обработчиков по добавлению узлов в виде возвращаемых результатов функций удобен для приложения, поскольку подлежащий вставке новый узел new-node, как правило, известен на этапе формулирования операции модификации, тогда как обрабатываемый узел node становится известным только на этапе обработки дерева документа.
При определении семантики операции “вставки внутрь” следует особо выделять случай, когда обрабатываемый узел является текстовым узлом, т.е. по определению не может содержать узлов, вложенных в него. Реакция на подобную ситуацию может различаться в зависимости от нужд конкретного приложения; ниже показывается реализация, которая оставляет обрабатываемый текстовый узел без изменения:
(define (insert-into new-node) (lambda (node) (if (not (pair? node)) ; текстовый node ; оставляем без изменения (append node (list new-node)))))
В рассматриваемых далее в данном разделе примерах используются выражения модификаций, исходно предложенные в [], и для них приводятся и обсуждаются аналоги на языке Scheme, записанные в терминах предлагаемой идеи обработчиков.
Пример 1
Запрос, содержащий операцию модификации на “вставку перед”, в терминах синтаксиса, разработанного в [], записывается в виде:
UPDATE INSERT <warning>High Blood Pressure!</warning>
PRECEDING //blood_pressure[systolic>180]
В контексте предложенной в данной статье идеи использования обработчиков для выражения операций модификации, рассматриваемый запрос получает естественное эквивалентное воплощение на Scheme для обработки документов в форме SXML:
(sxml:modify `("//blood_pressure[systolic>180]" ,(insert-preceding '(warning "High Blood Pressure!"))))
Функция sxml:modify
реализует запрос на модификацию, который может состоять из одной или более операций модификации. Операция модификации получает естественную нотацию в виде списка, состоящего из двух членов: выражения XPath и функции, играющей роль обработчика. Использованные при записи операции модификации выражения квази-цитирования (quasiquote, сокращенно обозначаемое символом "`") и снятия цитирования (unquote, сокращенно обозначаемое символом ",") показывают, что первый член списка представляет собой константное выражение, а второй член должен быть вычислен.
Результатом функции sxml:modify
является в свою очередь функция, которая и осуществляет обработку документа формата SXML.
В полной аналогии с примером 1 реализуются примеры на “вставку после” и “вставку перед”, и единственное отличие заключается в использовании соответствующего обработчика для каждой из этих операций.