XML名称空间和属性

我想了解名称空间如何在XML中工作。 当我有像foo:bar这样的元素时,这些属性往往没有名称空间。 但有时他们会。 是元素的名称空间中的属性,即使默认的名称空间已被声明? 查看xhtml的xsd,似乎这些属性是模式的一部分,应该在xhtml的命名空间中,但是它们不会以这种方式呈现…

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

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

大多数XML词汇表使用非名称空间属性是有原因的:
当元素有一个名称空间,并且这些元素具有属性时,就不会有混淆:属性属于您的元素,属于您的名称空间。 给属性添加一个名称空间前缀将使所有内容更加冗长。

那么为什么名称空间属性存在?
因为一些词汇表主要用属性来做有用的工作,并且可以在与其他词汇表混合时做到这一点。 最着名的例子是XLink 。

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

使用Clark符号进行说明的示例,其中名称空间前缀replace为大括号中的名称空间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"/> 

这个属性/命名空间主题有一些与我在使用XSD时花了一些时间来理解的东西有关。 如果有人遇到同样的问题,我将与您分享这个经历。

在我正在处理的Schema文档中,有些元素引用了一些全局属性。 为了简化这里的事情,我们假设这个我所说的XSD是关于一个Customer

我们来调用其中一个全局属性Id 。 并使用它的根元素Customer

我的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定义的解决scheme就是声明两次命名空间:一次没有前缀,为了使它成为元素的默认命名空间,一次使用前缀,以便与属性一起使用。 所以这是这样的:

 <?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> 

我发现很难find一些关于我在网上讨论的内容的参考。 我最终在Stylus XSD论坛上发现了这篇文章 ,其中一个名叫Steen Lehmann的人build议要么在本地声明属性,要么在属性组中声明属性

“所以这个属性声明本身不再是全局的”

这最后的解决scheme有一个“哈克”的味道,所以我只是决定坚持第一个解决scheme,并在本地声明我所有的属性。

请阅读6.1命名空间范围和6.2命名空间默认 w3c。

基本上:

声明前缀的名称空间声明的范围从其开始标记的开始处延伸到相应的结束标记的末尾

然而,这里的文本似乎并没有解释如果意味着a是foo:a或上下文中的默认命名空间。 我会假设它没有引用foo:a,而是文档的默认命名空间a。 考虑到这个报价至less:

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

IE浏览器。 命名空间“foo:”只适用于前缀为foo的元素: