xml schema中的namespace分析

我们知道,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:街道”。

<? xml version="1.0" encoding="GB2312" standalone="yes" ?>
< xs:schema  xmlns:xs ="http://www.w3.org/2001/XMLSchema"  xmlns ="www.shitou.com"  targetNamespace ="www.shitou.com"  elementFormDefault ="qualified"  attributeFormDefault ="unqualified" >
    
< xs:element  name ="城市"  type ="xs:string" />
    
< xs:element  name ="街道"  type ="xs:string" />
    
< xs:element  name ="省份"  type ="xs:string" />
    
< xs:element  name ="地址" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="街道" />
                
< xs:element  ref ="城市" />
                
< xs:element  ref ="省份" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
    
< xs:element  name ="EMAIL"  type ="xs:string" />
    
< xs:element  name ="ID"  type ="xs:string" />
    
< xs:element  name ="公司"  type ="xs:string" />
    
< xs:element  name ="姓名"  type ="xs:string" />
    
< xs:element  name ="电话"  type ="xs:string" />
    
< xs:element  name ="直接上司"  type ="xs:anyType" />
    
< xs:element  name ="联系人" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="姓名" />
                
< xs:element  ref ="ID" />
                
< xs:element  ref ="公司" />
                
< xs:element  ref ="EMAIL" />
                
< xs:element  ref ="电话" />
                
< xs:element  ref ="地址" />
                
< xs:element  ref ="直接上司" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
    
< xs:element  name ="联系人列表" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="联系人"  maxOccurs ="unbounded" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
</ xs:schema >

当然,上面的xmlns=“www.shitou.com”的语法并不受推崇,容易造成混乱,所以下面的manager.xsd中变了以下,取消了xmlns=“www.manager.com”,取而代之的是xmlns:经理=“www.manager.com”,相应的,其中ref的地方都要加上“经理”前缀,如

<xs:element ref="经理:姓名"/>
  <xs:element ref="经理:电话"/> 这样虽然麻烦点,但是不至于造成混乱。

<? xml version="1.0" encoding="GB2312" standalone="yes" ?>
< xs:schema  xmlns:xs ="http://www.w3.org/2001/XMLSchema"  xmlns:经理 ="www.manager.com"  targetNamespace ="www.manager.com"  elementFormDefault ="qualified"  attributeFormDefault ="unqualified" >
    
< xs:element  name ="企业经理" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:姓名" />
                
< xs:element  ref ="经理:电话" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
    
    
< xs:element  name ="姓名"  type ="xs:string" />
    
< xs:element  name ="手机"  type ="xs:string" />
    
< xs:element  name ="秘书电话"  type ="xs:string" />
    
< xs:element  name ="电话" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:秘书电话" />
                
< xs:element  ref ="经理:手机" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
</ xs:schema >

 因为一个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文档中使用我们定义的前缀了。

<? xml version="1.0" encoding="UTF-8" ?>
< 联系人: 联系人列表 xmlns:联系人 ="www.shitou.com"  xmlns:企业经理 ="www.manager.com"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation ="www.shitou.com
client.xsd www.manager.com manager.xsd"
>
    
< 联系人: 联系人 >
        
< 联系人: 姓名 > 张三丰 </ 联系人:姓名 >
        
< 联系人:ID > 001 </ 联系人:ID >
        
< 联系人: 公司 > huawei </ 联系人:公司 >
        
< 联系人:EMAIL > [email protected] </ 联系人:EMAIL >
        
< 联系人: 电话 > (0755)21530000 </ 联系人:电话 >
        
< 联系人: 地址 >
            
< 联系人: 街道 > 高新南十一道 </ 联系人:街道 >
            
< 联系人: 城市 > 深圳市 </ 联系人:城市 >
            
< 联系人: 省份 > 广东 </ 联系人:省份 >
        
</ 联系人:地址 >
        
< 联系人: 直接上司 >
            
< 企业经理: 姓名 > 大刀王五 </ 企业经理:姓名 >
            
< 企业经理: 电话 >
                
< 企业经理: 秘书电话 > 0755-21500000 </ 企业经理:秘书电话 >
                
< 企业经理: 手机 > 13800008888 </ 企业经理:手机 >
            
</ 企业经理:电话 >
        
</ 联系人:直接上司 >
    
</ 联系人:联系人 >
</ 联系人:联系人列表 >

本例在http://bbs.w3china.org/dispbbs.asp?BoardID=23&replyID=40537&id=15255&star=1&skin=0的例子基础上修改而成,经过xml spy2006验证。

下面考虑elementFormDefault属性值unqualified和qualified的区别:

将client.xsd修改成如下所示:

 

<? xml version="1.0" encoding="GB2312" standalone="yes" ?>
< xs:schema  xmlns:xs ="http://www.w3.org/2001/XMLSchema"  xmlns ="www.shitou.com"  targetNamespace ="www.shitou.com"  elementFormDefault ="unqualified"  attributeFormDefault ="unqualified" >
    
< xs:element  name ="城市"  type ="xs:string" />
    
< xs:element  name ="街道"  type ="xs:string" />
    
< xs:element  name ="省份"  type ="xs:string" />
    
< xs:element  name ="地址" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="街道" />
                
< xs:element  ref ="城市" />
                
< xs:element  ref ="省份" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >     

    
< xs:element  name ="联系人" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  name ="姓名"  type ="xs:string" />
                
< xs:element  name ="ID"  type ="xs:string" />
                
< xs:element  name ="公司"  type ="xs:string" />
                
< xs:element  name ="EMAIL"  type ="xs:string" />
                
< xs:element  name ="电话"  type ="xs:string" />
                
< xs:element  ref ="地址"   />
                
< xs:element  name ="直接上司"  type ="xs:anyType" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
    
< xs:element  name ="联系人列表" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="联系人"  maxOccurs ="unbounded" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
</ xs:schema >

这个时候,“姓名、ID、公司、EMAIL、电话、直接上司”因为不再是全局成分,将elementFromDefault值设置为unqualified时,这些子元素不再属于targetNamespace,而不属于任何 namespace,所以employee.xml应修改为如下所示: 我们注意到,“姓名、ID、公司、EMAIL、电话、直接上司”前面都没有加前缀“联系人”。

<? xml version="1.0" encoding="UTF-8" ?>
< 联系人: 联系人列表 xmlns:联系人 ="www.shitou.com"  xmlns:企业经理 ="www.manager.com"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation ="www.shitou.com
client.xsd www.manager.com manager.xsd"
>
    
< 联系人: 联系人 >
        
< 姓名 > 张三丰 </ 姓名 >
        
< ID > 001 </ ID >
        
< 公司 > huawei </ 公司 >
        
< EMAIL > [email protected] </ EMAIL >
        
< 电话 > (0755)21530000 </ 电话 >
        
< 联系人: 地址 >
            
< 联系人: 街道 > 高新南十一道 </ 联系人:街道 >
            
< 联系人: 城市 > 深圳市 </ 联系人:城市 >
            
< 联系人: 省份 > 广东 </ 联系人:省份 >
        
</ 联系人:地址 >
        
< 直接上司 >
            
< 企业经理: 企业经理 >             
                
< 企业经理: 姓名 > 大刀王五 </ 企业经理:姓名 >
                
< 企业经理: 电话 >
                    
< 企业经理: 秘书电话 > 0755-21500000 </ 企业经理:秘书电话 >
                    
< 企业经理: 手机 > 13800008888 </ 企业经理:手机 >
                
</ 企业经理:电话 >
            
</ 企业经理:企业经理 >
        
</ 直接上司 >
    
</ 联系人:联系人 >
</ 联系人:联系人列表 >

考虑了元素的命名空间,下面我们考虑属性的命名空间。其attributeFromDefault属性与elementFromDefault属性的用法相同。

我们将manager.xsd修改如下,添加一个属性“性别”,将attributeFormDefault 设置为"qualified",这样,“性别”属性属于命名空间targetNameSpace中。

<? xml version="1.0" encoding="GB2312" standalone="yes" ?>
< xs:schema  xmlns:xs ="http://www.w3.org/2001/XMLSchema"  xmlns:经理 ="www.manager.com"  targetNamespace ="www.manager.com"  elementFormDefault ="unqualified"  attributeFormDefault ="qualified" >
    
< xs:element  name ="企业经理" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:姓名" />
                
< xs:element  ref ="经理:电话" />
            
</ xs:sequence >
            
< xs:attribute  name ="性别" >
                
< xs:simpleType >
                    
< xs:restriction  base ="xs:string" >
                        
< xs:enumeration  value ="男" />
                        
< xs:enumeration  value ="女" />
                        
< xs:enumeration  value ="不男不女" />
                    
</ xs:restriction >
                
</ xs:simpleType >
            
</ xs:attribute >  
        
</ xs:complexType >
    
</ xs:element >
    
    
< xs:element  name ="姓名"  type ="xs:string" />
    
< xs:element  name ="手机"  type ="xs:string" />
    
< xs:element  name ="秘书电话"  type ="xs:string" />
    
< xs:element  name ="电话" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:秘书电话" />
                
< xs:element  ref ="经理:手机" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
</ xs:schema >

对应的employee.xml修改为如下,可以通过验证。

 

<? xml version="1.0" encoding="UTF-8" ?>
< 联系人: 联系人列表 xmlns:联系人 ="www.shitou.com"  xmlns:企业经理 ="www.manager.com"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation ="www.shitou.com
client.xsd www.manager.com manager.xsd"
>
    
< 联系人: 联系人 >
        
< 姓名 > 张三丰 </ 姓名 >
        
< ID > 001 </ ID >
        
< 公司 > huawei </ 公司 >
        
< EMAIL > [email protected] </ EMAIL >
        
< 电话 > (0755)21530000 </ 电话 >
        
< 联系人: 地址 >
            
< 联系人: 街道 > 高新南十一道 </ 联系人:街道 >
            
< 联系人: 城市 > 深圳市 </ 联系人:城市 >
            
< 联系人: 省份 > 广东 </ 联系人:省份 >
        
</ 联系人:地址 >
        
< 直接上司 >
            
< 企业经理: 企业经理 企业经理:性别 ="男" >             
                
< 企业经理: 姓名 > 大刀王五 </ 企业经理:姓名 >
                
< 企业经理: 电话 >
                    
< 企业经理: 秘书电话 > 0755-21500000 </ 企业经理:秘书电话 >
                    
< 企业经理: 手机 > 13800008888 </ 企业经理:手机 >
                
</ 企业经理:电话 >
            
</ 企业经理:企业经理 >
        
</ 直接上司 >
    
</ 联系人:联系人 >
</ 联系人:联系人列表 >

我们注意到,在上面的代码中,“性别”前加了前缀“企业经理”。

若将manager.xsd修改如下,将attributeFormDefault 设置为"qualified",这样,局部属性“性别”不再属于命名空间targetNameSpace中。

<? xml version="1.0" encoding="GB2312" standalone="yes" ?>
< xs:schema  xmlns:xs ="http://www.w3.org/2001/XMLSchema"  xmlns:经理 ="www.manager.com"  targetNamespace ="www.manager.com"  elementFormDefault ="unqualified"  attributeFormDefault ="unqualified" >
    
< xs:element  name ="企业经理" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:姓名" />
                
< xs:element  ref ="经理:电话" />
            
</ xs:sequence >
            
< xs:attribute  name ="性别" >
                
< xs:simpleType >
                    
< xs:restriction  base ="xs:string" >
                        
< xs:enumeration  value ="男" />
                        
< xs:enumeration  value ="女" />
                        
< xs:enumeration  value ="不男不女" />
                    
</ xs:restriction >
                
</ xs:simpleType >
            
</ xs:attribute >  
        
</ xs:complexType >
    
</ xs:element >
    
    
< xs:element  name ="姓名"  type ="xs:string" />
    
< xs:element  name ="手机"  type ="xs:string" />
    
< xs:element  name ="秘书电话"  type ="xs:string" />
    
< xs:element  name ="电话" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:秘书电话" />
                
< xs:element  ref ="经理:手机" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
</ xs:schema >

这时,employee.xml中的“性别”属性前要去掉前缀“企业经理”,方能通过验证。如:

<? xml version="1.0" encoding="UTF-8" ?>
< 联系人: 联系人列表 xmlns:联系人 ="www.shitou.com"  xmlns:企业经理 ="www.manager.com"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation ="www.shitou.com
client.xsd www.manager.com manager.xsd"
>
    
< 联系人: 联系人 >
        
< 姓名 > 张三丰 </ 姓名 >
        
< ID > 001 </ ID >
        
< 公司 > huawei </ 公司 >
        
< EMAIL > [email protected] </ EMAIL >
        
< 电话 > (0755)21530000 </ 电话 >
        
< 联系人: 地址 >
            
< 联系人: 街道 > 高新南十一道 </ 联系人:街道 >
            
< 联系人: 城市 > 深圳市 </ 联系人:城市 >
            
< 联系人: 省份 > 广东 </ 联系人:省份 >
        
</ 联系人:地址 >
        
< 直接上司 >
            
< 企业经理: 企业经理 性别 ="男" >             
                
< 企业经理: 姓名 > 大刀王五 </ 企业经理:姓名 >
                
< 企业经理: 电话 >
                    
< 企业经理: 秘书电话 > 0755-21500000 </ 企业经理:秘书电话 >
                    
< 企业经理: 手机 > 13800008888 </ 企业经理:手机 >
                
</ 企业经理:电话 >
            
</ 企业经理:企业经理 >
        
</ 直接上司 >
    
</ 联系人:联系人 >
</ 联系人:联系人列表 >

若将manager.xsd文件中局部属性“性别”改成全局属性,如下面代码所示,则“性别”属性还是属于命名空间targetNamespace中。

<? xml version="1.0" encoding="GB2312" standalone="yes" ?>
< xs:schema  xmlns:xs ="http://www.w3.org/2001/XMLSchema"  xmlns:经理 ="www.manager.com"  targetNamespace ="www.manager.com"  elementFormDefault ="unqualified"  attributeFormDefault ="unqualified" >
    
< xs:element  name ="企业经理" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:姓名" />
                
< xs:element  ref ="经理:电话" />
            
</ xs:sequence >
            
< xs:attribute  ref ="经理:性别" />
        
</ xs:complexType >
    
</ xs:element >
    
    
< xs:attribute  name ="性别" >
        
< xs:simpleType >
            
< xs:restriction  base ="xs:string" >
                
< xs:enumeration  value ="男" />
                
< xs:enumeration  value ="女" />
                
< xs:enumeration  value ="不男不女" />
            
</ xs:restriction >
        
</ xs:simpleType >
    
</ xs:attribute >  
    
    
< xs:element  name ="姓名"  type ="xs:string" />
    
< xs:element  name ="手机"  type ="xs:string" />
    
< xs:element  name ="秘书电话"  type ="xs:string" />
    
< xs:element  name ="电话" >
        
< xs:complexType >
            
< xs:sequence >
                
< xs:element  ref ="经理:秘书电话" />
                
< xs:element  ref ="经理:手机" />
            
</ xs:sequence >
        
</ xs:complexType >
    
</ xs:element >
</ xs:schema >

此时,employee.xml文件中的属性“性别”前的前缀要加上,才能通过验证,如下所示。

<? xml version="1.0" encoding="UTF-8" ?>
< 联系人: 联系人列表 xmlns:联系人 ="www.shitou.com"  xmlns:企业经理 ="www.manager.com"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation ="www.shitou.com
client.xsd www.manager.com manager.xsd"
>
    
< 联系人: 联系人 >
        
< 姓名 > 张三丰 </ 姓名 >
        
< ID > 001 </ ID >
        
< 公司 > huawei </ 公司 >
        
< EMAIL > [email protected] </ EMAIL >
        
< 电话 > (0755)21530000 </ 电话 >
        
< 联系人: 地址 >
            
< 联系人: 街道 > 高新南十一道 </ 联系人:街道 >
            
< 联系人: 城市 > 深圳市 </ 联系人:城市 >
            
< 联系人: 省份 > 广东 </ 联系人:省份 >
        
</ 联系人:地址 >
        
< 直接上司 >
            
< 企业经理: 企业经理 企业经理:性别 ="男" >             
                
< 企业经理: 姓名 > 大刀王五 </ 企业经理:姓名 >
                
< 企业经理: 电话 >
                    
< 企业经理: 秘书电话 > 0755-21500000 </ 企业经理:秘书电话 >
                    
< 企业经理: 手机 > 13800008888 </ 企业经理:手机 >
                
</ 企业经理:电话 >
            
</ 企业经理:企业经理 >
        
</ 直接上司 >
    
</ 联系人:联系人 >
</ 联系人:联系人列表 >

相信通过这么啰啰嗦嗦讲了一大堆,大家应该也基本明白了。还有一个属性xsi:noNamespaceSchemaLocation没有提到,大家上网查查。希望我的这点理解能对大家有所帮助。


你可能感兴趣的:(xml schema中的namespace分析)