问题描述
嗨,我在理解命名空间和默认命名空间在 xml 中的工作方式时遇到问题
在下面的示例中,我看到了 2 个默认命名空间(recherche 和 mots-clefs)和 2 个命名空间(xmlns:yahoo 和 xmlns:yahoo2,我对吗?
<?xml version="1.0"?>
<recherche xmlns="http://www.google.com/" xmlns:yahoo="http://www.yahoo.com/">
<mots-clefs xmlns="http://www.yahoo.com/">fraise,orange</mots-clefs>
<yahoo:mot xmlns:yahoo2="http://www.yahoo.com/">
<nombre>3</nombre>
</yahoo:mot>
</recherche>
解决方法
声明了 2 个不同的命名空间:
有两个命名空间前缀,都绑定到 http://www.yahoo.com/ 命名空间:
- 雅虎
- 雅虎2
有些元素的声明没有命名空间前缀,但仍然绑定到命名空间:
- /*:recherche = http://www.google.com/
- /:recherche/:mots-clefs = http://www.yahoo.com/
- /:recherche/:mot = http://www.yahoo.com/
- /:recherche/:mot/*:nombre = http://www.google.com/
注意 nombre
元素绑定到 http://www.google.com/ 命名空间,因为它没有命名空间前缀,而第一个祖先没有命名空间前缀 recherche
将命名空间设置为 http://www.google.com/。
在 XPath 中,您可以使用 namespace-uri()
函数询问元素的命名空间。
由于命名空间的继承方式,当人们使用混合命名空间并且不使用命名空间前缀时,这可能会造成混淆(并且容易出错)。一般来说,最好的做法是应用命名空间前缀以避免这种混淆。
如果您对 XML 进行手工编码,设置不带前缀的命名空间有助于更轻松地构建 XML 并避免重复相同的事情。
,是的,XML 维护两个默认命名空间定义和两个命名空间前缀定义。由于两者重叠,底层标签具有细微的作用域继承。
根据关于 Namespace Scoping 的 XML 1.0 规范:
声明前缀的命名空间声明的范围从它出现的开始标记的开头扩展到相应结束标记的结尾,不包括具有相同 NSAttName 部分的任何内部声明的范围。在空标签的情况下,范围是标签本身。
这样的命名空间声明适用于其范围内的所有元素和属性名称,其前缀与声明中指定的前缀相匹配。
前缀元素或属性名对应的扩展名以绑定前缀的URI为命名空间名,本地部分为本地名。
因此,虽然您发布的 XML 中有两个默认命名空间,但内部声明的默认命名空间在范围内取代了外部默认命名空间,但仅适用于该特定标签及其后代。
此外,任何打算解析根 <recherche>
及其所有非前缀标记后代内容的 DOM 库方法都必须确认 Google URI。但是,仅 <mots-clefs>
及其所有非前缀后代(除了文本节点之外没有)必须使用 Yahoo URI 的当前默认命名空间范围。
为了进一步说明,请参阅 XML 缩进版本中的命名空间作用域注释。请注意,<nombre>
标记是 <recherche>
的后代,并且没有冒号分隔的前缀将默认为第一个声明的默认命名空间。
<?xml version="1.0"?> <!-- NMSP SCOPES: -->
<recherche xmlns="http://www.google.com/" xmlns:yahoo="http://www.yahoo.com/"> <!-- GOOGLE URI -->
<mots-clefs xmlns="http://www.yahoo.com/">fraise,orange</mots-clefs> <!-- YAHOO URI -->
<yahoo:mot xmlns:yahoo2="http://www.yahoo.com/"> <!-- YAHOO PREFIX -->
<nombre>3</nombre> <!-- GOOGLE URI -->
</yahoo:mot>
</recherche>