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

Я пытаюсь понять, как пространства имен работают в XML. Когда у меня есть такой элемент, как foo: bar, у атрибутов часто не будет пространств имен. Но иногда они будут. Находятся ли атрибуты в пространстве имен элемента, даже если было объявлено пространство имен по умолчанию? Просматривая xsd для xhtml, кажется, что атрибуты являются частью схемы и должны находиться в пространстве имен для xhtml, но они никогда не представляются таким образом...

4 ответа

В большинстве случаев атрибуты не будут находиться ни в одном пространстве имен. Спецификация пространства имен говорит (выделено мое):

Объявление пространства имен по умолчанию применяется ко всем нефиксированным именам элементов в пределах его области. Объявления пространства имен по умолчанию не применяются непосредственно к именам атрибутов; Интерпретация нефиксированных атрибутов определяется элементом, на котором они появляются.

Есть причина, по которой большинство словарей XML используют атрибуты без пространств имен:
Если у ваших элементов есть пространство имен, а эти элементы имеют атрибуты, тогда не должно быть путаницы: атрибуты принадлежат вашему элементу, который принадлежит вашему пространству имен. Добавление префикса пространства имен к атрибутам сделает все более многословным.

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

Наконец, W3C XML Schema имеет слишком простой способ (<schema attributeFormDefault="qualified">) объявления ваших атрибутов как находящихся в пространстве имен, вынуждая вас префиксировать их в ваших документах, даже если вы используете пространство имен по умолчанию.

Примеры для иллюстрации с использованием нотации Clark, где префикс пространства имен заменяется URL-адресом пространства имен в фигурных скобках:

<bar xmlns:foo="http://www.foo.com/"
    foo:baz="baz"
    qux="qux"/>
<bar xmlns="http://www.foo.com/" xmlns:foo="http://www.foo.com/"
    foo:baz="baz"
    qux="qux"/>
<foo:bar xmlns="http://www.foo.com/" xmlns:foo="http://www.foo.com/"
    foo:baz="baz"
    qux="qux"/>

является

<{}bar
    {http://www.foo.com/}baz="baz"
    {}qux="qux"/>
<{http://www.foo.com/}bar
    {http://www.foo.com/}baz="baz"
    {}qux="qux"/>
<{http://www.foo.com/}bar
    {http://www.foo.com/}baz="baz"
    {}qux="qux"/>

Есть кое-что, связанное с этим атрибутом / предметным пространством имен, которое мне понадобилось некоторое время, чтобы понять сегодня, когда я работал над XSD. Я поделюсь с вами этим опытом на случай, если у кого-нибудь возникнут те же проблемы.

В Документе Схемы, над которым я работал, было несколько глобальных атрибутов, на которые ссылались некоторые элементы. Для упрощения здесь давайте предположим, что этот XSD, о котором я говорю, был о клиенте.

Давайте назовем один из этих глобальных атрибутов Id. И корневой элемент с его помощью клиента

Моя XSD-декларация выглядела так:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema  xmlns="http://schemas.mycompany.com/Customer/V1" 
targetNamespace="http://schemas.mycompany.com/Customer/V1" 
xmlns:xs="http://www.w3.org/2001/XMLSchema">

Моя декларация атрибута Id выглядела так:

<xs:attribute name="Id" type="xs:positiveInteger"/>

И мой элемент Customer использовал атрибут следующим образом:

<xs:element name="Customer">
   <xs:complexType>
      <xs:attribute ref="Id" use="required"/>
      <!-- some elements here -->
    </xs:complexType>
</xs:element>

Теперь, допустим, я хотел объявить XML-документ Customer следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<Customer Id="1" xmlns="http://schemas.mycompany.com/Customer/V1">
  <!-- ... other elements here -->
</Customer>

Я обнаружил, что не могу: когда атрибут объявлен глобально, он не находится в том же пространстве имен, что и элемент, который на него ссылается.

Я выяснил, что единственное решение с таким определенным XSD - это объявление пространства имен дважды: один раз без префикса, чтобы сделать его пространством имен по умолчанию для элементов, и один раз с префиксом, чтобы использовать его с атрибутами. Вот как это выглядело бы:

<?xml version="1.0" encoding="utf-8"?>
<Customer cus:Id="1" xmlns="http://schemas.mycompany.com/Customer/V1"
 xmlns:cus="http://schemas.mycompany.com/Customer/V1">
  <!-- ... other elements here -->
</Customer>

Это настолько непрактично, что я просто решил избавиться от всех глобальных атрибутов и объявить их локально. Что в случае с примером, который я привел здесь, выглядело бы так:

<xs:element name="Customer">
   <xs:complexType>
       <xs:attribute name="Id" type="xs:positiveInteger" use="required"/>
       <!-- some elements here -->
   </xs:complexType>
</xs:element>

Мне было трудно найти ссылки на то, о чем я говорю, здесь, в сети. В конце концов я нашел этот пост на форуме Stylus XSD, где парень по имени Стин Леманн предложил либо объявить атрибут локально, либо объявить его в группе атрибутов.

"так что само объявление атрибута больше не является глобальным"

Это последнее решение имеет "хакерский" вкус, поэтому я просто решил придерживаться первого решения и объявить все свои атрибуты локально.

Читайте в разделе 6.1. Определение пространства имен и 6.2 По умолчанию в пространстве имен на w3c.

В принципе:

Область объявления пространства имен, объявляющего префикс, простирается от начала начального тега, в котором он появляется, до конца соответствующего конечного тега

Тем не менее, текст здесь, кажется, не объясняет, означает ли a a foo: a или пространство имен по умолчанию в контексте. Я бы предположил, что это не относится к foo: a, а скорее к пространству имен документов по умолчанию a. Учитывая эту цитату как минимум:

Такое объявление пространства имен применяется ко всем именам элементов и атрибутов в пределах его области действия, префикс которых совпадает с указанным в объявлении.

То есть. пространство имен "foo:" применяется только к элементам с префиксом foo:

Другие вопросы по тегам