Spec-Zone.ru › SVG

Краткий курс по пространствам имён

Будучи диалектом XML, SVG использует пространства имён. Если вы планируете создавать содержимое SVG, важно понимать концепцию пространств имён и то, как они используются. Пространства имён необходимы пользовательским агентам, поддерживающим несколько диалектов XML; браузеры должны строго соблюдать соответствующие правила. Если сейчас уделить время изучению пространств имён, это избавит вас от проблем в будущем.

Предыстория

Давняя цель различных спецификаций W3C — сделать возможным смешивание разных типов содержимого на основе XML в одном и том же файле XML или HTML. Например, SVG и MathML можно встроить непосредственно в научный документ на основе HTML. Возможность смешивать такие типы содержимого имеет множество преимуществ, но для этого также требовалось решить вполне реальную проблему.

Естественно, каждый диалект XML определяет значение имён элементов разметки, описанных в его спецификации. Проблема смешивания содержимого разных диалектов XML в одном документе заключается в том, что элементы, определённые одним диалектом, могут иметь те же имена, что и элементы, определённые другим. Например, и в HTML, и в SVG есть элемент <title>. Как пользовательскому агенту различить их? Как стилям CSS различать их? И вообще, как пользовательский агент понимает, что содержимое ему известно, а не является просто бессмысленным неопределённым пользовательским элементом HTML или XML-файлом со случайными именами элементов, которые ему неизвестны?

Вопреки распространённому мнению, ответ на этот вопрос — не «он может определить это по объявлению DOCTYPE». DTD никогда не разрабатывались с расчётом на смешанное содержимое, и прежние попытки создать DTD для смешанного содержимого теперь считаются неудачными. Для XML и некоторых диалектов XML (включая SVG и HTML) объявление DOCTYPE не обязательно. В SVG 1.2 его даже нет. Тот факт, что объявления DOCTYPE (как правило) соответствуют содержимому в файлах с одним типом содержимого, — лишь совпадение. DTD предназначены только для проверки, а не для идентификации содержимого. Любой пользовательский агент, который определяет содержимое XML по объявлению DOCTYPE, ненадёжен.

На самом деле XML-содержимое сообщает пользовательскому агенту, к какому диалекту относятся имена элементов, с помощью явных «объявлений пространства имён».

Объявление пространств имён

Как выглядят такие объявления пространств имён и где их указывать? Вот короткий пример.

<svg xmlns="http://www.w3.org/2000/svg">
  <!-- more tags here -->
</svg>

Объявление пространства имён задаётся параметром xmlns. Этот параметр указывает, что элемент <svg> и его дочерние элементы принадлежат диалекту XML с именем пространства имён http://www.w3.org/2000/svg, то есть, конечно же, SVG. Обратите внимание, что объявление пространства имён указывается только один раз для корневого элемента (и подразумевается, если оно опущено). Это объявление задаёт пространство имён по умолчанию, поэтому пользовательский агент знает, что все потомки элемента <svg> также принадлежат тому же пространству имён. Пользовательские агенты проверяют, известно ли им имя пространства имён, чтобы определить, умеют ли они обрабатывать эту разметку.

Обратите внимание, что имена пространств имён — это просто строки, поэтому не имеет значения, что имя пространства имён SVG также выглядит как URI. URI обычно используют, поскольку они уникальны, но цель состоит не в том, чтобы куда-либо «перейти по ссылке». (На самом деле URI используются настолько часто, что вместо «имени пространства имён» обычно говорят «URI пространства имён».)

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

Если все потомки корневого элемента также объявлены принадлежащими пространству имён по умолчанию, как добавить содержимое из другого пространства имён? Чтобы включить пространство имён SVG в HTML, нужно добавить <svg>. В XML пространство имён объявляется. Вот короткий пример.

<report xmlns="https://www.acme.org/reports">
  <title>Some stats</title>
  <summary>...</summary>
  <statTable xmlns="https://www.acme.org/tables">
    <content>...</content>
    <!-- redeclaring root's default namespace -->
    <summary xmlns="https://www.acme.org/reports">...</summary>
  </statTable>
</report>

В этом примере атрибут xmlns корневого элемента <report> объявляет пространством имён по умолчанию https://www.acme.org/reports, или reports. В результате пользовательский агент интерпретирует его и все его дочерние элементы как принадлежащие reports, за исключением элемента <content>, который находится в пространстве имён https://www.acme.org/tables, или tables. У элемента <summary> есть собственный параметр xmlns, и повторное объявление пространства имён reports сообщает пользовательскому агенту, что элемент <summary> и его потомки (если только они также не объявят другое пространство имён) принадлежат reports.

В HTML пространство имён http://www.w3.org/1999/xhtml подразумевается. В SVG это http://www.w3.org/2000/svg. Для MathML — http://www.w3.org/1998/Math/MathML.

Объявление префиксов пространств имён

Диалекты XML определяют не только собственные элементы, но и собственные параметры.

По умолчанию параметры вообще не имеют пространства имён. Известно лишь, что они уникальны, поскольку присутствуют у элемента, который сам имеет уникальное имя. Однако иногда необходимо определять параметры так, чтобы их можно было повторно использовать у разных элементов и при этом считать одним и тем же параметром независимо от элемента, у которого они используются. Отличный пример — параметр href, определённый спецификацией XLink. Этот параметр часто используется другими диалектами XML для создания ссылок на внешние ресурсы. Но как сообщить пользовательскому агенту, к какому диалекту относится параметр, в данном случае XLink? Рассмотрим следующий пример.

<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink">
  <script xlink:href="cool-script.js" type="text/javascript" />
</svg>

В этом примере используется довольно необычно выглядящий параметр xmlns:xlink. Как можно догадаться по первой части xmlns, это ещё одно объявление пространства имён. Однако вместо установки пространства имён по умолчанию оно задаёт пространство имён для так называемого «префикса пространства имён». В данном случае мы выбрали префикс xlink (вторая часть), поскольку он будет использоваться для сообщения пользовательскому агенту об атрибутах, принадлежащих XLink.

Как следует из названия, префиксы пространств имён используются в качестве префиксов имён параметров и элементов. Для этого перед именем параметра ставят префикс пространства имён и двоеточие, как показано для элемента <script> в примере выше. Это сообщает пользовательскому агенту, что конкретный параметр принадлежит пространству имён, назначенному этому префиксу (XLink), и может использоваться у других элементов с тем же значением.

Обратите внимание, что в XML использование префикса, не связанного с именем пространства имён, считается ошибкой XML. Связь, созданная параметром xmlns:xlink в примере выше, необходима, чтобы параметр xlink:href не вызывал ошибку. Этот параметр XLink также часто используется в SVG, в частности, у элементов <a>, <use> и <image>, поэтому рекомендуется всегда включать объявление XLink в документы.

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

<html
  lang="en"
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:svg="http://www.w3.org/2000/svg">
  <body>
    <h1>SVG embedded inline in XHTML</h1>
    <svg:svg width="300px" height="200px">
      <svg:circle cx="150" cy="100" r="50" fill="red" />
    </svg:svg>
  </body>
</html>

Примечание: Это файл XHTML, а не HTML. Пространства имён XML недопустимы в HTML. Чтобы проверить этот пример, сохраните файл как .xhtml.

Обратите внимание: поскольку для элемента <svg:svg> и его дочернего элемента <svg:circle> используется префикс пространства имён, повторно объявлять пространство имён по умолчанию не требовалось. В целом лучше повторно объявить пространство имён по умолчанию, чем добавлять префиксы ко множеству элементов таким образом.

Скрипты в XML с пространствами имён

Пространства имён влияют на разметку и скрипты (и даже на CSS). Если вы пишете скрипты для XML с пространствами имён, например SVG, читайте дальше.

Рекомендация DOM Level 1 была создана до публикации рекомендации Namespaces in XML; поэтому DOM1 не поддерживает пространства имён. Это вызывает проблемы при работе с XML, использующим пространства имён, например SVG. Чтобы решить эти проблемы, в DOM Level 2 Core добавили аналоги всех применимых методов DOM Level 1 с поддержкой пространств имён. При работе со скриптами SVG важно использовать методы с поддержкой пространств имён. В таблице ниже перечислены методы DOM1, которые не следует использовать в SVG, и соответствующие методы DOM2, которые следует использовать вместо них.

DOM1 (не использовать) DOM2 (используйте эти методы!)
createAttribute() createAttributeNS()
createElement() createElementNS()
getAttributeNode() getAttributeNodeNS()
getAttribute() getAttributeNS()
getElementsByTagName() getElementsByTagNameNS() (также добавлен в Element)
getNamedItem() getNamedItemNS()
hasAttribute() hasAttributeNS()
removeAttribute() removeAttributeNS()
removeNamedItem() removeNamedItemNS()
setAttribute() setAttributeNS()
setAttributeNode() setAttributeNodeNS()
setNamedItem() setNamedItemNS()

Первым параметром всех методов DOM2 с поддержкой пространств имён должно быть имя пространства имён (также известное как URI пространства имён) соответствующего элемента или параметра. Для элементов SVG это http://www.w3.org/2000/svg. Однако обратите особое внимание: рекомендация Namespaces in XML 1.1 указывает, что имя пространства имён для параметров без префикса не имеет значения. Иными словами, хотя параметры принадлежат пространству имён элемента, нельзя использовать имя пространства имён тега. Вместо этого для параметров без префикса необходимо использовать null в качестве имени пространства имён. Поэтому для создания элемента SVG rect с помощью document.createElementNS() нужно написать:

document.createElementNS("http://www.w3.org/2000/svg", "rect");

А чтобы получить значение параметра x элемента SVG rect, нужно написать:

rect.getAttributeNS(null, "x");

Обратите внимание, что для параметров с префиксом пространства имён это правило не действует (такие параметры не принадлежат тому же диалекту XML, что и элемент). Для параметров, таких как xlink:href, требуется имя пространства имён, назначенное этому префиксу (для XLink это http://www.w3.org/1999/xlink). Поэтому, чтобы получить значение параметра xlink:href элемента <a> в SVG, нужно написать:

elt.getAttributeNS("http://www.w3.org/1999/xlink", "href");

При установке параметров, принадлежащих пространству имён, рекомендуется (но не обязательно) также включать их префикс во второй параметр, чтобы впоследствии DOM можно было проще преобразовать обратно в XML (например, если нужно отправить его обратно на сервер). Например:

elt.setAttributeNS(
  "http://www.w3.org/1999/xlink",
  "xlink:href",
  "other-doc.svg",
);

И наконец, вот пример того, как можно динамически создать элемент <image> с помощью JavaScript:

const SVG_NS = "http://www.w3.org/2000/svg";
const XLink_NS = "http://www.w3.org/1999/xlink";
const image = document.createElementNS(SVG_NS, "image");
image.setAttributeNS(null, "width", "100");
image.setAttributeNS(null, "height", "100");
image.setAttributeNS(XLink_NS, "xlink:href", "flower.png");

Заключение

Для SVG, HTML и MathML пространство имён подразумевается и потому является необязательным. В XML-файлах пространство имён необходимо объявлять. Если этого не сделать, пользовательские агенты не распознают содержимое и отобразят разметку XML либо сообщат пользователю об ошибке в XML.

При создании SVG полезно использовать шаблон, содержащий все часто используемые объявления пространств имён. Если у вас ещё нет такого шаблона, создайте его, начав со следующего кода:

<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"></svg>

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

Полный пример

Полный пример см. в разделе SVG: краткий курс по пространствам имён: пример.

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/Namespaces_crash_course

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API