Я пытаюсь понять, как пространства имен работают в XML. Когда у меня есть элемент типа foo: bar, атрибуты часто не будут иметь пространства имен на них. Но иногда они будут. Является ли атрибут в пространстве имен элемента, даже если объявлено пространство имен по умолчанию? Оглядываясь на xsd для xhtml, кажется, что атрибуты являются частью схемы и должны находиться в пространстве имен для xhtml, но они никогда не представлены таким образом...
Пространства имен XML и атрибуты
Ответ 1
В большинстве случаев атрибуты не будут находиться в каком-либо пространстве имен. пространство имен говорит (внимание мое):
Объявление пространства имен по умолчанию применяется ко всем именам неповрежденных элементов в пределах области действия. Декларации пространства имен по умолчанию не применяются непосредственно к именам атрибутов; интерпретация неподписанных атрибутов определяется элементом, на котором они появляются.
Есть причина, по которой большинство словарей XML используют атрибуты, отличные от имен:
Когда ваши элементы имеют пространство имен, и эти элементы имеют атрибуты, тогда не может быть путаницы: атрибуты принадлежат вашему элементу, принадлежащему вашему пространству имен. Добавление префикса пространства имен к атрибутам просто сделает все более подробным.
Итак, почему существуют атрибуты с расширением имен?
Потому что некоторые словари полезны для работы с большей частью атрибутами и могут делать это, когда смешиваются с другими словарями. Наиболее известным примером является XLink.
Наконец, W3C XML Schema имеет слишком простой способ (<schema attributeFormDefault="qualified">
) объявить ваши атрибуты как находящиеся в пространстве имен, заставляя их префикс их в ваших документах, даже если вы используете пространство имен по умолчанию.
Ответ 2
Примеры, иллюстрирующие использование обозначение Кларка, где префикс пространства имен заменяется 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"/>
Ответ 3
Там что-то связанное с этим атрибутом/пространством имен, которое заняло у меня некоторое время, чтобы понять сегодня, когда я работал над XSD. Я собираюсь поделиться этим опытом с вами, если у кого-нибудь случится одинаковые проблемы.
В документе схемы я работал над несколькими глобальными атрибутами, на которые ссылаются некоторые элементы. Чтобы упростить ситуацию, позвольте предположить, что XSD, о котором я говорю, касался Customer.
Позвольте назвать один из этих глобальных атрибутов 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">
Объявление атрибута My Id выглядело следующим образом:
<xs:attribute name="Id" type="xs:positiveInteger"/>
И мой элемент Клиент использовал атрибут следующим образом:
<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, где парень по имени Стин Леманн предложил либо объявить атрибут локально, либо объявить его в группе атрибутов
", чтобы объявление атрибута сам уже не является глобальным"
Это последнее решение имеет "хакерский" вкус, поэтому я просто решил придерживаться первого решения и объявить все свои атрибуты локально.
Ответ 4
Читайте в 6.1 Область видимости пространства имен и 6.2 Пространство имен По умолчанию на w3c.
В принципе:
Область описания пространства имен, объявляющая префикс, продолжается от начала начального тега, в котором он отображается в конце соответствующего конечного тега
Однако текст здесь, похоже, не объясняет, означает ли это a foo: a или пространство имен по умолчанию в контексте. Я бы предположил, что это не относится к foo: a, а скорее к пространству имен по умолчанию a. Учитывая эту цитату как минимум:
Такое объявление пространства имен применяется ко всем именам элементов и атрибутов в пределах своей области, префикс которых соответствует указанному в объявлении.
Т.е. пространство имен "foo:" применяется только к элементам с префиксом foo: