SVG 命名空间(xmlns、xmlns:xlink、xmlns:svg)

简介: SVG 命名空间(xmlns、xmlns:xlink、xmlns:svg)

本文来自 SVG Namespaces Docs,有疑问请看原版,原版中英混搭。

一、简介

作为 XML 的一个方言,SVG 需要在一个命名空间内(is namespaced)。理解命名空间的概念,以及在你打算编辑SVG内容时,命名空间如何使用,是很重要的。SVG查看器的版本早于Firefox 1.5的发布的,都几乎没有注意命名空间的问题, but they are essential to multi-XML dialect supporting user agents such as Gecko-based browsers which must be very strict. 现在,花一点时间来理解命名空间,这会让你以后避免各种麻烦。

二、背景

W3C的长期目标是使不同类型的XML基本内容可以混合在同一个XML文件中。例如, SVG 和 MathML 可以直接并入基于XHTML的科学文档中。 能够混合这样的内容类型有很多优点,但也需要解决一个非常实际的问题。

合理来说, 每个XML语言定义其规范中描述的标记标签名称的含义。 在单个XML文档中混合来自不同XML方言的内容的问题是,由一个方言定义的标签可能与另一个方言定义的标签具有相同的名称。例如,XHTML和SVG都有一个

与大众想法相反, 这个问题的答案不是“可以从DOCTYPE声明中得知”。DTDs的设计不考虑混合内容,而过去尝试创建混合内容的DTDs现在被认为是失败的。XML和一些XML方言 (包括SVG), 不要求DOCTYPE 声明,SVG 1.2 更不会有。DOCTYPE声明(通常)与单个内容类型文件中的内容匹配的事实只是巧合的。DTDs仅用于验证,而不是内容的识别。使用其DOCTYPE声明欺骗和标识XML内容的使用者会造成危害(User agents that cheat and identify XML content using its DOCTYPE declaration cause harm)。

问题的真正答案是,XML内容通过给明确的标签显示“命名空间声明”来告诉使用者哪个方言标签名称属于哪个。

三、声明命名空间

所以这些命名空间声明是什么样的呢,并且在什么地方用他们,如下的例子所示:

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

命名空间声明是通过 xmlns attribute 提供的。xmlns 属性意味着这个

请注意,命名空间仅仅只是一些字符串,所以SVG上那些看起来像URI的命名空间并不重要。因为URIs的唯一性从而被广泛使用,它的本意并不是要“链接”到某个地址。(实际上URIs被如此频繁地使用是“命名空间 URI"普遍使用而不是”命名空间的名字“被使用。)

四、重新定义默认命名空间

如果根节点的所有子节点也被定义为默认命名空间,那么你如何混合使用另一种命名空间呢?很简单,你仅仅只需重新定义默认命名空间即可。这里是一个简单的例子。

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    <!-- 在这里放置一些 XHTML 标签 -->
    <svg xmlns="http://www.w3.org/2000/svg" width="300px" height="200px">
      <!-- 在这里放置一些 SVG 标签 -->
    </svg>
    <!-- 在这里放置一些 XHTML 标签 -->
  </body>
</html>

在这个例子中根节点<html>xmlns 属性定义了XHTML为默认命名空间。结果就是它和它所有的子节标签,除了 <svg> 标签,都被用户代理解释为属于XHTML命名空间。 <svg> 标签拥有它自己的xmlns属性,通过重新定义默认的命名空间,告诉用户代理 <svg> 标签以及他所包含的标签(除非他们也重新定义了默认名称空间)属于SVG.

看到没,命名空间其实没有那么难以理解。

五、声明命名空间前缀

XML 方言不仅定义了自己的标签,还定义了自己的属性。默认情况下,属性根本没有命名空间,并且只知道它们是唯一的,因为它们出现在本身具有唯一名称的元素上。但是,有时需要定义属性,以便它们可以在许多不同的元素上重用,并且仍然被视为相同的属性,而与使用它们的元素无关。hrefXLink 规范定义的属性就是一个很好的例子。此属性通常被其他 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/ecmascript"/>
</svg>

这个例子具有相当不寻常的外观属性xmlns:xlink。正如您可能从第一个 ‘xmlns’ 部分猜到的,这是另一个命名空间声明。然而,这个命名空间声明不是设置默认命名空间,而是为称为“命名空间前缀”的东西设置命名空间。在这种情况下,我们选择使用前缀xlink(第二部分),因为前缀将用于告诉用户代理属于 XLink 的属性。

顾名思义,命名空间前缀用于作为属性名称和标签名称的前缀。这是通过在属性名称之前放置命名空间前缀和冒号来完成的,如上例中的<script>标记所示。这告诉用户代理该特定属性属于分配给命名空间前缀 (XLink) 的命名空间,并且是一个可以在其他标签上具有相同含义的属性。

请注意,使用尚未绑定到命名空间名称的前缀是 XML 错误。xmlns:xlink如果xlink:href属性不会导致错误,则由上面示例中的属性创建的绑定是绝对必要的。此 XLink 属性也经常用于 SVG 中的<a><use><image>标签等,因此始终在文档中包含 XLink 声明是个好主意。

顺便说一句,了解命名空间前缀也可用于标记名称是很有用的。这告诉用户代理该特定标签(但这次不是它的子标签!)属于分配给前缀的命名空间。如果您在以下示例中遇到这样的标记,知道这一点将节省您的一些困惑:

<html 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="#ff0000"/>
    </svg:svg>
  </body>
</html>

请注意,因为名称空间前缀用于<svg:svg>标记及其子项<svg:circle>,所以没有必要重新声明默认名称空间。一般来说,虽然最好重新声明默认命名空间,而不是以这种方式为大量标签添加前缀。

六、在命名空间的 XML 中编写脚本

命名空间不仅会影响标记,还会影响脚本。如果您为命名空间的 XML(例如 SVG)编写脚本,请继续阅读。

DOM 级别 1 推荐是在 XML 中的原始命名空间推荐已发布;因此,DOM1 不知道命名空间。这会导致命名空间 XML(如 SVG)出现问题。为了解决这些问题,DOM 级别 2 核心添加了所有适用的 DOM 级别 1 方法的命名空间感知等价物。在编写 SVG 脚本时,使用命名空间感知方法很重要. 下表列出了不应在 SVG 中使用的 DOM1 方法,以及应使用的等效 DOM2 对应方法。

所有 DOM2 命名空间感知方法的第一个参数必须是相关元素或属性的命名空间名称(也称为命名空间 URI)。对于 SVG元素, 这是’http://www.w3.org/2000/svg’。但是,请注意:XML 1.1 中的命名空间建议指出没有前缀的属性的命名空间名称没有值。换句话说,虽然属性属于标签的命名空间,但你并没有使用标签的命名空间名称。相反,您必须使用 null 作为非限定(无前缀)属性的命名空间名称。因此,要使用来创建 SVGrect元素document.createElementNS(),您必须编写:

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

但是要检索SVG元素上的x属性rect,您必须编写:

rect.getAttributeNS(null, 'x');

请注意,对于具有命名空间前缀的属性(不属于与标记相同的 XML 方言的属性),情况并非如此。诸如属性之类的xlink:href属性需要分配给该前缀的命名空间名称(对于 XLink ,为http://www.w3.org/1999/xlink)。因此,要获取SVG 中元素的xlink:href属性值,<a>您可以编写:

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

对于设置具有命名空间的属性,建议(但不是必需的)您还将它们的前缀包含在第二个参数中,以便稍后可以更轻松地将 DOM 转换回 XML(例如,如果您想将其发送回服务器)。例如:

elt.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'otherdoc.svg');

作为最后一个示例,这里演示了如何<image>使用脚本动态创建元素:

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

七、结论

确保始终声明您在 XML 文件中使用的命名空间。如果您不这样做,Firefox 等用户代理将无法识别您的内容,而只会显示 XML 标记或通知用户 XML 中有错误。在创建新的 SVG 文件时,最好使用包含所有常用命名空间声明的模板。如果您还没有,请从以下代码开始编写:

<svg version="1.1"
     baseProfile="full"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:ev="http://www.w3.org/2001/xml-events">
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
</svg>

即使您不在特定文档中使用所有这些命名空间,包含命名空间声明也没有坏处。如果您最终从未使用的命名空间之一添加内容,它可能会使您免于一些烦人的错误。

八、案例

一个完整的官方例子 SVG:命名空间速成课程:示例



相关文章
|
XML Android开发 数据格式
android中SVG 的使用姿势
android中SVG 的使用姿势
android中SVG 的使用姿势
|
9月前
|
XML Android开发 数据格式
Android XML 布局基础(六)相对布局 - RelativeLayout
Android XML 布局基础(六)相对布局 - RelativeLayout
111 0
|
9月前
|
XML Android开发 数据格式
Android XML 布局基础(五)线性布局 - LinearLayout
Android XML 布局基础(五)线性布局 - LinearLayout
86 0
|
9月前
|
XML Android开发 数据格式
Android XML 布局基础(八)帧布局 - GridLayout
Android XML 布局基础(八)帧布局 - GridLayout
95 0
|
12月前
|
XML API Android开发
Android-Xml绘图
Android-Xml绘图
70 0
|
XML Android开发 数据格式
Android使用本地svg及不显示问题解决
Android使用本地svg及不显示问题解决
|
XML Android开发 数据格式
简单的自定义 View,xmlns 作用,属性动画。
简单的自定义 View,xmlns 作用,属性动画。
50 0
|
XML JavaScript Android开发