Опубликован: 10.12.2007 | Уровень: специалист | Доступ: платный
Лекция 14:

Шаблоны

14.4. Часто встречающиеся образцы запросов

В шаблонах широко используются следующие запросы.

14.4.1. Контейнеры

Наиболее очевидные запросы шаблонов используют стандартную организацию фактов, а это означает применение RDF контейнера. Простой синтаксис запроса поддерживает эту организацию фактов.

14.4.2. Запросы одного факта

Запросы одного факта (см. предыдущее обсуждение) можно сконструировать лишь с использованием расширенного синтаксиса запросов. Простой синтаксис использовать нельзя. Запросы одного факта могут возвратить ноль или более решений. Единственное неизвестное может быть лишь дополнением запрашиваемого факта. Подлежащее и предикат должны быть известны и вдобавок буквально указаны в запросе. Подобный запрос можно реализовать лишь с тегами <member> или <triple>. Если использовать тег <member>, это выглядит так:

<rule>
<conditions> 
  <content uri="?uri"/> 
    <member container="?uri" child="?data"/> 
</conditions> 
  <action> 
    <description uri="?data" value="?uri ?data"/> 
  </action> 
</rule>

В данном случае, если предикат единичного факта не является фактом, содержащимся в контейнере (то есть rdf:_1, или некоторым специфичным для Mozilla значением, например child ), то этот предикат должен быть указан в атрибуте containment. В данном атрибуте можно перечислить несколько альтернативных предикатов. В случае <triple> код выглядит так:

<rule> 
<conditions> 
  <content uri="?uri"/> 
    <triple subject="?uri" predicate="predURI" object="?data"/> 
  </conditions> 
<action> 
  <description uri="?data" value="?uri ?data"/> 
</action> 
</rule>

Предикат - "predURI", выраженный литералом. Если требуется указать несколько предикатов, используйте несколько правил rule.

14.4.3. Набор свойств

Набор свойств - это запрос, чьей целью является получение ряда элементов информации, связанных с подлежащим факта. Типичный пример, когда мы рассматриваем подлежащее как объект JavaScript и хотим получить значения свойств этого объекта. Другой пример - считать подлежащее факта идентификатором записи в базе данных и получить все элементы данной записи. Эти аналогии не противоречат обычному использованию терминов "свойство" и "значение" в RDF.

Если подлежащее и его свойства являются членами RDF-контейнера, или контейнероподобного тега, простой синтаксис запроса строится так:

<rule> 
<box uri="rdf:*">
<label value="rdf:http://www.test.com/Test#Prop1"/> 
<label value="rdf:http://www.test.com/Test#Prop2"/> 
<label value="rdf:http://www.test.com/Test#Prop3"/> 
<label value="rdf:http://www.test.com/Test#Prop4"/> 
</box> 
</rule>

Если подлежащее и его свойства не являются элементами контейнера, следует использовать расширенную запись запроса. В этом случае стартовая точка та же, что и в запросе единичного факта, с использованием тега <triple>. Должно быть известно, что по крайней мере одно свойство существует.

<rule> 
<conditions> 
  <content uri="?uri"/> 
    <triple subject="?uri" predicate="p1" object="?v1"/> 
    <triple subject="?uri" predicate="p2" object="?v2"/> 
    <triple subject="?uri" predicate="p3" object="?v3"/> 
    <triple subject="?uri" predicate="p4" object="?v4"/>
</conditions> 
<action> 
  <description uri="?data" value="?v1 ?v2 ?v3 ?v4"/> 
</action> 
</rule>

Здесь p снова означает полный URI предиката, наподобие http://www.test.com/Test#Prop1. На каждое свойство множества приходится один триплет <triple>. Если некоторые свойства могут не существовать (или имеют значение null ), соответствующий тег <triple> можно заменить тегом <binding> и переместить в секцию <bindings>.

14.4.4. Единственные решения

Если запрос находит ровно одно решение, оно называется единственным решением. Обычно это бывает, если прикладной программист знает, что решение всегда существует, и единственно. Этот случай не требует специального синтаксиса, это просто следствие устройства фактов.

Здесь есть, однако, некоторая хитрость. Она возникает, когда мы используем атрибут uri в теге <action>. Поскольку речь идет о теге <action>, значит, это расширенный синтаксис. Здесь возникает случай, когда запрос найдет множество решений, но построит контент лишь для одного. Это возможно только для комплексных запросов. Приведенный ниже пример иллюстрирует этот случай. Предположим, что у нас есть следующий контент RDF:

<Description about="urn:example:root"> 
  <link1> 
    <Description about="urn:example:child"> 
      <link2 resource="urn:example:X"/> 
      <link2 resource="urn:example:Y"/> 
    </Description> 
  </link1> 
</Description>

Все ресурсы этих фактов можно обнаружить таким запросом:

<rule> 
<conditions> 
  <content uri="?uri"/> 
    <triple subject="?uri" predicate="p1" object="?child"/> 
    <triple subject="?child" predicate="p2" object="?res"/> 
</conditions> 
<action> 
  <description uri="?res" value="?uri ?child ?res"/> 
</action> 
</rule>

В этом запросе p1 и p2 нужно заменить подходящими URI для link1 и link2. Поскольку переменная ?res принимает свое значение для каждого решения (одно X и одно Y), будут порождены две копии контента тега <action>. Если, однако, тег <description> заменить следующей строкой, будет порождена лишь одна копия:

<description uri="?child" value="?uri ?child ?res"/>

Здесь порождается лишь одна копия, потому что переменная ?child может быть обоснована лишь одним значением. Обычно найденное решение соответствует первому найденному в документе RDF решению, но такое поведение не гарантируется.

14.4.5. Запросы шаблонов для деревьев

Все запросы шаблонов эквивалентны навигации по дереву данных, поскольку система запросов использует стратегию "сначала вниз". Запросы шаблонов кажутся сложными, потому что (а) зачастую они рекурсивны, (б) требуется расширенный синтаксис. Сложный синтаксис маскирует тот факт, что на самом деле они очень просты. Листинг 14.16 иллюстрирует это положение.

<tree flex="1" datasources="test.rdf"
  ref="http://www.example.com/test.rdf">
  <treecols> 
    <treecol id="colA" primary="true"/> 
  </treecols> 
<template>
  <rule>
    <conditions> 
      <content uri="?uri"/> 
        <member container="?uri" child="?item"/> 
    </conditions> 
    <action> 
    <treechildren> 
      <treeitem uri="?item"> 
        <treerow> 
          <treecell label="?item"/> 
        </treerow>
      </treeitem> 
    </treechildren> 
    </action> 
  </rule> 
</template> 
</tree>
Листинг 14.16. Простой запрос для дерева с расширенным синтаксисом.

В листинге 14.16 приведена прямолинейная минимальная комбинация шаблона и дерева. Темным выделена разметка шаблона, светлым - разметка дерева. Несмотря на то, что конструируется общий случай, разметка собственно шаблона очень проста. Секция <rule> есть не что иное, как запрос единичного факта. Результат запроса используется ровно в одном месте. Код кажется сложным, потому что перегруженная разметка дерева смешивается с перегруженной разметкой шаблона. Если тег <tree> заменить на <box> а порождаемый контент минимизировать до тега <description>, шаблон сведется к листингу 14.17.

<box datasources="test.rdf" ref="http://www.example.com/test.rdf"> 
<template> 
  <rule> 
    <conditions>
      <content uri="?uri"/> 
        <member container="?uri" child="?item"/>
    </conditions> 
    <action> 
      <description uri="?item" value="?item"/>
    </action> 
  </rule> 
</template> 
</box>
Листинг 14.17. Простой запрос для дерева с расширенным синтаксисом.

Здесь видно, что он несложен.

Эту запись можно упростить и дальше, если RDF контент организован стандартно. Если запрос рекурсивен, это упрощение окажется немного сложнее, чем может показаться на первый взгляд. Стандартная организация требует двух фактов, чтобы запрос с простым синтаксисом извлек единственное значение RDF свойства. Эти два факта имеют в качестве подлежащих идентификатор контейнера и тег member контейнера.

Оба факта должны повторяться вниз по дереву, поскольку каждый шаг запроса требует обоих фактов. Это значит, что дерево, исследуемое запросом с простым синтаксисом, должно быть вдвое больше, нежели дерево, запрашиваемое более экономичным расширенным. В листинге 14.17 требуется только один факт на каждый шаг вниз по дереву.

14.4.6. Объединения запросов

Есть несколько способов получить решения объединений двух или более запросов.

Атрибут datasources может указывать на несколько RDF файлов или иных источников данных, так что результат запроса будет объединением нескольких множеств фактов.

Атрибут containment может добавить к запросу несколько разных предикатов container.

Можно использовать несколько тегов <rule>, чтобы найти более одного решения на данном множестве фактов.

Можно использовать несколько тегов <binding>, чтобы получить несколько поддеревьев данного запроса.

14.4.7. Некорректные запросы

Следующий запрос не будет обработан:

<rule> 
<conditions> 
  <content uri="?uri"/> 
  <triple subject="?uri" predicate="a" object="?v1"/> 
  <triple subject="?v1" predicate="b" object="?v2"/> 
  <triple subject="?v2" predicate="c" object="?v3"/> 
  <triple subject="?v4" predicate="d" object="?v3"/>
</conditions> 
</rule>

В данном запросе последний тег <triple> не использует переменную ?v3 как подлежащее, а пытается двигаться по дереву в обратную сторону. Это уменьшает глубину проникновения в дерево на шаг, вместо того чтобы двигаться вглубь. Такое поведение запроса не реализовано, все условия <conditions> должны продвигать запрос в одну сторону.

Дмитрий Гуменюк
Дмитрий Гуменюк
Россия, Звенигород
Konstantin Grishko
Konstantin Grishko
Россия, Москва, Московский финансово-промышленный университет "Синергия", Москва