XML名称空间和属性

时间:2008-09-03 12:34:44

标签: xml xsd namespaces

我正在尝试了解命名空间如何在XML中工作。当我有一个像foo:bar这样的元素时,属性通常没有命名空间。但有时他们会。即使已声明默认命名空间,元素名称空间中的属性也是如此?查看xsd for xhtml似乎属性是模式的一部分,应该在xhtml的命名空间中,但它们从未以这种方式呈现......

4 个答案:

答案 0 :(得分:53)

大多数情况下,属性不会出现在任何名称空间中。 namespace spec说(强调我的):

  

默认名称空间声明适用于其范围内所有未加前缀的元素名称。默认名称空间声明直接应用于属性名称;对无前缀属性的解释由它们出现的元素决定。

大多数XML词汇表使用非命名空间属性是有原因的:
当您的元素具有命名空间并且这些元素具有属性时,则不会产生混淆:属性属于您的元素,属于您的命名空间。为属性添加名称空间前缀只会使一切更加冗长。

那么为什么存在命名空间属性呢? 因为一些词汇表主要使用属性进行有用的工作,并且可以在与其他词汇表混合时执行此操作。最着名的例子是XLink

最后,W3C XML Schema有一种非常简单的方法(<schema attributeFormDefault="qualified">)将您的属性声明为名称空间,强制您在文档中添加前缀,甚至使用默认命名空间。

答案 1 :(得分:15)

使用Clark notation来说明的示例,其中命名空间前缀被大括号中的命名空间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"/>

答案 2 :(得分:9)

有一些与此属性/命名空间主题相关的内容在我使用XSD时花了一些时间来理解今天。 如果有人碰巧遇到同样的问题,我将与你分享这段经历。

在我正在研究的S​​chema Document中,有一些元素引用了一些全局属性。为了简化这里的事情,让我们假设我所说的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"/>

我的客户元素使用了如下属性:

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

现在,假设我想声明一个 Customer XML文档,如下所示:

<?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论坛中找到this post,其中一个名为Steen Lehmann的人建议在本地声明属性或在属性组中声明它

  

“以便属性声明   本身不再是全球性的“

这最后一个解决方案有“hacky”的味道,所以我决定坚持使用第一个解决方案并在本地声明我的所有属性。

答案 3 :(得分:3)

在w3c上的6.1 Namespace Scoping6.2 Namespace Defaulting阅读。

基本上:

  

声明前缀的名称空间声明的范围从它出现的起始标记的开头延伸到相应的结束标记的末尾

但是,这里的文字似乎没有解释是否意味着a是foo:a或上下文中的默认命名空间。我认为它不是指foo:a,而是文档默认命名空间a。至少考虑这个引用:

  

此类名称空间声明适用于其范围内的所有元素和属性名称,其前缀与声明中指定的前缀相匹配。

IE中。命名空间“foo:”仅适用于以foo为前缀的元素: