我试图了解命名空间如何在 XML 中工作。当我有一个像 foo:bar 这样的元素时,属性上通常不会有命名空间。但有时他们会。即使声明了默认命名空间,该属性是否在元素的命名空间中?查看 xhtml 的 xsd 似乎属性是模式的一部分,应该在 xhtml 的命名空间中,但它们从未以这种方式呈现......
4 回答
大多数时候,属性不会在任何命名空间中。命名空间规范说(强调我的):
默认命名空间声明适用于其范围内的所有无前缀元素名称。默认命名空间声明不直接应用于属性名称;无前缀属性的解释由它们出现的元素决定。
大多数 XML 词汇表使用非命名空间属性是有原因的:
当您的元素具有命名空间并且这些元素具有属性时,就不会混淆:属性属于您的元素,而元素属于您的命名空间。向属性添加名称空间前缀只会使一切变得更加冗长。
那么为什么存在命名空间属性呢?
因为有些词汇表对大多数属性有用,并且在与其他词汇表混合时可以做到这一点。最著名的例子是XLink。
最后,W3C XML <schema attributeFormDefault="qualified">
Schema有一种非常简单的方法(
使用Clark 表示法进行说明的示例,其中命名空间前缀替换为大括号中的命名空间 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 时,有一些与属性/命名空间主题相关的东西让我花了一些时间来理解。我将与您分享此经验,以防万一有人遇到同样的问题。
在我正在处理的架构文档中,一些元素引用了几个全局属性。为了简化这里的事情,让我们假设我正在谈论的这个 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"/>
我的Customer元素使用了这样的属性:
<xs:element name="Customer">
<xs:complexType>
<xs:attribute ref="Id" use="required"/>
<!-- some elements here -->
</xs:complexType>
</xs:element>
现在,假设我想像这样声明一个客户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 论坛上找到了这篇文章,其中一个名叫 Steen Lehmann 的人建议要么在本地声明属性,要么在属性组中声明它
“使属性声明本身不再是全局的”
最后一个解决方案有一种“hacky”的味道,所以我决定坚持第一个解决方案并在本地声明我的所有属性。
阅读w3c上的6.1 命名空间范围和6.2 命名空间默认设置。
基本上:
声明前缀的命名空间声明的范围从它出现的开始标记的开头延伸到相应结束标记的结尾
但是,这里的文字似乎没有解释 a 是 foo:a 还是上下文中的默认命名空间。我假设它不是指 foo:a,而是文档默认命名空间 a。至少考虑到这句话:
这样的命名空间声明适用于其范围内的所有元素和属性名称,其前缀与声明中指定的前缀匹配。
IE。命名空间“foo:”仅适用于以 foo 为前缀的元素: