XML名称空间是做什么用的?
这是我总是很难向他人解释的事情:
为什么存在XML名称空间?
我们什么时候应该使用它们,何时不应该使用它们?
在XML中使用命名空间时,常见的陷阱有哪些?
另外,它们与XML模式有何关系? XSD模式应该始终与名称空间关联吗?
解决方案
根据W3的建议...
XML namespaces provide a simple method for qualifying element and attribute names used in Extensible Markup Language documents by associating them with namespaces identified by URI references.
它们用于允许多种标记语言进行组合,而不必担心元素和属性名称的冲突。
例如,看一下XSLT代码的任何部分,然后思考如果不使用名称空间而试图编写XSLT,其中输出必须包含"模板"," for-each"等元素,将会发生什么情况? 。语法错误,是什么。
我会将建议和陷阱留给比我经验更多的人。
命名空间用于消除我们在文档中使用的名称的歧义。它还使我们能够将短名称绑定到名称空间,然后该名称空间可用于引用远程元素或者属性。命名空间本身是指定义我们在文档中使用的元素和属性的位置。还有很多事情要知道,但这就是核心。这里有很多信息。
几乎与询问"我们为什么要使用Java / C#包?"几乎相同:
- 可重用性:我们可以在不同类型的xml文档中重用定义的一组标记/属性。
- 模块化:如果我们需要在XML中添加一些"方面";向XML文档中添加名称空间比更改整个XML模式定义更简单。
- 避免污染"主要"名称空间:我们不必强制解析器使用庞大的架构定义,而只需使用所需的名称空间即可。
例如:XML命名空间示例
用我的话来说:如果我们必须对外部公司使用某种XML格式(例如),并且需要在XML文档中提供一些具有相同名称的信息,则需要一个名称空间。
例子:
<sampleDoc> <header title="Hello world!"> <items> <item name="Volvo" color="Blue"/> </items> </header> </sampleDoc>
并且我们想要将一些数据合并到此文档中,该文件具有相同的名称,但从另一种意义上(因此为to),则应使用名称空间:
<sampleDoc> <header title="Hello world!"> <items> <item name="Volvo" color="White" my_unique_namespace:color="#FFFFFF"/> </items> </header> </sampleDoc>
当然,我们可以更改属性的名称。例如" my_unique_color"。在另一个文档中芽,可以再次具有相同名称的属性。因此,如果我们具有唯一的名称空间(例如我们的Web域),则可以始终使用相同名称的元素和/或者属性,而不会遇到任何问题。
可以将它们视为元素类型的姓氏。如果我们有两个朋友,两个人都叫鲍勃,而我们正在谈论其中的一个,则有人可能会问我们正在谈论哪个鲍勃。只是说"鲍勃"不是很有帮助,所以你说"鲍勃·史密斯"或者"鲍勃·琼斯"。
元素类型相同。有时,短名称是不够的,因为不同的人可以选择相同的名称。因此,我们包含一个URI作为"姓",以区分其中的不同Bobs。
XML是一种超级语言,这意味着它是任何基于XML的语言的基础(有意义,对吧?)。将XML视为可以用任何语言写任何句子的笔。一切都取决于作者,最好是读者应该知道该语言。
XML名称空间基本上是语言的名称,很像"英语"或者" ?????"。我帮助XML文档的接收者解析它并提取其中的信息。
假设我有一家家具厂,而我们有一家家具店。存储应用程序和我的供应应用程序是完全不相关的,但是当它们通过XML消息进行通信时,消息应易于理解并且双方都可以轻松解析
因此,两个系统都需要了解Schema,该Schema定义了语言语法和约定的限制。可以将模式视为字典和语法教科书。模式是两个系统都应该知道的文档,每个系统中编写解析代码的人都必须知道该文档,其中包括名称空间的声明。
每个命名空间都被命名为URI,在大多数情况下,这是定义它的架构文档的位置。
当然,并不是每个XML文档都需要一个名称空间,尤其是在不用于将信息传递到远程系统时。例如,当我们将对象序列化为XML以持久化在数据库中时。
恕我直言,最大的陷阱是人机交互解释文件,例如开发代码来处理XML文档。只关注文档的文字表达而不是解析文档的信息集结果太容易了。
例如以下节点
<a xmlns="uri:foo"/> <foo:a xmlns:foo="uri:foo"/> <bar:a xmlns:bar="uri:foo"/>
在语义上都是相同的,但与幼稚的眼睛有很大不同。
第一个示例在开发XPath时产生了一个非常常见的错误,它缺少以下事实:" a"位于名称空间中,因此// a不产生匹配项。 (或者更糟糕的是,仍然匹配不同名称空间中的节点!)
第三个示例在理解前缀文本在语义上具有重要意义方面带来了另一个缺陷。使用XPATH解析文档时,只要uri与文档中的URI匹配,我就可以声明我喜欢匹配的任何前缀。
我们之所以使用命名空间,是因为人们希望在自己的私人爱达荷州使用相同的单词来表示不同的事物。通常,我们可以根据上下文确定一个人的意思。在人员数据库中,XML是人员记录。在车辆登记数据库中,XML是车辆登记记录。
两者都保留有一个名为" location"的标签,但是标签对每个标签都具有不同的含义,并且包含不同的字段。
现在,这很酷:但是,如果我们需要或者希望将两个数据库中的XML存储在同一个数据库中怎么办?或者,更有趣的是,如果两个数据库都希望存储其他一些通用数据库(例如Accounts数据库)中的XML块,该怎么办?
XML名称空间与每个XML标记关联一个URI,以便标记名称本身在其前面有一个url,这是标记名称的一部分(当然,实际的XML文档使用速记方法来做到这一点)。通过仔细选择URI,很容易确定标记名称不会冲突,就好像两个位置标记的命名完全不同,因此不会造成混淆。另外,两个完全不同的位置标签可以包含来自帐户数据库的内容,并明确声明它们在谈论同一件事。
使所有这些都有用的是XPATH。
通过上面的内容,我们可以开始编写XPATH表达式,其内容如下:在此xml中的任意位置找到我的所有accounts:account overdue
部分。或者:在这个特定的XML块中的任意位置找到我的任何"帐户:警告消息"项,其中警告消息是"人员:付款"节点或者"车辆:状态"节点的子节点(无论深度如何)。
该XPATH表达式可以在XSLT文档中的某处使用,该文档的工作是将XML转换为XHTML或者XPDF,以进行显示。
收益是多少?为什么呢因为我们可以搜索XML日志文件,所以将所有过期的邮件都撤出,无论它们出现在哪里,而不会与其他系统生成的" message"标签混淆,将它们转换为xhtml,并通过css标签以红色粗体显示:无需编写任何程序代码。