РОССИЙСКИЙ НАУЧНЫЙ ЭЛЕКТРОННЫЙ ЖУРНАЛ Электронные библиотеки
2003 | Том 6 | Выпуск 4

Язык XML Path (XPath) и его функциональная реализация SXPath

Д.А. Лизоркин, К.Ю. Лисовский

Московский Государственный Университет,
Институт Системного Программирования РАН


XPath -- это язык для адресации структурных частей XML-документа. Данная статья дает обзор XPath и рассматривает его применение для Электронных Библиотек (ЭБ).

SXPath -- это реализация XPath на языке функционального программирования Схема. SXPath базируется на модели данных SXML -- представлении Информационного Пространства XML Infoset в виде S-выражений. Дизайн SXPath, рассматриваемый в данной статье, показывает, как великолепно функциональные методы подходят для реализации SXPath; и иллюстрирует практически неограниченные возможности, предоставляемые комбинацией SXPath и языка Схема. SXPath может использоваться как язык запросов для основанной на XML электронной библиотеки.

1  Введение

Язык XML Path (XPath) [1] -- это язык для адресации частей XML-документа [2]. XPath является ключевым языком для множества XML-технологий и используется многими важными XML-языками; в частности, XSLT, XPointer и XQuery.

В нашей предыдущей статье [3] мы обсуждали, как ресурсы Электронных Библиотек могут быть описаны с помощью Dublin Core и представлены в Модели Описания Ресурсов (Resource Description Framework, RDF) как XML-документ. Мы напомним вид подобного описания на рисунке 1, и будем далее ссылаться на него в этой статье. Чтобы использовать такие описания ресурсов, приложению необходим инструмент для извлечения требуемой информации из XML-документа. Например, чтобы найти нужный ресурс в Электронной Библиотеке, приложение, вероятно, захочет адресоваться к некоторым полям в описании ресурса -- для их анализа на предмет удовлетворения условиям поиска. Поскольку поля в описании на RDF/XML являются частями XML-документа, XPath, обсуждаемый в данной статье, является основным инструментом для подобной адресации.


<?xml version="1.0"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> <rdf:Description> <dc:creator>Karl Mustermann</dc:creator> <dc:title>Algebra</dc:title> <dc:subject>mathematics</dc:subject> <dc:date>2000-01-23</dc:date> <dc:language>EN</dc:language> <dc:description>An introduction to algebra</dc:description> </rdf:Description> </rdf:RDF>


Table 1: XML-документ (иллюстрирующий описание книги с помощью Dublin Core, выраженное в Модели Описания Ресурсов)


Раздел 2 дает общий обзор языка XML Path. Раздел 3 вводит SXPath -- реализацию XPath функциональными методами. Пункты 2.1 и 3.1 описывают некоторые технические подробности организации пространств имен в XPath и SXPath соответственно. Раздел 4 объясняет, почему функциональные методы великолепно подходят для реализации XPath, иллюстрируя изложение примерами реализации базовых концепций XPath как функций низкого уровня библиотеки SXPath. Раздел 5 рассматривает пользовательские функции высокого уровня в SXPath, и обсуждает свойство SXPath как языка запросов.

2  Обзор XPath

Назначение XPath -- это адресация частей XML-документа. XPath трактует документ как дерево узлов, -- поскольку XML-документ является, в сущности, древовидной структурой. Адресация частей документа производится с помощью так называемого пути доступа (location path) [4], имеющего текстовый синтаксис. Путь доступа обычно применяется к корню XML-документа, и результат вычисления пути доступа для этого документа -- это набор узлов (node-set) [4], состоящий из (возможно, нескольких) узлов, выбранных с помощью данного пути доступа. Выбранные узлы соответствуют XML-элементам, атрибутам, текстовым данным и другим частям исходного XML-документа.

Пример пути доступа языка XML Path приводится на рисунке 2. Путь доступа состоит из последовательности одного или более шагов доступа (location steps), разделенных символом /. Так, путь доступа на рисунке 2 состоит из 4 шагов доступа.


rdf:RDF/rdf:Description/dc:title/text()


Table 2: Пример пути доступа


Шаги в пути доступа вычисляются по очереди слева направо. Самый левый шаг вычисляется первым, обычно по отношению к узлу, который представляет корень XML-документа. Каждый последующий шаг доступа выбирает набор узлов, который вычисляется по отношению к набору узлов, выбранному предыдущим шагом доступа. Набор узлов, выбранный самым правым шагом доступа -- это результат всего пути доступа для данного XML-документа.

Шаг доступа состоит из трех частей [1]:

  • Оси (axis), определяющей соотношение в дереве между узлами, в контексте которых вычисляется шаг доступа, и узлами, которые выбирает шаг доступа. Ось можно считать "направлением движения" по дереву, представляющему XML-документ. Спецификация XPath определяет 13 различных осей. Они включают в себя оси для спуска к листьям дерева, для подъема в сторону корня, для выбора соседних узлов и т.п. Синтаксически имя оси отделяется от остальной части шага адресации с помощью "::" (двойного двоеточия).
  • Теста узла (node test), определяющего тип и, возможно, имя узлов, выбираемых шагом доступа. В то время как ось определяет "направление движения", тест узла определяет желаемые узлы, которые должны быть выбраны.
  • Нуля или более предикатов (predicates). Каждый предикат синтаксически записывается в квадратных скобках и используется для дальнейшего просеивания набора узлов, выбираемых шагом доступа.

Для краткости изложения мы не будем рассматривать предикаты XPath в данной статье; читатель может ознакомиться с этим вопросом в [5].

Среди осей XPath наиболее важной является ось child. Эта ось включает в себя дочерние узлы контекстного узла. Для узла, представляющего собой XML-элемент, ось child выбирает его дочерние XML-элементы и дочерние текстовые узлы. Для корня документа, ось child выбирает элемент документа (document element). Данная ось используется в XPath по умолчанию, т.е. слово child:: можно опускать при написании шага адресации. В приведенном выше рисунке 2, каждый шаг доступа использует ось child.

Из существующих в XPath тестов узлов мы рассмотрим два.

Тест узлов text() допускает только текстовые узлы. Другими словами, если мы будем использовать терминологию, принятую в Спецификации XPath [1], тест узлов text() есть истина для каждого текстового узла. В примере на рисунке 2, последний (самый правый) шаг доступа использует этот тест узлов.

Тест узлов, представляемый (квалифицированным) XML-имемем, есть истина только для узла с тем же именем. Для узла, который представляет XML-элемент, именем узла является имя этого XML-элемента. В примере на рисунке 2 первые три шага доступа используют тесты узлов, которые являются квалифицированными XML-именами (соответственно, rdf:RDF, rdf:Description и dc:title). Механизм разрешения префиксов пространств имен в XPath обсуждается более подробно в пункте 2.1.

Будучи примененным к корню XML-документа, показанного на рисунке 1, путь доступа, рассмотренный на рисунке 2, будет вычисляться следующим образом:

  1. Первый шаг доступа (вычисляемый относительно корня документа) выбирает множество узлов, состоящее лишь из элемента документа rdf:RDF (он удовлетворяет тесту узла);
  2. Второй шаг доступа выбирает все дочерние для элемента документа узлы с именем rdf:Description (в рассматриваемом документе есть ровно один такой узел);
  3. Аналогично, третий шаг доступа выбирает все элементы dc:title, являющиеся дочерними для выбранного на втором шаге элемента rdf:Description (в рассматриваемом документе такой элемент dc:title ровно один);
  4. Наконец, четвертый шаг доступа выбирает дочерние текстовые узлы для ранее выбранного элемента dc:title. Это вычисляется в набор узлов, состоящий из единственного текстового узла "Algebra", и это становится результатом вычисления всего пути доступа для данного документа.
Таким образом, путь доступа на рисунке 2 адресуется к названию книги, описанной в XML-документе на рисунке 1.

2.1  XPath и пространства имен

Элементы и атрибуты в XML-документе в общем случае имеют имена, квалифицированные [6] с помощью Унифицированного Идентификатора Ресурса (Uniform Resource Identifier, URI). Как обсуждалось в нашей предыдущей статье [3], роль Унифицированного Идентификатора Ресурса в имени -- просто позволить приложениям распознать имя. Рекомендация о Пространствах Имен в XML квалифицирует имена с помощью Унифицированных Идентификаторов Ресурсов косвенным способом, который основан на идее префикса. Если тип элемента или имя атрибута содержит двоеточие, то часть имени, стоящая перед двоеточием, рассматривается как префикс, а часть имени после двоеточия -- как локальное имя. Префикс foo ссылается на Унифицированный Идентификатор Ресурса, определяемый значением атрибута xmlns:foo [7]. Таким образом, имя вершины моделируется как пара, состоящая из локальной части и (возможно, отсутствующего) Унифицированного Идентификатора Ресурса пространства имен; все вместе называется расширенным именем (expanded-name).

Чтобы выбрать элементы и атрибуты, имеющие квалифицированные имена, XPath использует тест узлов, который сам является квалифицированным именем, т.е. он синтаксически состоит из локального имени и префикса, разделенных двоеточием. Квалифицированное имя в тесте узла преобразуется в расширенное имя с помощью набора объявлений пространств имен (namespace declarations) из контекста вычисляемого XPath-выражения. Набор объявлений пространств имен представляет собой отображение префиксов на Унифицированные Идентификаторы Ресурсов пространств имен. Тест узла, являющийся квалифицированным именем, есть истина, только если вершина имеет расширенное имя, совпадающее с расширенным именем для данного квалифицированного имени; т.е. у них совпадают Унифицированные Идентификаторы Ресурсов пространств имен и локальные имена.

Процессору XPath набор объявлений пространств имен предоставляется от пользователя XPath, в частности, от XSLT или XPointer. Рекомендации XSLT и XPointer специфицируют, как объявления пространств имен определяются для XPath-выражений, используемых в XSLT и XPointer соответственно.

Необходимо отметить, что набор объявлений пространств имен в XPath и объявления пространств имен в документе полностью независимы. В XML-документе, префикс foo ссылается на Унифицированный Идентификатор Ресурса, заданный в ближайшем атрибуте xmlns:foo; и имя префикса выбирается дизайнером документа. В пути доступа языка XML Path, префикс ссылается на набор объявлений пространств имен (namespace declarations); и имя префикса выбирается разработчиком приложения. Эти два вида префиксов никак не соотносятся друг с другом. Вместо этого, соответствующие им Унифицированные Идентификаторы Ресурсов пространств имен сравниваются при вычислении теста узлов.

Чтобы сделать наш пример пути доступа на рисунке 2 корректным, нам теперь следует упомянуть набор объявлений пространств имен: префикс rdf: ассоциируется с пространством имен Модели Описания Ресурсов "http://www.w3.org/1999/02/22-rdf-syntax-ns#", а префикс dc: ассоциируется с пространством имен Dublin Core "http://purl.org/dc/elements/1.1/".

3  SXPath: реализация языка XML Path на Схеме

В данном разделе мы рассмотрим SXPath [8] -- реализацию XPath на языке функционального программирования Схема (Scheme) [9].

Прежде всего, мы хотели бы заметить, что текстовое представление XML с парными угловыми скобками является лишь внешним представлением XML-документа [10]. Приложениям (и, в частности, процессорам XPath) приходится работать с его внутренним представлением, которое позволяло бы приложению находить конкретные данные или трансформировать их.

Например, реализации XPath могут использовать Объектную Модель Документа (Document Object Model, DOM) как интерфейс прикладного программирования для управления XML-данными. Как обсуждалось в [11], большое различие между внешней текстовой нотацией XML и этой внутренней объектной моделью приводит к неприятной проблеме несоответствия импеданса [12].

Реализация XPath на Схеме позволяет нам использовать очень естественное и удобное внутреннее представление для XML-данных -- SXML [10]. SXML -- это представление для XML-документа в форме S-выражения. Как мы обсуждали в [11], текстовые нотации XML и SXML довольно похожи: грубо говоря, SXML лишь использует круглые скобки вместо каждой пары угловых скобок. Это делает нотацию SXML простой для изучения, краткой и простой для восприятия, и простой для редактирования, даже вручную. SXML, таким образом, может рассматриваться как одновременно внешнее представление документа и его внутреннее представление. Для иллюстрации данной идеи, рисунок 3 показывает SXML-аналог для XML-документа из рисунка 1.


(*TOP* (@@ (*NAMESPACES* (rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#") (dc "http://purl.org/dc/elements/1.1/"))) (*PI* xml "version=\"1.0\"") (rdf:RDF (rdf:Description (dc:creator "Karl Mustermann") (dc:title "Algebra") (dc:subject "mathematics") (dc:date "2000-01-23") (dc:language "EN") (dc:description "An introduction to algebra"))))


Table 3: SXML-документ, соответствующий XML-документу из рисунка 1


XML-документ может быть автоматически преобразован в соответствующий SXML-вид с помощью чисто функционального, написанного на Схеме парсера SSAX [13].

SXPath полностью соответствует Спецификации XPath Консорциума Всемирной Сети (World Wide Web Consortium). Рисунок 4 иллюстрирует, как путь доступа, рассмотренный нами на рисунке 2, может быть вычислен с помощью SXPath для показанного выше SXML-документа из рисунка 3. Здесь мы предполагаем, что этот документ связан (bound) с идентификатором Схемы doc.


((sxpath "rdf:RDF/rdf:Description/dc:title/text()") doc)


Table 4: Вычисление пути доступа из рисунка 2 с помощью SXPath (здесь мы предполагаем, что идентификатор doc связан с SXML-документом из рисунка 3)


SXPath естественным образом моделирует набор узлов, выбираемых путем адресации, в виде списка Схемы, членами которого являются SXML-узлы. Таким образом, пример на рисунке 4 возвращает список, состоящий из единственного текстового узла "Algebra".

SXPath разделяет непосредственно разбор пути доступа и его вычисление. Обработка XML с помощью SXPath состоит из двух последовательных фаз:

  1. Производится разбор пути доступа. Точнее, SXPath способен разбирать пути доступа с помощью "функциональных" шагов доступа, в дополнении к стандартному XPath. Результатом подобного разбора является функция, которая соответствует данному пути доступа. На рисунке 4 эта фаза соответствует внутреннему выражению на Схеме:

    (sxpath "rdf:RDF/rdf:Description/dc:title/text()")

  2. Сконструированная функция применяется к SXML-документу. Получив документ в качестве аргумента, функция возвращает набор узлов, как результат вычисления пути доступа для данного документа. На рисунке 4 эта фаза соответствует внешнему выражению на Схеме:

    ((...) doc)

Данный подход имеет следующие преимущества:
  • Функция, сконструированная с помощью SXPath, может неоднократно применяться к разным XML-документам. Скажем, мы можем привязать (bind) сконструированную функцию к идентификатору Схемы для последующих обращений:

    (define f (sxpath "rdf:RDF/rdf:Description/dc:title/text()")) -- и затем использовать эту функцию несколько раз:

    (f sxml-doc1) (f sxml-doc2) Например, это может быть полезно, когда мы вычисляем один и тот же путь доступа над несколькими документами или производим сравнение по образцу в XSLT [14]. Обратите внимание, что разбор пути доступа производится лишь один раз.

  • Аналогичная стратегия может использоваться для того, чтобы помещать разбор пути адресации в некритичные места нашей программы (скажем, в место, где производится инициализация). В этом случае, критичные по производительности места программы будут лишь применять уже сконструированную функцию.

3.1  SXPath и пространства имен

Как обсуждалось в нашей предыдущей статье [3], SXML применяет концепцию идентификаторов пространств имен, которая определенным образом напоминает префиксы пространств имен в XML. Аналогично префиксу, идентификатор пространства имен соответствует Унифицированному Идентификатору Ресурса, определяющему пространство имен. Отличительной чертой идентификаторов пространства имен является то, что существует взаимно однозначное соответствие между ними и Унифицированными Идентификаторами Ресурсов, определяющими пространства имен. Это в общем случае не так для префиксов пространства имен в XML.

Идентификатор пространства имен, таким образом, служит в качестве сокращения для Унифицированного Идентификатора Ресурса в SXML-именах. Необходимо отметить, что идентификаторы пространства имен выбираются разработчиком приложения, потому что они вводятся во время преобразования XML-документа в SXML. Рисунок 5 иллюстрирует эту идею с помощью вызова функции -- парсера SSAX [13]. Второй аргумент этого вызова определяет желаемые сокращения для некоторых конкретных Унифицированных Идентификаторов Ресурсов, определяющих пространства имен. При разборе XML-документа, SSAX автоматически разрешает XML-префиксы соответствующими Унифицированными Идентификаторами Ресурсов, а затем заменяет некоторые из них идентификаторами пространств имен, в соответствии с заданными сокращениями.


(ssax:xml->sxml (open-input-file "example.xml") '((rdf . "http://www.w3.org/1999/02/22-rdf-syntax-ns#") (dc . "http://purl.org/dc/elements/1.1/")))


Table 5: Преобразование XML-документа в SXML с помощью парсера SSAX. Предполагая, что "example.xml" содержит документ из рисунка 1, SSAX создаст SXML-документ, ранее показанный на рисунке 3.


Поскольку и имена префиксов в пути доступа языка XML Path, и идентификаторы пространств имен в SXML-документе выбираются разработчиком приложения, SXPath по умолчанию предполагает, что префикс в пути доступа символизирует идентификатор пространства имен. Подобное поведение SXPath логично, поскольку идентификатор пространства имен является сокращением для Унифицированного Идентификатора Ресурса в SXML-именах. Формально, если набор объявлений пространств имен не предоставлен функции sxpath, каждый префикс, появляющийся в пути доступа, рассматривается как идентификатор пространства имен с тем же именем, т.е. никакого отображения префиксов не производится.

SXPath способен принимать набор объявлений пространств имен как необязательный второй аргумент. Использование этого аргумента иллюстрируется рисунком 6. Набор объявлений пространств имен, являясь списком пар (prefix . namespace-URI), определяет отображение с префиксов, встречающихся в пути доступа, на Унифицированные Идентификаторы Ресурсов, определяющие пространства имен. Данное отображение необходимо для вычисления пути доступа для SXML-документа с квалифицированными явным образом именами [3], такого, как показан на рисунке 7.


((sxpath "rdf:RDF/rdf:Description/dc:title/text()" '((rdf . "http://www.w3.org/1999/02/22-rdf-syntax-ns#") (dc . "http://purl.org/dc/elements/1.1/"))) doc2)


Table 6: Вычисление пути доступа из рисунка 2 с помощью SXPath для SXML-документа с квалифицированными явным образом именами (здесь мы предполагаем, что идентификатор doc2 связан с SXML-документом из рисунка 7)



(*TOP* (*PI* xml "version=\"1.0\"") (http://www.w3.org/1999/02/22-rdf-syntax-ns#:RDF (http://www.w3.org/1999/02/22-rdf-syntax-ns#:Description (http://purl.org/dc/elements/1.1/:creator "Karl Mustermann") (http://purl.org/dc/elements/1.1/:title "Algebra") (http://purl.org/dc/elements/1.1/:subject "mathematics") (http://purl.org/dc/elements/1.1/:date "2000-01-23") (http://purl.org/dc/elements/1.1/:language "EN") (http://purl.org/dc/elements/1.1/:description "An introduction to algebra"))))


Table 7: SXML-документ с квалифицированными явным образом именами, соответствующий XML-документу из рисунка 1


4  Низкоуровневые функции SXPath

Не только интерфейс SXPath является простым, -- сама реализация XPath функциональными методами очень естественна и прямолинейна. В данном разделе мы дадим иллюстрацию того, как базовые концепции XPath реализуются в виде набора низкоуровневых функций библиотеки SXPath.

Как упоминалось в разделе 3, SXPath моделирует наборы узлов XPath как списки Схемы, членами которых являются SXML-узлы. Хотя сами узлы в SXML часто также представляют собой списки, мы всегда можем отличить набор узлов от отдельного узла: если узел представляет собой список, то его первым членом всегда будет символ Схемы (имя узла). Напротив, непустой набор узлов очевидно имеет своим первым членом SXML-узел, который никогда не может быть символом Схемы.

Предикат nodeset?, предоставляемый библиотекой SXPath, реализует в точности эту логику: он возвращает истину либо для пустого списка (пустого набора узлов), либо для списка, первым членом которого не является символ Схемы. Реализация предиката nodeset? показана на рисунке 8; car -- это базовая функция Схемы, возвращающая первый член списка-аргумента.


(define (nodeset? x) (or (null? x) ; пустой набор узлов (and (list? x) (not (symbol? (car x))))))


Table 8: Предикат для различения набора узлов и отдельного узла


Как обсуждалось в разделе 2, тест узла в XPath служит для того, чтобы специфицировать условие на узлы, выбираемые с помощью шага доступа. Поскольку Рекомендация XPath определяет тест узла в терминах "быть истинным для некоторого вида узлов", естественно реализовывать тест узла как предикат, который принимает SXML-узел и возвращает булевское значение в зависимости от того, удовлетворяет ли узел тесту узла.


(define (text? node) (string? node)) (define (ntype?? name) (lambda (node) (and (list? node) ; текстовый узел не имеет имени (eq? name (car node)))))


Table 9: Реализация некоторых тестов узлов XPath


Рисунок 9 дает упрощенную реализацию двух тестов узлов XPath, которые рассматриваются в данной статье:
  • Функция text? реализует тест узла text(), который допускает только текстовые узлы. В SXML текстовый узел представляется как строка (string) Схемы, поэтому стандартный предикат string? выполняет эту задачу.
  • Функция ntype?? реализует тест узла, который есть истина для узла с конкретным именем. Эта функция сначала параметризуется именем (name), и затем возвращает предикат, применимый к узлам:

    (lambda (node) (and (list? node) ; текстовый узел не имеет имени (eq? name (car node)))) Реализация этого предиката очевидна: узел должен быть списком (поскольку текстовый узел вообще не имеет имени) и первый член этого списка (получаемый с помощью car) должен совпадать с параметром name.

    Реализация оси child, показанная на рисунке 10 иллюстрирует, насколько великолепно SXML подходит в качестве модели данных для XPath.


    (define (select-kids node-test) (lambda (node) (if (text? node) '() ; нет дочерних узлов (filter node-test (cdr node)))))


    Table 10: Упрощенная реализация оси child


    Поскольку ось и тест узла действуют совместно, SXPath проектирует оси как параметризуемые с помощью предикатов, реализующих тесты узлов. Получив предикат node-test, функция select-kids создает функцию, принимающую на вход SXML-узел node и возвращающую его потомков, удовлетворяющих тесту узла:

    (lambda (node) (if (text? node) '() ; нет дочерних узлов (filter node-test (cdr node)))))

    Текстовый узел, очевидно, не имеет дочерних узлов, поэтому в этом случае возвращается пустой набор узлов. Иначе узел node является списком; и его дочерние узлы, выбираемые базовой функцией Схемы cdr, фильтруются в соответствии с предикатом node-test. Функция filter оставляет только те дочерние узлы, для которых предикат node-test есть истина.

    Поскольку SXML представляет элементы и атрибуты однородным образом [11], специальная реализация для оси attribute не требуется: в SXPath она является лишь частным случаем оси child.

    Библиотека SXPath включает в себя несколько функций, играющих роль комбинаторов. В частности, комбинатор node-join соединяет (joins) несколько функций, каждая из которых реализует отдельный шаг доступа, в законченный путь доступа. Реализация node-join является чисто технической и здесь не приводится. Вместо этого, на рисунке 11 мы проиллюстрируем одну конкретную комбинацию уже рассмотренных низкоуровневых примитивов SXPath. Легко видеть, что эта комбинация включает в себя четыре шага доступа, и реализует путь доступа из рисунка 2. Апостроф используется для включения литеральных констант в код на Схеме.


    (node-join (select-kids (ntype?? 'rdf:RDF)) (select-kids (ntype?? 'rdf:Description)) (select-kids (ntype?? 'dc:title)) (select-kids text?))


    Table 11: Комбинация низкоуровневых примитивов SXPath, которая образует функцию для вычисления пути доступа из рисунка 2.


    5  Высокоуровневые функции SXPath

    Главная функция, предоставляемая библиотекой SXPath -- это sxpath. Мы упомянули эту функцию в разделе 3, а здесь будем обсуждать ее более подробно.

    Функция sxpath, получив на входе путь доступа, разбирает его в соответствии с грамматикой XPath и переводит его в комбинацию низкоуровневых примитивов SXPath, часть из которых была рассмотрены в разделе 4. Например, если мы вернемся к рисунку 4, его внутреннее выражение

    (sxpath "rdf:RDF/rdf:Description/dc:title/text()")

    сконструирует функцию, очень похожую на ту, что была показана на рисунке 11. Низкоуровневые функции SXPath, таким образом, составляют виртуальную машину, в которую компилируются выражения более высокого уровня [15].

    В дополнение к "текстовому", соответствующему Спецификации XPath синтаксису для представления пути доступа, библиотека SXPath также вводит свое собственное "родное" представление для пути доступа -- в форме списка. В этом представлении шаги доступа записываются как члены списка. Идея иллюстрируется рисунком 12, а его внутреннее выражение

    (sxpath '(rdf:RDF rdf:Description dc:title *text*)) также сконструирует функцию, очень похожую на ту, что была показана на рисунке 11.


    ((sxpath '(rdf:RDF rdf:Description dc:title *text*)) doc)


    Table 12: Вычисление "родного" SXPath-аналога для пути доступа из рисунка 2 (здесь мы предполагаем, что идентификатор doc связан с SXML-документом из рисунка 3)


    С помощью данного "родного" представления для пути доступа, SXPath обеспечивает естественную возможность для функции Схемы -- служить в качестве одного из шагов в пути доступа, -- поскольку в SXPath функция Схемы является низкоуровневым представлением для шага доступа. Чтобы проиллюстрировать это утверждение, мы перепишем наш пример из рисунка 12, представив третий шаг доступа в его явной форме, как низкоуровневый примитив SXPath (рисунок 13). Следует заметить, что примеры на рисунках 4, 12 и 13 имеют одинаковую семантику. Хотя может показаться, что пример на рисунке 13 лишь добавляет излишнюю сложность, он позволяет проиллюстрировать очень важное свойство SXPath. А именно, возможность использовать произвольную функцию Схемы как шаг доступа в пути доступа обеспечивает SXPath практически неограниченными возможностями. В частности, это свойство делает SXPath языком запросов, о чем будет говориться в следующем пункте данной статьи.


    ((sxpath `(rdf:RDF rdf:Description ,(select-kids (ntype?? 'dc:title)) *text*)) doc)


    Table 13: Вычисление "родного" представления SXPath для пути доступа из рисунка 2, с третьим шагом доступа в форме функции Схемы (здесь мы предполагаем, что идентификатор doc связан с SXML-документом из рисунка 3)


    5.1  SXPath как язык запросов

    XPath определяется Консорциумом Всемирной Сети как язык адресации частей XML-документа. Это означает, в частности, что путь адресации в XPath не может вернуть что-либо отличное от набора узлов из документа, относительно которого этот путь доступа вычисляется.

    SXPath, однако, предоставляет возможности языка запросов, поскольку SXPath позволяет формулировать произвольные запросы к информации в XML/SXML-документах, и генерировать по ней произвольные отчеты.

    "Родное" представление для пути доступа в SXPath является S-выражением и может включать в себя произвольные процедуры, определенные на Схеме, в дополнение к набору предопределенных примитивов XPath.

    Для иллюстрации этого свойства мы модифицируем наш пример пути доступа, выбирающий заголовок книги. В соответствии с семантикой Dublin Core мы можем предположить, что описание книги всегда имеет ровно одно название (т.е. ровно один элемент dc:title); поэтому мы можем захотеть, чтобы путь доступа возвращал только этот заголовок, а не набор узлов. Далее, предположим, что мы хотим иметь этот заголовок, написанный большими буквами. Мы делаем эти действия пятым специализированным шагом в пути доступа (рисунок 14). Будучи вычисленным, этот путь доступа вернет строку "ALGEBRA". Заметим, что в SXML-документе не было текстового узла "ALGEBRA", эта строка была построена как результат запроса на SXPath.


    ((sxpath `(rdf:RDF rdf:Description dc:title *text* ,(lambda (nodeset) (string-upcase (car nodeset))))) doc)


    Table 14: Запрос на SXPath (здесь мы предполагаем, что идентификатор doc связан с SXML-документом из рисунка 3)


    Возможность использовать функции языка Схема в качестве предикатов SXPath, и возможность использовать выражения SXPath в функциях языка Схема, делают SXPath поистине расширяемым языком [15]. Пользователь может составлять запросы на SXPath, следуя Рекомендации XPath, -- и в то же время полагаться на полную выразительную мощь языка Схема.

    6  Заключение

    XPath -- это ключевой язык для множества XML-технологий, и он используется многими важными XML-языками, в частности, XSLT, XPointer и XQuery. Благодаря поддержке Пространств Имен в XML, XPath может использоваться для выбора информации из описаний, выраженных в Модели Описания Ресурсов, -- важной технологии в контексте электронных библиотек.

    SXML изначально разрабатывался с целью обеспечить эффективное вычисление выражений XPath. SXPath -- полностью соответствующая Спецификации реализация XPath на языке функционального программирования Схема -- расширяет XPath возможностями языка запросов и органично интегрирует XPath со Схемой. Комбинация SXPath и Схемы предоставляет мощную технологию для основанных на XML электронных библиотек, и особенно хорошо подходит для реализации "легковесных" электронных библиотек.

    Литература

    [1]
    Язык XML Path (XPath) Версия 1.0. Рекомендация W3C от 16 Ноября 1999.
    http://www.xpath.info/docs/REC-xpath-19991116-ru.html

    [2]
    Extensible Markup Language (XML) 1.0 (Second Edition). W3C Recommendation 6 October 2000.
    http://www.w3.org/TR/REC-xml

    [3]
    Д.А. Лизоркин, К.Ю. Лисовский. Пространства имен в XML и SXML. Электронные библиотеки, 2003, Том 6, Выпуск 3.
    http://www.elbib.ru/journal/2003/200303/LL/LL.ru.html

    [4]
    Когаловский М.Р. Глоссарий по технологиям платформы XML. Версия 3 (15-12-2002).
    http://www.elbib.ru/index.phtml?page=elbib/rus/methodology/xmlbase/glossary_XML

    [5]
    XPath Location Paths. W3 Schools.
    http://www.w3schools.com/xpath/xpath_location.asp

    [6]
    Namespaces in XML. World Wide Web Consortium 14-January-1999.
    http://www.w3.org/TR/REC-xml-names/

    [7]
    James Clark. XML Namespaces. February 4, 1999.
    http://www.jclark.com/xml/xmlns.htm

    [8]
    Kiselyov O. XML and Scheme. Workshop on Scheme and Functional Programming 2000, Montreal, 2000.
    http://www.okmij.org/ftp/Scheme/SXML-short-paper.html

    [9]
    H. Abelson, R. K. Dubving, C. T. Haynes, G. J. Rozas, N. I. Adams IV, D. P. Friedman, E. Kohlbecker, G. L. Sleete Jr., D. H. Bartley, R. Halstead, D. Oxley, G. J. Sussman, G. Brooks, C. Hanson, K. M. Pitman, M. Wand. Revised(5) Report on the Algorithmic Language Scheme.
    http://www.swiss.ai.mit.edu/ftpdir/scheme-reports/r5rs-html/r5rs_toc.html

    [10]
    Oleg Kiselyov. SXML, Revision 2.5. August 9, 2002.
    http://okmij.org/ftp/Scheme/SXML.html

    [11]
    Д.А. Лизоркин, К.Ю. Лисовский. SXML: XML-документ как S-выражение. Электронные библиотеки, 2003, Том 6, Выпуск 2.
    http://www.elbib.ru/journal/2003/200302/LK/LK.ru.html

    [12]
    Лисовский К. Ю. Разработка XML-приложений на языке Scheme. Программирование, выпуск 28, номер 4, 2002.
    http://www.maik.rssi.ru/journals/procom.htm

    [13]
    Oleg Kiselyov. Functional XML parsing framework: SAX/DOM and SXML parsers with support for XML Namespaces and validation. September 5, 2001.
    http://www.okmij.org/ftp/Scheme/SSAX.scm

    [14]
    Язык преобразований XSL (XSLT) Версия 1.0. Рекомендация W3C от 16 ноября 1999.
    http://www.rol.ru/news/it/helpdesk/xslt01.htm

    [15]
    O. Kiselyov, K.Lisovsky. XML, XPath, XSLT Implementation as SXML, SXPath and SXSLT. International Lisp Conference ILC 2002, San Francisco. October, 2002.
    http://www.okmij.org/ftp/papers/SXs.pdf


     

Об авторах

Д.А. Лизоркин - аспирант Московского Государственного Университета. В 2002 году защитил дипломную работу, посвященную реализации языка XML Linking Language (XLink) с помощью функциональных методов
e-mail: lizorkin@hotbox.ru

К.Ю. Лисовский - к.т.н., консультант по информационным технологиям, старший научный сотрудник
Института Системного Программирования РАН. Главная область исследовательских интересов - функциональные и логические методы обработки слабоструктурированных данных. С 1999 года участвовал в ряде исследовательских и прикладных проектов, связанных с разработкой и применением методов обработки XML-данных с использованием языка Схема.
e-mail: lisovsky@acm.org
http://pair.com/lisovsky/


©  Д.А. Лизоркин, К.Ю. Лисовский, 2003
Последнее обновление страницы было произведено: 2003-12-09

Все предложения и пожелания по содержанию и структуре портала направляйте по адресу rdlp@iis.ru