我们知道,namespace在xml中占有重要的地位,其是xml的核心标准之一。所以,xml schema、xml query等后来的标准都对namespace有较好的支持。namespace很琐碎,是广大xml初学者的绊脚石。下面讲讲xml schema中的namespace,让大家消除点恐惧。
xml schema对namespace的支持体现在targetNamespace上,每个xml schema文档有一个顶层的schema元素,其targetNamespace就是全局成分所在的名字空间(全局成分指的是元素xsd:schema的直接子节点,包括元素声明、属性声明、复杂/简单类型定义、组定义、属性组定义).
属性elementFormDefault的默认值是unqualified,也就是规定了只有全局成分才被定义在目标名称空间中。将elementFormDefault的值赋为qualified,使得目标名称空间包含非全局的元素定义。同样,使属性attributeFormDefault的值赋为qualified,可使得目标名称空间包含非全局属性定义。如以下文档client.xsd,所有的元素均在namespace “www.shitou.com”中。至于声明xmlns=“www.shitou.com”,为的是ref的时候不用写namespace前缀了。否则,诸如
<xs:element ref="街道"/>
<xs:element ref="城市"/>
<xs:element ref="省份"/> 等语句就会出现问题了,因为No namespace的元素“街道”没有定义,client.xsd定义的只是“www.shitou.com:街道”。
当然,上面的xmlns=“www.shitou.com”的语法并不受推崇,容易造成混乱,所以下面的manager.xsd中变了以下,取消了xmlns=“www.manager.com”,取而代之的是xmlns:经理=“www.manager.com”,相应的,其中ref的地方都要加上“经理”前缀,如
<xs:element ref="经理:姓名"/>
<xs:element ref="经理:电话"/> 这样虽然麻烦点,但是不至于造成混乱。
因为一个xsd只有一个tagetNamespace属性,言下之意,也就是这个文档中定义的所有元素都属于一个namespace,这与我们的xml文件经常出现多个namespace的情况不符。于是,有必存在一种手段,将多个xsd中定义的namespace融合在一个xml文档中。
下面这个例子employee.xml融合了上面的client.xsd和manager.xsd,注意,其中声明的namespace必须和xsd中声明的targetNamespace相符,如联系人对应的www.shitou.com,企业经理对应的www.manager.com,此外,还要在xsi:schemaLocation中说明schema所在的位置,其格式是“namespace1 xsd文件路径1 namespace2 xsd文件路径2...”,这样,我们就可以在xml文档中使用我们定义的前缀了。
本例在http://bbs.w3china.org/dispbbs.asp?BoardID=23&replyID=40537&id=15255&star=1&skin=0的例子基础上修改而成,经过xml spy2006验证。
下面考虑elementFormDefault属性值unqualified和qualified的区别:
将client.xsd修改成如下所示:
这个时候,“姓名、ID、公司、EMAIL、电话、直接上司”因为不再是全局成分,将elementFromDefault值设置为unqualified时,这些子元素不再属于targetNamespace,而不属于任何 namespace,所以employee.xml应修改为如下所示: 我们注意到,“姓名、ID、公司、EMAIL、电话、直接上司”前面都没有加前缀“联系人”。
考虑了元素的命名空间,下面我们考虑属性的命名空间。其attributeFromDefault属性与elementFromDefault属性的用法相同。
我们将manager.xsd修改如下,添加一个属性“性别”,将attributeFormDefault 设置为"qualified",这样,“性别”属性属于命名空间targetNameSpace中。
对应的employee.xml修改为如下,可以通过验证。
我们注意到,在上面的代码中,“性别”前加了前缀“企业经理”。
若将manager.xsd修改如下,将attributeFormDefault 设置为"qualified",这样,局部属性“性别”不再属于命名空间targetNameSpace中。
这时,employee.xml中的“性别”属性前要去掉前缀“企业经理”,方能通过验证。如:
若将manager.xsd文件中局部属性“性别”改成全局属性,如下面代码所示,则“性别”属性还是属于命名空间targetNamespace中。
此时,employee.xml文件中的属性“性别”前的前缀要加上,才能通过验证,如下所示。
相信通过这么啰啰嗦嗦讲了一大堆,大家应该也基本明白了。还有一个属性xsi:noNamespaceSchemaLocation没有提到,大家上网查查。希望我的这点理解能对大家有所帮助。