Поделиться через


Из июльского выпуска журнала MSDN Magazine за 2001 г.

Журнал MSDN

Общие сведения о пространствах имен XML
Аарон Сконнард
N

amespaces являются источником большой путаницы в XML, особенно для тех, кто не знакомы с технологией. Большинство вопросов, которые я получаю от читателей, учащихся и участников конференции, так или иначе связаны с пространствами имен. На самом деле это немного иронично, так как пространства имен в РЕКОМЕНДАЦИИ XML (http://www.w3.org/TR/REC-xml-names) является одной из более коротких спецификаций XML, в которую входит чуть менее 10 страниц, за исключением приложений. Однако путаница связана с семантикой пространства имен, а не с синтаксисом, изложенным в спецификации. Чтобы полностью понять пространства имен XML, необходимо знать, что такое пространство имен, как определяются пространства имен и как они используются.
      Остальная часть этой колонки посвящена ответу на эти три вопроса, как синтаксически, так и абстрактно. К тому времени, когда вы закончите чтение этой статьи, вы поймете, как пространства имен влияют на семейство технологий XML.

Что такое пространство имен?

      Пространство имен — это набор имен, в котором все имена уникальны. Например, имена моих детей можно рассматривать как пространство имен, как имена корпораций Калифорнии, имена идентификаторов типов C++ или имена доменов Интернета. Любой логически связанный набор имен, в котором каждое имя должно быть уникальным, является пространством имен.
      Пространства имен упрощают создание уникальных имен. Представьте, как трудно было бы назвать вашего следующего ребенка, если имя должно быть уникальным по всему лицу земли. Ограничение уникальности более ограниченным контекстом, как мой набор детей, значительно упрощает вещи. Когда я назову своего следующего ребенка, мое единственное соображение заключается в том, что я не использую то же имя, которое я уже использовал для одного из моих других детей. Другой набор родителей может выбрать то же имя, что я выбираю для одного из своих детей, но эти имена будут частью отдельных пространств имен и, следовательно, могут быть легко различимы.
      Перед добавлением нового имени в пространство имен центр пространства имен должен убедиться, что новое имя еще не существует в пространстве имен. В некоторых сценариях это тривиальная ситуация, как и при именовании дочерних элементов. В других это довольно сложно. Сегодня многие интернет-именования власти представляют собой хороший пример. Однако если этот шаг пропущен, повторяющиеся имена в конечном итоге повреждают пространство имен, что делает невозможным ссылаться на определенные имена без неоднозначности. В этом случае набор имен больше не считается пространством имен— по определению пространство имен должно обеспечивать уникальность его членов.
      Чтобы быть полезными, самим пространствам имен также должны быть присвоены имена. После того как пространство имен имеет имя, можно ссылаться на его члены. Например, рассмотрим примеры пространств имен, показанные в двух полях на рис. 1. Имена этих примеров пространств имен : Microsoft и AcmeHardware соответственно. Обратите внимание, что несмотря на то, что оба этих пространства имен содержат одни и те же локальные имена, можно ссылаться на них без неоднозначности с помощью имен с указанием пространств имен, также показанных на рис. 1.

Рис. 1. Не неоднозначные пространства имен
Рис. 1. Не неоднозначные пространства имен

      Конечно, предполагается, что имена пространств имен также уникальны. Если это не может быть гарантировано, то фактические имена пространств имен также могут быть помещены в собственное пространство имен. Например, если есть несколько хранилищ AcmeHardware (один в Калифорнии и один в штате Юта), размещение имени AcmeHardware в двух отдельных пространствах имен разрешает конфликт, как показано ниже:
  California.AcmeHardware.Paint
Utah.AcmeHardware.Paint

      Этот шаблон можно продолжать столько раз, сколько потребуется, чтобы гарантировать уникальность имен пространств имен. Именно так работает система доменных имен Интернета (DNS) — это просто одно большое пространство имен.
      Без такого типа секционирования пространства имен вы будете вынуждены использовать очень длинные (нетипичные) имена, чтобы обеспечить уникальность:
  MicrosoftWindowsOperatingSystemPaintApplication

      Представьте себе сложность и в результате разочарование только одного глобального пространства имен, которое не может быть секционировано. Люди в значительной степени зависят от пространств имен в повседневных социальных взаимодействиях, хотя в большинстве случаев они не делаются явными. Однако для использования пространств имен при разработке программного обеспечения они должны быть явными с помощью конкретного синтаксиса. Прежде чем переходить к пространствам имен в XML, рассмотрим пример синтаксиса пространства имен в одном из основных современных языков программирования.

Пространства имен в языках программирования

      Чтобы использовать пространства имен на языке программирования, необходимо ознакомиться с синтаксисом для определения пространства имен и ссылки на что-то в пространстве имен. Многие из современных языков, включая C++, Java и C#, обеспечивают поддержку пространств имен. В C++ пространство имен определяется с помощью блока пространства имен, как показано на рисунке 2. В этом примере определяются два пространства имен: foo1 и foo2, каждое из которых содержит два имени, bar и baz (в данном случае это идентификаторы классов).
  foo1::bar b1;   // refers to bar class in foo1
foo2::bar b2;   // refers to bar class in foo2

Чтобы ссылаться на класс bar определенного пространства имен, идентификатор панели должен быть указан с помощью заданного идентификатора пространства имен.
      Также можно объявить, что вы используете определенное пространство имен в заданном исходном файле для удобства. Это делает указанное пространство имен одним из пространств имен по умолчанию для исходного файла. Тогда больше не нужно полностью квалифицировать определенные члены пространства имен, если, конечно, это не обязательно, чтобы избежать неоднозначности:
  using namespace foo1;
bar b1; // refers to bar class in foo1

      Как видите, синтаксис для определения и использования пространств имен в C++ прост и прост. C# работает практически так же с несколькими незначительными вариантами. Синтаксис пространств имен в Java несколько отличается, но концепция одинакова.
      Пространства имен используются во многих языках программирования, чтобы избежать конфликтов имен. Это именно тот тип решения, который необходим для выполнения спецификации XML 1.0.

Пространства имен в XML

      Многие разработчики считают, что спецификация XML 1.0 () была неполной,http://www.w3.org/TR/REC-xml так как она не предлагала поддержку пространства имен. В результате все имена, используемые в XML-документах, принадлежали к одному глобальному пространству имен, что затрудняет создание уникальных имен.
      Большинство разработчиков, включая самих авторов XML 1.0, знали, что в конечном итоге это вызовет слишком много неоднозначности в больших распределенных системах на основе XML. Например, рассмотрим следующий XML-документ:
  <student>
  <id>3235329</id>
  <name>Jeff Smith</name>
  <language>C#</language>
  <rating>9.5</rating>
</student>

В этом документе используется несколько имен, каждое из которых является обычным явлением. Элемент student моделирует учащегося курса обучения программному обеспечению. Элементы идентификатора, языка и рейтинга моделиируют номер записи базы данных учащегося, предпочитаемый язык программирования и оценку, которую учащийся дал курсу (из 10). Каждое из этих имен, безусловно, будет использоваться в других ситуациях, когда они не передают то же значение.
      Например, ниже приведен другой XML-документ, в котором те же имена используются совершенно по-другому:
  <student>
  <id>534-22-5252</id>
  <name>Jill Smith</name>
  <language>Spanish</language>
  <rating>3.2</rating>
</student>

В этом случае элемент учащегося моделирует учащегося начальной школы. Теперь элементы id, language и rating моделировают номер социального страхования ребенка, родной разговорный язык и текущее среднее балл учащегося (из 4) соответственно. Авторы этих двух документов могли бы использовать более длинные и менее распространенные имена, чтобы обеспечить уникальность, но в конечном итоге это не гарантирует уникальность в любом случае, и их труднее использовать.
      Хотя люди могут иметь возможность взглянуть на эти два документа и сказать разницу, они будут выглядеть точно так же, как часть программного обеспечения. Представьте, что вы отвечаете за создание приложения для управления учащимися, которое должно поддерживать множество различных XML-документов, связанных с учащимися, включая упомянутые. Когда вы пишете код, как вы собираетесь (программно) различать профессионального учащегося и учащегося начальной школы, или любой другой тип учащегося, если на то пошло? Нет надежного способа провести различие.
      Каждый раз, когда элементы и атрибуты из различных словарей XML используются в одном документе или приложении, возникают конфликты имен. Рассмотрим XSLT, который сам по себе является словарем XML для определения преобразований. В данном преобразовании можно выводить определяемые пользователем литеральные элементы. Таким образом, так как словарь XSLT содержит элемент с именем template, как можно было бы вывести определяемый пользователем литеральный элемент с именем template?
  <!-- this is the template element from XSLT -->
<template match="foo">
  <!-- I want to output this template element -->
  <template match="foo"/>
</template>

      Вероятность конфликтов имен становится весьма очевидной в таких языках, как XSLT и XML-схема, которые в значительной степени смешивают словари XML. Однако этих проблем можно было бы легко избежать, если XML обеспечивает поддержку пространств имен.
      Пространства имен в рекомендации XML — это решение W3C для проблем именования XML 1.0. Эта спецификация определяет, как расширить конкретный синтаксис XML 1.0 для поддержки пространств имен. Поскольку большинство разработчиков считают это дополнение фундаментальным и абсолютно необходимым, оно часто учитывается официальное добавление XML 1.0, даже если оно не является одним из них. На самом деле, сегодня многие разработчики отказываются ссылаться только на XML 1.0, а не на "XML 1.0 + пространства имен" по той же причине.
      Пространства имен в xml-рекомендации определяют синтаксис именования пространств имен XML, а также синтаксис для ссылки на что-либо в пространстве имен XML. Однако он не касается синтаксиса для определения того, что находится в пространстве имен XML. Это было оставлено на другую спецификацию, а именно XML-схему. Каждая из этих областей требует некоторого объяснения.

Именование пространств имен

      При определении пространства имен на языке программирования, таком как C++, существуют ограничения на символы, которые могут использоваться в имени. Идентификаторы пространства имен XML также должны соответствовать определенному синтаксису — синтаксису для ссылок на универсальный код ресурса (URI). Это означает, что идентификаторы пространства имен XML должны соответствовать универсальному синтаксису для URI, определенного в RFC 2396.
      URI определяется как компактная строка символов для идентификации абстрактного или физического ресурса. В большинстве случаев ссылки на URI используются для идентификации физических ресурсов (веб-страниц, скачиваемых файлов и т. д.), но в случае пространств имен XML ссылки на URI определяют абстрактные ресурсы, в частности пространства имен.
      Согласно спецификации URI, существует две общие формы URI: универсальные указатели ресурсов (URL-адрес) и универсальные имена ресурсов (URN). В качестве идентификатора пространства имен можно использовать любой тип URI. Ниже приведен пример двух URL-адресов, которые можно использовать в качестве идентификаторов пространства имен:
  http://www.develop.com/student
http://www.ed.gov/elementary/students

Ниже приведено несколько примеров URI, которые также можно использовать в качестве идентификаторов пространства имен:
  urn:www-develop-com:student
urn:www.ed.gov:elementary.students
urn:uuid:E7F73B13-05FE-44ec-81CE-F898C4A6CDB4

      Наиболее важным атрибутом идентификатора пространства имен является его уникальность. Авторы могут гарантировать уникальность URL-адреса, регистрируя доменное имя в интернет-органе именования. Затем автор обязан убедиться, что все строки, используемые после доменного имени, уникальны.
      URN работают так же. Ниже приведен основной синтаксис URN:
  urn:<namespace identifier>:<namespace specific string>

      Чтобы гарантировать уникальность URN, авторы должны снова зарегистрировать свой идентификатор пространства имен в интернет-центре именования. Затем автор отвечает за выполнение схемы создания уникальных строк, относящихся к пространству имен.
      Организации, определяющие пространства имен XML, должны разработать согласованную схему для создания новых имен пространств имен. Например, W3C постоянно определяет новые пространства имен XML. В них используется довольно интуитивно понятная эвристика, которая использует текущий год и название рабочей группы. На рисунке 3 показан шаблон, используемый W3C.

Рис. 3. Конструкции URI W3C
Рис. 3. Конструкции URI W3C

      По определению универсальный код ресурса (URI) уникален, поэтому нет необходимости добавлять дополнительные пространства имен поверх идентификаторов пространств имен XML. Пока автор пространства имен гарантирует уникальность идентификатора пространства имен, всегда можно однозначно идентифицировать что-то в XML с помощью только одного квалификатора пространства имен. Это значительно упрощает работу с пространствами имен в XML.
      Обработчики XML обрабатывают идентификаторы пространств имен как непрозрачные строки и никогда не как разрешаемые ресурсы. Повторимся: идентификаторы пространств имен — это просто строки! Два идентификатора пространства имен считаются идентичными, если они точно одинаковы— символ для символа.
      В конце концов, на самом деле не имеет значения, какой тип ссылки на URI вы решили использовать. Многие разработчики предпочитают использовать URL-адреса, так как их легче читать и запоминать, в то время как другие предпочитают URL-адреса из-за их гибкости.

Определение пространств имен

      В рекомендации по пространствам имен в XML не предусмотрен синтаксис для определения того, что находится в пространстве имен. Во многих ситуациях этот тип синтаксического определения даже не требуется. Сегодня большинство пространств имен XML определяются в официальных документах спецификаций, в которых описываются имена элементов и атрибуты, а также их семантика. Именно так формально определяются все пространства имен W3C (пример см. в спецификации http://www.w3.org/TR/xslt XSLT 1.0).
      После определения пространства имен разработчики программного обеспечения реализуют пространство имен, как описано в спецификации. Например, MSXML 3.0, Xalan и Saxon являются реализациями спецификации XSLT 1.0. Эти реализации жестко закодированы для поиска элементов, принадлежащих пространству имен XSLT 1.0 (http://www.w3.org/1999/XSL/Transform). Чтобы использовать эти реализации, необходимо передать им XML-документ, в котором правильно используются имена из пространства имен XSLT 1.0 (дополнительные сведения об этом см. в следующем разделе). Если что-либо в пространстве имен XSLT 1.0 изменится, необходимо обновить вспомогательное программное обеспечение.
      Рабочая группа схемы XML () вhttp://www.w3.org/XML/Schema настоящее время объединяет новую спецификацию (XML-схему), которая определяет синтаксис на основе XML для определения элементов, атрибутов и типов в пространстве имен. Наконец, xml-схема позволяет предоставить синтаксическое определение пространства имен, как показано на рисунке 4.
      В этом примере пространство http://www.develop.com/student имен определяется как содержащее четыре именованных элемента: student, id, name, language и rating. Помимо простого предоставления пространства имен, эта схема также предоставляет дополнительные метаданные, такие как порядок дочерних элементов учащегося, а также их типы.
      С помощью синтаксических определений пространства имен, таких как те, которые предлагаются в схеме XML, можно создать более сложное программное обеспечение, которое использует сведения об имени и типе во время выполнения. Xml-схемы по-прежнему не определяют семантику определенных элементов и атрибутов и поэтому по-прежнему требуют сопроводительной спецификации. В будущем большинство пространств имен XML будут определяться с помощью спецификаций и определений схем.

Использование пространств имен

      Я определяю использование пространства имен как процесс использования одного или нескольких элементов или атрибутов из заданного пространства имен в XML-документе. Для этого требуется понимание синтаксиса, описанного в рекомендации по пространствам имен в XML для определения имен элементов и атрибутов с идентификаторами пространства имен.
      Имена элементов и атрибутов можно квалифицировать с помощью префикса пространства имен. Префикс — это просто аббревиатура для идентификатора пространства имен (URI), который обычно довольно длинный. Префикс сначала сопоставляется с идентификатором пространства имен с помощью объявления пространства имен. Синтаксис объявления пространства имен:
  xmlns:<prefix>='<namespace identifier>'

      Объявление пространства имен выглядит так же, как атрибут (в элементе), но оно официально не считается атрибутами с точки зрения логической структуры документа (то есть они не будут отображаться в коллекции атрибутов элемента при использовании модели DOM).
      Префикс пространства имен считается область в элементе объявления, а также в любом из его потомков. После объявления префикс можно использовать перед любым элементом или именем атрибута, разделенным двоеточием (например, s:student). Это полное имя, включая префикс, называется полным именем (QName):
  QName = <prefix>:<local name>

Префикс связывает элемент или атрибут с идентификатором пространства имен, сопоставленным с префиксом в настоящее время в область.
      Предположим, что разработчик хочет использовать пространство имен XSLT 1.0. Ему потребуется предоставить объявление пространства имен, которое сопоставляет произвольный префикс с официальным идентификатором пространства имен XSLT 1.0 (http://www.w3.org/1999/XSL/Transform). Затем каждый элемент или атрибут, который разработчик хочет использовать из пространства имен XSLT 1.0, просто должен быть соответствующим префиксом, как показано в следующем примере:
  <x:transform version='1.0'
   xmlns:x='http://www.w3.org/1999/XSL/Transform'
>
   <x:template match='/'>
      <hello_world/>
   </x:template>
</x:transform>

      В предыдущем примере показан синтаксис для ссылки на элементы в пространстве имен. Каждый элемент с префиксом "x" относится к пространству http://www.w3.org/1999/XSL/Transform имен, а все элементы, не имеющие префикса, не из пространства имен (например, hello_world). Теперь процессоры могут различать конструкции программирования XSLT 1.0 и литеральные элементы, предназначенные для вывода, например hello_world. Если пространство имен XSLT 1.0 было написано одним символом, процессор XSLT 1.0 не сможет распознать документ как словарь, который он понимает.
      По сути, каждый элемент теперь имеет двухкомпонентное имя, идентификатор пространства имен и локальное имя. Сочетание этих двух имен часто называют именем пространства имен (примечание. Это отличается от QName, которое представляет собой сочетание префикса и локального имени).
      В качестве другого примера в следующем XML-документе показано, как использовать элементы из определения схемы XML, показанного ранее в этом столбце:
  <d:student xmlns:d='http://www.develop.com/student'>
  <d:id>3235329</d:id>
  <d:name>Jeff Smith</d:name>
  <d:language>C#</d:language>
  <d:rating>9.5</d:rating>
</d:student>

Обратите внимание, что независимо от того, как определены пространства имен, синтаксис ссылки на них одинаков.
      Когда в документах используются элементы или атрибуты из нескольких пространств имен, в данном элементе часто используется несколько объявлений пространств имен, как показано в следующем примере:
  <d:student xmlns:d='http://www.develop.com/student'
  xmlns:i='urn:schemas-develop-com:identifiers'
  xmlns:p='urn:schemas-develop-com:programming-languages'
>
  <i:id>3235329</i:id>
  <name>Jeff Smith</name>
  <p:language>C#</p:language>
  <d:rating>9.5</d:rating>
</d:student>

      Здесь учащийся и оценка относятся к одному и тому же пространству имен, а идентификатор и язык относятся к другому пространству имен, но имя не принадлежит пространству имен.
      Префиксы пространства имен также можно переопределить, переопределив префикс во вложенном область, как показано ниже:
  <d:student xmlns:d='http://www.develop.com/student'>
  <d:id>3235329</d:id>  
  <d:name xmlns:d='urn:names-r-us'>Jeff Smith</d:name>
  <d:language>C#</d:language>
  <d:rating>35</d:rating>
</d:student>

В этом примере все происходит из того же пространства имен, за исключением элемента name, который является из пространства имен urn:names-r-us. Хотя можно повторно объявить префикс пространства имен, отменить запрет на префикс пространства имен невозможно. Например, следующее является недопустимым:
  <d:student xmlns:d='http://www.develop.com/student'>
  <d:id xmlns:d=''>3235329</d:id>  
   •••
</d:student>

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

Пространства имен по умолчанию

      Существует еще один тип объявления пространства имен, который можно использовать для связывания идентификаторов пространств имен с именами элементов. Это называется объявлением пространства имен по умолчанию, в котором используется следующий синтаксис:
  xmlns='<namespace identifier>'

Обратите внимание, что префикс отсутствует. Если в элементе используется объявление пространства имен по умолчанию, все неквалифицированные имена элементов в его область автоматически связываются с указанным идентификатором пространства имен. Однако объявления пространства имен по умолчанию абсолютно не влияют на атрибуты. Единственный способ связать атрибут с идентификатором пространства имен — с помощью префикса.
      Рассмотрим следующий пример.
  <d:student  xmlns:d='http://www.develop.com/student'
     xmlns='urn:foo' id='3235329'
>
  <name>Jeff Smith</name>
  <language xmlns=''>C#</language>
  <rating>35</rating>
</d:student>

Здесь "student" — из http://www.develop.com/student пространства имен, а "name" и "rating" — из пространства имен по умолчанию urn:foo. Атрибут id не принадлежит пространству имен, так как атрибуты не связываются автоматически с идентификатором пространства имен по умолчанию.
      В этом примере также показано, что можно отменить включение пространства имен по умолчанию, просто задав для идентификатора пространства имен по умолчанию пустую строку, как показано в элементе language (помните, что это невозможно сделать с объявлениями префиксов). В результате элемент языка также не принадлежит к пространству имен.
      Синтаксис пространств имен по умолчанию был разработан для удобства, но он, как правило, вызывает больше путаницы, чем стоит. Путаница обычно связана с тем, что элементы и атрибуты обрабатываются по-разному, и не сразу видно, что вложенным элементам назначается идентификатор пространства имен по умолчанию. Тем не менее, в конце концов, выбор между префиксами и пространствами имен по умолчанию в основном является вопросом стиля, за исключением случаев, когда атрибуты вступают в игру.

Абстракции пространства имен

      Работать с пространствами имен из абстрактного представления XML-документа гораздо проще, чем с описанными лексическими проблемами. Набор xml-данных (набор сведений) определяет абстрактную структуру XML-документа, которая защищает разработчиков от сложностей базового формата сериализации, например описанного синтаксиса пространства имен.
      Согласно infoset, каждый элемент или атрибут имеет два свойства имени: идентификатор пространства имен и локальное имя. На рисунке 5 показана логическая структура XML-документа, содержащего имена с указанием пространства имен. Обратите внимание, что учащийся, идентификатор и язык находятся в одном пространстве имен, а оценки — из другого пространства имен, а имя не принадлежит пространству имен. Этот документ можно сериализовать с помощью любого из методов, описанных в предыдущем разделе.

Рис. 5. XML-документ с указанием пространства имен
Рис. 5. XML-документ с указанием пространства имен

      Рассмотрим, как современные основные API SAX и DOM реализуют эту абстрактную модель данных. SAX моделирует элементы с помощью вызовов методов startElement/endElement ContentHandler:
  public interface contentHandler
{
•••
void startElement(String namespaceURI, String localName, 
   String qName, Attributes atts) throws SAXException;
void endElement(String namespaceURI, String localName, 
   String qName) throws SAXException;
•••
}

      Обратите внимание, что элементы идентифицируются по сочетанию идентификатора пространства имен и локального имени (при необходимости — QName). Атрибуты также определяются с помощью набора методов, поддерживающих пространство имен, в интерфейсе Attributes. Средство синтаксического анализа SAX (или любое другое приложение производителя) должно предоставлять имена пространств имен при доставке потока документов. Однако при использовании SAX можно легко различать различные типы элементов учащихся программным способом (см . рис. 6).
      Так как имя пространства имен (идентификатор пространства имен + локальное имя) автоматически разрешается с помощью средства синтаксического анализа SAX, не имеет значения, какой префикс (если таковой имеется) использовался для определенного элемента или атрибута в исходном документе— это в основном сведения о сериализации. Это не означает, однако, что префиксы могут быть выброшены после анализа. Рассмотрим следующий XML-документ:
  <student xmlns:xsd='http://www.w3.org/2000/10/XMLSchema'
 xmlns:xsi='http://www.w3.org/2000/10/XMLSchema-instance'
>
  <age xsi:type='xsd:double'>35.0</age>
</student>

Обратите внимание, что атрибут xsi:type XML-схемы для age содержит значение QName. Каждый раз, когда QName используется в содержимом элемента или атрибута, используемое приложение должно работать с ним вручную. Единственным способом правильной интерпретации этого значения приложением является то, к чему привязан идентификатор пространства имен xsd. По этой причине infoset также поддерживает набор область объявлений пространства имен для каждого элемента в документе. SAX моделирует эти сведения с помощью вызовов методов startPrefixMapping и endPrefixMapping.
      API DOM является еще одной реализацией Infoset. Интерфейс Node моделирует базовое удостоверение узлов элемента или атрибута с помощью двух свойств имен: namespaceURI и localName. Он также моделирует QName узла и префикс с помощью свойств nodeName и prefix. Код языка Java на рисунке 7 показывает, как можно различать два разных элемента учащихся с помощью модели DOM.
      Как и в случае с SAX, средство синтаксического анализа XML, которое создает дерево DOM, отвечает за правильное заполнение свойств пространства имен. Таким образом, не имеет значения, как пространства имен были объявлены в исходном документе после работы со структурой логического документа. Если вы создаете документ с помощью API DOM, вы отвечаете за предоставление идентификаторов пространства имен для каждого элемента и атрибута после создания:
  void generateStudentDocument(Document doc)
{
   Node docEl = doc.createElementNS("urn:dm:student", "student");
   doc.appendChild(docEl);
   Node n = doc.createElementNS("", "name");
   docEl.appendChild(n);
   •••
}

      Как видите, этот код позволяет создавать логическую структуру напрямую. Затем реализация DOM позволяет выяснить, как сериализовать объявления пространства имен в базовый документ XML 1.0. Это конкретное дерево DOM можно сериализовать следующим образом:
  <student xmlns='urn:dm:student'>
   <name xmlns=''/>
</student>

      При работе с абстрактным представлением XML-документа (с помощью API SAX/DOM) важно отметить, что не существует понятия пространства имен по умолчанию. В приведенном выше примере после вызова createElementNS для "student" urn:dm:student не стал пространством имен по умолчанию. Вызов createElementNS для имени без пространства имен, которому элементу name назначен пустой идентификатор пространства имен (не urn:dm:student). То же самое относится к SAX в отношении последовательности вызовов методов startElement/endElement. Каждый узел элемента или атрибута всегда обрабатывается независимо относительно сведений об имени.
      XPath — это еще одна спецификация XML, которая определяет способ идентификации узлов в структуре абстрактного документа. Выражения XPath позволяют идентифицировать элементы и атрибуты по именам, полным пространства имен. Так как тесты имен XPath являются простыми строковыми выражениями, единственный способ связать тест имени XPath с идентификатором пространства имен — использовать префикс пространства имен.
      Тесты узлов XPath можно считать типом QName. Это означает, что если тест узла не содержит префикс, это похоже на запрос заданного имени, которое принадлежит к "no namespace". Например, возьмем следующее выражение XPath:
  /student/name

Это выражение идентифицирует все элементы имен, не принадлежащие ни одному пространству имен, которые являются дочерними элементами корневого элемента учащегося, который не принадлежит ни к одному пространству имен. Чтобы определить элементы student и name, принадлежащие пространству имен urn:dm:student, сначала необходимо связать префикс пространства имен с urn:dm:student. Затем этот префикс можно использовать в выражении XPath.
      Предполагая, что "dm" связан с urn:dm:student в контексте XPath, следующее выражение теперь будет определять элементы имен, принадлежащие пространству имен urn:dm:store, которые являются дочерними элементами корневого элемента student, также принадлежащими пространству имен urn:dm:store:
  /dm:student/dm:name

Если запрашиваемый документ был похож на приведенный ниже код, то предыдущее выражение определит все три элемента имен, которые являются дочерними элементами учащегося, независимо от их префиксов, так как все они находятся в одном и том же пространстве имен.
  <s:student xmlns:s='urn:dm:student'>
   <s:name/>
   <n:name xmlns:n='urn:dm:student'/>
   <s:name/>
</s:student>

      Префиксы сопоставляются в контексте XPath в зависимости от реализации (дополнительные сведения о том, как это работает в MSXML 3.0, см. в столбце За май 2001 г.). Одним из примеров этого является XSLT, который предоставляет контекст для использования выражений XPath. Для использования выражений XPath с указанием пространства имен в документе XSLT можно использовать стандартное объявление пространства имен для сопоставления идентификатора целевого пространства имен с произвольным префиксом:
  <x:transform version='1.0'
   xmlns:x='http://www.w3.org/1999/XSL/Transform'
   xmlns:d='urn:dm:student'
>
   <x:template match='d:student'>
     <!-- transform student here -->
     <x:apply-templates select='d:name'/>
   </x:template>
   •••
</x:transform>

Обратите внимание, что первый шаблон соответствует элементу student из пространства имен urn:dm:student. Если бы значение совпадения было просто "student", оно сопоставляло бы только элементы student без пространства имен. Затем элемент apply-templates обрабатывает все дочерние элементы имен, которые также являются пространством имен urn:dm:student.
      Как видите, понимание того, как пространства имен работают как лексически, так и абстрактно, имеет решающее значение для понимания всего семейства спецификаций XML. Вы столкнетесь с множеством ситуаций, похожих на эти, разбросанных по новым спецификациям XML.

Резюме

      Пространство имен — это набор имен, в котором все имена уникальны. Пространства имен в XML позволяют присваивать элементам и атрибутам уникальные имена. Хотя пространства имен, как правило, являются источником много путаницы, их легко понять, как только вы ознакомитесь с тем, как они определены и используются как синтаксически, так и абстрактно. Дополнительные сведения о пространствах имен см. в рекомендациях по пространствам имен в XML по адресу http://www.w3.org/TR/REC-xml-names, в разделе Часто задаваемые вопросы о пространствах имен от Рональда Буррета в http://www.rpbourret.com/xml/NamespacesFAQ.htm и http://www.jclark.com/xml/xmlns.htm .http://www.xml.com/pub/1999/01/namespaces.html


Отправьте вопросы и комментарии для Аарона по .xmlfiles@microsoft.com
Аарон Сконнард является инструктором и исследователем в DevelopMentor, где он разрабатывает учебную программу XML. Аарон соавтором Essential XML (Addison-Wesley Longman, 2000) и написал Essential WinInet (Addison-Wesley Longman, 1998). Свяжитесь с Аароном по адресу http://staff.develop.com/aarons.