关于xsd:XML命名空间和属性

关于xsd:XML命名空间和属性

XML namespaces and attributes

我试图了解名称空间如何在XML中工作。 当我有一个像foo:bar这样的元素时,这些属性通常将没有名称空间。 但是有时候他们会。 即使声明了默认名称空间,属性也位于元素的名称空间中吗? 查看xsd中的xhtml,似乎属性是架构的一部分,应该在xhtml的命名空间中,但是从来没有那样显示它们...


大多数时候,属性不会出现在任何命名空间中。命名空间规范说(强调我的):

A default namespace declaration applies to all unprefixed element names within its scope. Default namespace declarations do not apply directly to attribute names; the interpretation of unprefixed attributes is determined by the element on which they appear.

大多数XML词汇表使用非命名空间属性是有原因的:
当元素具有名称空间并且那些元素具有属性时,就不会造成混淆:属性属于元素,元素属于名称空间。在属性上添加名称空间前缀只会使所有内容变得更加冗长。

那么为什么命名空间属性存在?
因为某些词汇表主要对属性有用,所以在与其他词汇表混合使用时可以做到这一点。最著名的示例是XLink。

最后,W3C XML Schema拥有一种非常简单的方法(),将属性声明为位于名称空间中,即使您使用默认名称空间,也迫使您在文档中添加前缀。


使用Clark表示法的示例,其中用大括号将名称空间前缀替换为名称空间URL:

1
2
3
4
5
6
7
8
9
<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"/>

1
2
3
4
5
6
7
8
9
<{}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"/>

今天,当我使用XSD时,与此属性/命名空间主题相关的一些事情使我花了一些时间来理解。
如果有人碰巧遇到相同的问题,我将与您分享这种经验。

在我正在研究的模式文档中,一些元素引用了几个全局属性。为了简化起见,我们假设我正在谈论的XSD是关于客户的。

让我们称这些全局属性Id之一。和使用它的根元素Customer

我的XSD声明看起来像这样:

1
2
3
4
<?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属性声明如下所示:

1
<xs:attribute name="Id" type="xs:positiveInteger"/>

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

1
2
3
4
5
6
<xs:element name="Customer">
   <xs:complexType>
      <xs:attribute ref="Id" use="required"/>
      <!-- some elements here -->
    </xs:complexType>
</xs:element>

现在,假设我想这样声明一个Customer XML文档:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<Customer Id="1" xmlns="http://schemas.mycompany.com/Customer/V1">
  <!-- ... other elements here -->
</Customer>

我发现不能:当全局声明该属性时,该属性与引用该元素的元素不在同一命名空间中。

我发现用XSD定义的唯一解决方案是两次声明名称空间:一次不带前缀以使其成为元素的默认名称空间,一次带前缀以使其与属性一起使用。这就是它的样子:

1
2
3
4
5
<?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>

这太不切实际了,以至于我决定放弃所有全局属性,然后在本地声明它们。在我给的例子中,维奇看起来像这样:

1
2
3
4
5
6
<xs:element name="Customer">
   <xs:complexType>
       <xs:attribute name="Id" type="xs:positiveInteger" use="required"/>
       <!-- some elements here -->
   </xs:complexType>
</xs:element>

我发现很难在网上找到一些关于我在说什么的参考。我最终在Stylus XSD论坛上找到了这篇文章,一个叫Steen Lehmann的人建议要么在本地声明属性,要么在属性组中声明它。

"so that the attribute declaration
itself is no longer global"

最后一个解决方案具有" hacky"的味道,因此我决定坚持使用第一个解决方案,并在本地声明我的所有属性。


在w3c上阅读6.1命名空间范围和6.2命名空间默认值。

基本上:

The scope of a namespace declaration declaring a prefix extends from the beginning of the start-tag in which it appears to the end of the corresponding end-tag

但是,这里的文本似乎没有解释a的意思是a:foo:a还是上下文中的默认名称空间。我假设它没有引用foo:a,而是文档的默认名称空间a。至少考虑此报价:

Such a namespace declaration applies to all element and attribute names within its scope whose prefix matches that specified in the declaration.

就是名称空间" foo:"仅适用于以foo为前缀的元素:


推荐阅读