Глава 8.3. Пространства имен

8.3.1. Постановка проблемы

Из самого определения языка XML вытекает, что основным его достоинством является возможность определять собственные имена элементов и их атрибутов. Набор таких имен, определенных в DTD специализированного XML-языка, называется его словарем. Однако, произвольность создания словарей приводит к тому, что они зачастую содержат одинаковые имена для различных сущностей. Рассмотрим следующий пример:

<book>
  <title>Антигона</title>
  <author>Софокл</author>
  <price title="рубль">103.50</price>
</book>

Здесь присутствуют элемент title (название книги) и атрибут title (название денежной единицы), которые явно относятся к разным словарям. Но то, что очевидно для человеческого глаза, недоступно XML-процессору, проводящему формальный анализ документа. Для того, чтобы избежать двусмысленностей в XML-документе, который пользуется несколькими словарями, и были введены пространства имен (namespaces), описанные в этой главе.

По существу, пространство имен XML — это словарь, идентифицируемый ссылкой на URI ресурса, содержащего описание данного словаря. Каждому такому словарю приписывается префикс пространства имен, уникальный в пределах данного документа. Теперь, чтобы избежать двусмысленности, мы можем использовать полные формы имен элементов и атрибутов, которые состоят из префикса, указывающего на пространство имен, двоеточия и собственно имени. Такое ограниченное имя (qualified name) однозначно идентифицирует элемент или атрибут и указывает, к какому пространству имен он относится.

8.3.2. Декларация простанства имен

Существует два способа декларации пространства имен: декларация по умолчанию и явная декларация. Декларация по умолчанию объявляет пространство имен для всех элементов и их атрибутов, которые содержатся в данном элементе. Она имеет вид:

xmlns=URI

где xmlns — ключевое слово XML, а URI — это адрес ресурса, содержащего соответствующий словарь. В следующем примере элемент book и все элементы и атрибуты внутри него будут браться XML-анализатором из пространства имен "http://www.booker.com/schema".

<book xmlns="http://www.booker.com/schema">
  <title>Антигона</title>
  <author>Софокл</author>
  <price>103.50</price>
</book>

Явная декларация имеет вид:

xmlns:имя=URI

Как мы видим, она отличается наличием имени, которое задает префикс данного пространства имен. Рассмотрим следующий пример:

<book xmlns:bk="http://www.booker.com/schema"
      xmlns:money="http://www.finance.org/money">
  <bk:title>Антигона</bk:title>
  <bk:author>Софокл</bk:author>
  <money:price money:title="рубль">103.50</money:price>
</book>

Здесь элемент book содержит декларации двух пространств имен: первое из них имеет префикс bk, второе — money. При этом содержащиеся в нем элементы title и author относятся к первому пространству имен, а price и его атрибут title ко второму.

Из приведенных примеров видно, что декларация пространства имен выглядит как обычный атрибут со специальным именем xmlns, но может содержать дополнительно префикс, который позволяет нам уточнять, к какому пространству относится то или иное имя. Как отмечено выше, имена с префиксом (типа bk:author) называются ограниченными. При этом имя, следующее за двоеточием, называется локальным. Элементы и атрибуты, чьи имена не содержат префикса, считаются относящимися к пространству имен по умолчанию.

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

Существует особый префикс xml, который не требует декларации. Он зарезервирован для расширений языка XML и всегда относится к пространству имен "http://www.w3.org/XML/1998/namespace". Пример использования этого префикса приведен ниже.

8.3.3. Область действия пространства имен

Пространство имен действует только в пределах того элемента, атрибутом которого является его декларация. Рассмотрим на примере, что это означает.

<Trees>
  <!-- объявим пространством имен по умолчанию имена HTML -->
  <table xmlns="http://www.w3.org/TR/REC-html40">
    <tr><td>Название</td><td>Классификация</td><td>Описание</td></tr>
    <tr>
      <td><author xmlns="http://flora.com/trees">осина</author></td>
      <td><title xmlns="http://flora.com/trees">род тополь</title></td>
      <td>
        <details xmlns="http://flora.com/trees">
          <areal>леса и степи Северной Евразии</areal>
          <use>производство целлюлозы и спичек</use>
        </details>
      </td>
    </tr>
  </table>
</Trees>

В этом примере имена элементов не ограничены, т. е. не имеют префиксов. Поэтому элемент Trees не относится ни к какому пространству имен, элементы tr и td относятся к пространству имен "http://www.w3.org/TR/REC-html40", а все остальные элементы к пространству имен "http://flora.com/trees".

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

8.3.4. Базовые URI фрагментов XML-документа

Пространства имен в XML были, в частности, использованы для задания в XML-документе базового URI любого из его фрагментов. Как мы помним, в HTML для этого используется элемент BASE, однако он относится к HTML-документу в целом. XML в этом отношении более гибок; в нем мы можем задать базовый URI любого элемента с помощью атрибута xml:base следующего вида (напомним, что префикс xml относится к пространству имен "http://www.w3.org/XML/1998/namespace"):

xml:base=URI

Рассмотрим такой пример:

<?xml version="1.0"?>
<doc xml:base="http://example.org/today/">
  <head>
    <title>Виртуальная библиотека</title>
  </head>
  <body>
    <para>Прочти горячие новости дня!</para>
    <olist xml:base="/hotpicks/">
      <item xml:base="pick1.xml">Горячая новость №1</item>
      <item xml:base="pick2.xml">Горячая новость №2</item>
      <item xml:base="pick3.xml">Горячая новость №3</item>
    </olist>
  </body>
</doc>

Здесь корневой элемент doc содержит указание на свой базовый URI "http://example.org/today/", а относительные URI вложенных в него элементов будут разрешаться так:

  • базовым URI элемента olist является "http://example.org/today/hotpicks";
  • базовым URI элементов item являются "http://example.org/today/hotpicks/pick1.xml" и т. п.

Тепеь мы можем сформулировать строгие правила описания базовых URI. Во-первых, их синтаксис и семантика сооответствуют общим правилам, принятым для URI (см. Приложение 2). Во-вторых, действуют следующие соглашения о присвоении элементам базовых URI:

  • если элемент имеет атрибут xml:base, то это базовый URI элемента; в противном случае
  • если предок элемента имеет атрибут xml:base, то это базовый URI элемента; в противном случае
  • базовым URI элемента является URI раздела документа или внешнего раздела, содержащего данный элемент.

Наконец, в-третьих, относительные URI разрешаются в полные так же, как все относительные URI, но со следующими уточнениями:

  • базовым URI для ссылки внутри текста является базовый URI содержащего этот текст элемента;
  • базовым URI для ссылки внутри атрибута xml:base является базовый URI предка этого элемента;
  • базовым URI для ссылки внутри любого другого атрибута является базовый URI этого элемента;
  • базовым URI для ссылки внутри директивы является базовый URI предка этой директивы.