命名空间与XML有什么关系?

3

这里有些让我困惑的地方:

NSXMLParser方法中有一个namespaceURI属性:

- (void)parser:(NSXMLParser *)parser 
 didEndElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI 
 qualifiedName:(NSString *)qName

从文档中我无法确定"namespace"的含义。有人能举个例子解释一下XML中的名称空间是什么以及为什么我需要它吗?

编辑:是的,我看到了维基百科。但是它依然很令人困惑。在XML文件顶部放置一个单一的名称空间声明有什么意义呢?

xmlns:xhtml="http://www.w3.org/1999/xhtml"

再次强调,这完全没有意义。维基百科也没有提供有用的示例来解释为什么我真正需要名称空间,更重要的是这在XML文件中是如何呈现的。他们说它是为了解决多个同名元素(如ID)的歧义问题,但没有示例说明多个名称空间如何解决这个问题。

4个回答

7

XML命名空间的工作方式与其他地方的命名空间相同。

它们提供了一种唯一区分同名元素或属性的方法。这是通过声明命名空间URI并可选地将前缀附加到节点名称来完成的。此前缀(可选)会随命名空间声明一起定义。

<!-- node without any namespace (it's in the default namespace) -->
<node>
  <child /><!-- descendants are in the parent namespace by default -->
</node>

<!-- node with explicit default namespace -->
<node xmlns="http://some/namespace/uri/">
  <child /><!-- descendants are in the parent namespace by default -->
</node>

<!-- NS declaration with prefix (node is still in the default namespace!) -->
<node xmlns:prefix="http://some/namespace/uri/">
  <child /><!-- descendants are in the parent's namespace -->
  <prefix:child><!-- explicit namespace assignment by prefix -->
    <grandchild /><!-- prefixes don't propagate, this is in the default namespace! -->
  </prefix:child>
</node>

命名空间是严格作用域的。它们仅适用于节点及其后代。要使命名空间在整个XML文档中可用,必须在顶层元素(文档元素)上声明。

对于你的情况,在示例或<prefix:child />中:

didEndElement = "child"
 namespaceURI = "http://some/namespace/uri/"
qualifiedName = "prefix:child"

仅为澄清起见:在 prefix:node<child /></prefix:node> 中,子元素仍具有默认命名空间,而不是与前缀相关联的命名空间。 - Bart van Heukelom
@Bart:非常正确,我会更改描述。 - Tomalak

3

命名空间用于限定元素名称,前缀用于简化XML。默认情况下,有一个URI为空的命名空间。

扩展Tomalak的示例:

<!-- Mixing namespaces default namespace -->
<node xmlns:gc="http://other/namespace/gc"> <!-- node is in default NS -->
  <child> <!-- child is still in default NS, inherited from parent - node -->
    <gc:grandchild/>  <!-- grandchild is in the "http://other/namespace/gc", because of gc prefix -->
  </child>
  <child xmlns="http://some/namespace/uri/" xmlns:gc2="http://other/namespace/gc"> <!-- node is in "http://home/namespace/uri" because of declration -->
    <gc2:grandchild/> <!-- again, in "http://other/namespace/gc", despite different prefix -->
    <grandchild/> <!-- yet this one is in "http://home/namespace/uri", no prefix, inherited from parent -->
  </child>
</node>

这里的要点是两个“子”节点是不同的节点。它们看起来相同,但它们的“完全限定名称”是不同的。这在XSL中尤为重要。
孙节点也是如此。gc:grandchild和gc2:grandchild是相同的,它们共享相同的命名空间URI,但使用不同的前缀。第三个孙节点是不同的,因为它使用了从父子节点继承的命名空间。
命名空间很重要,因为它们允许您在单个文档中从不同的词汇表中“混合和匹配”XML。例如,在XHTML文档中嵌入SVG标记。使用命名空间可以避免出现相同基本节点名称的重叠。
对于大多数简单的XML问题,它们是不必要的。但当您开始合并标准等时,它们变得非常重要。
另一个例子是在Web服务的SOAP信封中嵌入SAML断言。 SOAP是一种标准,SAML是另一种独立的标准和标准机构,但两者都允许在其文档中插入“任意XML”的区域。命名空间使内容保持分离。


1

命名空间在XML中非常重要,因为您可能会在同一XML层次结构中具有相同本地名称的节点。

想象一个描述期刊文章的XML文档。您可能会有一个元素来定义文章的作者:

<article>
  <head>
    <author>Emily Berthenstien</author>
  </head>
....

在文章的后面,您可能会看到列出已被引用的作者的引文。
<citations>
  <citation>
    <author>Bernard Rightofen</author>
  </citation>  
</citations>       

你如何区分这两个“author”节点?
在头部和引用节点中添加不同的命名空间,将为每个作者节点创建一个QName,您可以使用XPath或其他方法特定地访问它们,而不会混淆。例如,现在您可以使用XPath及其QName仅选择引用作者:
declare namespace citauths="http://citation/authors/only"

//citauths:author

只需文章作者:

declare namespace auths="http://article/authors/only"

//auths:author

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接