详解XML namespace

[size=medium]XML Namespaces[/size]

首先来看下,[color=red]为什么要引入 Namespaces [/color]这个概念,明白了这个,我们再来一步一步挖掘 namespaces。
来看个简单的例子
<?xml version="1.0"?>
<Person>
<Name>Tom</Name>
<Address>
<Street>XinHua .7</Street>
<City>BeiJing</City>
</Address>
</Person>

记录了一个人的基本信息,名字,家庭地址
<?xml version="1.0"?>
<Contact>
<Address>Tom@hotmail.com</Address>
<Tel>010-123123123</Tel>
</Contact>

记录了一个人的联系方式,电子邮箱,电话号码

可以看到,第一个xml文件存在一个 Address Element Type
第二个xml 文件同样存在一个 Address Element Type。当然如果这两个Element Type都是单独存在的话,就像上面这样,各自存在与不同的xml document当中,是完全没有问题的。

可是假如,想要对一个人做记录,其中包括名字,地址,联系方式。
<?xml version="1.0"?>
<Person>
<Name>Tom</Name>
<Address>
<Street>XinHua .7</Street>
<City>BeiJing</City>
</Address>
<Contact>
<Address>Tom@hotmail.com</Address>
<Tel>010-123123123</Tel>
</Contact>
</Person>

那么程序如何分得清楚第一个Address Element Type代表的是家庭地址,而第二个则代表的是邮箱地址。不单是这个例子,假如图书馆想要对借书的人与被借走的书做个record的话,不单是Person这个Element Type 有<Name></Name>,Book同样有<Name></Name>这样的Element Type。所以这就需要引入Namespace这个重要的概念[quote]XML namespaces were originally designed to provide universally unique names for elements and attributes.[/quote]Namespace是为elements和attributs提供独一无二的Name,来避免发生上面例子当中的命名冲突。所以上面的例子可以写为
<?xml version="1.0"?>
<Person>
<Name>Tom</Name>
<addr:Address xmlns:addr="http//www.google.com/address">
<addr:Street>XinHua .7</addr:Street>
<addr:City>BeiJing</addr:City>
</addr:Address>
<cont:Contact xmlns:cont="http//www.google.com/contact">
<cont:Address>Tom@hotmail.com</cont:Address>
<cont:Tel>010-123123123</cont:Tel>
</cont:Contact>
</Person>


上面知道了Namespace的作用是为elements和attribute命名的,而命名方式是[color=red]Two-Part Naming System[/color],又叫做[color=red]expanded name[/color]即是 local name + Namespace name。[color=red]所以对与任何一个element type 和 attribute 的名字都是由 local name+ Namespace name构成的。[/color]来看下W3对local name 和 Namespace name 是怎样定义的
[quote]For a name N in a namespace identified by a URI I, the namespace name is I. For a name N that is not in a namespace, the namespace name has no value.In either case the local name is N. [/quote]
举个例子
<?xml version="1.0"?>
<addr:Address xmlns:addr="http://www.google.com/address">Xinhua.7</addr:Address>

对于Element type Address而言,它属于"http://www.google.com/address"这个namespace,所以它的namespace name就是"httto://www.google.com/",local name就是Address
<?xml version="1.0"?>
<Address>Xinhua.7</Address>

对于Element type Address而言,[color=red]因为没有declare任何namespace,所以它不属于任何namespace,[/color]所以它的namespace name是has no value的,但是local name仍然是 Address。

判断XML中的两个Element type 或者两个attribute是否相同时,不但要看local name是否一致,还要判断它们的namespace name 是否相同,辨别namespace name是否相同,则要看URI reference 是不是一致,URI reference 是一系列的字符即字符串,当且仅当字符串内的每一个字符都是一致的时候,才能说URI reference是相同的。
(注意,一般URL reference用普通的URL表示就可以了,这个URL只是个identifier 标识符,并不要求可以 access any resource(并不要求可以到达指定的位置)。

上面定义中分了两种情况,一种是Name N(注意每当提到XML Name的时候,都是指XML中Element type的名字或者Attribute的名字) is in a namespace,另一种是is not in a namespace。可是又怎样区分一个NAME是否属于某个namespace呢,需要先来看下[color=red]XML是怎样声明一个namespace[/color]的

[quote]A namespace (or more precisely, a namespace binding) is declared using a family of reserved attributes. Such an attribute's name must either be xmlns or begin xmlns:. [/quote]

W3中明确说明,只有两种方式可以声明一个namespace
xmlns="......."
xmlns:NAME="......"
这两个keyword都是attribute name,统称为[color=red]NSAttName[/color]。 和
<?xml version="1.0"?>
<Person name="Tom"/>
中的属性name是一样的道理。
xmlns叫做 DefaultAttName,xmlns:NAME(此处的NAME可以是任何字符)叫做PrefixedAttName。
每当谈到一个attribute的时候,都应该想到attribute name和attribute value 例如上面的name是attribute name的名字(更准确的说,是attribute name的local name),"Tom"则是attribute value。
而对于属性 xmlns 或者 xmlns:NAME,它们的attribute value必须是URI reference或者空的字符串“”
<?xml version="1.0"?>
<Address xmlns="http://www.google.com/address"/>


<?xml version="1.0"?>
<Person xmlns:ns="http://www.google.com/person"/>

这两种方式,分别声明了名字(namespace name)为“http://www.google.com/address"的namespace 和名字为"http://www.google.com/person"的namespace。

这两种声明方式有很大的区别,区别主要在与:对Element type和attribute的作用不同,先来看 PrefixedAttName
xmlns:NAME,这个Name的作用是给namespace加了个前缀(give namespace a prefix),这个前缀是用来联系XML中的Element type 和 Attribute。例如
<?xml version="1.0"?>
<ns:Person xmlns:ns="http://www.google.com/person"/>

ns:Person,表明,Element Type Person 属于名字为“http://www.google.com/person"的namespace(Person is in this namespace) 那么对于Element type Person的namespace name 是"http://www.google.com/person/",local name是 Person.
对于下面的代码
<?xml version="1.0"?>
<Person xmlns:ns="http://www.google.com/person"/>
只能表示,声明了一个namespace,但是Element type:Person并不属于这个namespace。既然此处的person也没有被其他namespace的prefix限定,那么它的namespace name是has no value的。再重复一遍,不管这个Person属于不属于这个namespace 它的local name都是 Person。


仅仅知道如何声明namespace和如何将一个element type 或者 attribute加入到某个namespace还是不够的,还需要了解[color=red] namespace 的 scope (范围)[/color] [quote]The scope of a namespace declaration declaring a prefix extends from the beginning of the start-tag in which it appears to the end of the corresponding end-tag, [color=red]excluding[/color] the scope of any inner declarations with the same NSAttName part. In the case of an empty tag, the scope is the tag itself. [/quote]

意思是说,当用PrefixAttName的方式在一个Element的start-tag中声明的namespace,namespace的作用范围包括本身及所有的children,除去那些又被其他namespace 的prefix 覆盖了的element。(假如在xml文件的root element的start-tag中声明Prefix的namespace,那么这个prefix可以作用与整个xml document)
举个例子
<?xml version="1.0"?>
<addr:Address xmlns:addr="http//www.google.com/address"
xmlns:cont="http//www.google.com/contact">
<addr:Street>XinHua .7</addr:Street>
<addr:City>BeiJing</addr:City>
<cont:Address>Tom@hotmail.com</cont:Address>
<cont:Tel>010-123123123</cont:Tel>
</addr:Address>
注意可以在一个element的start-tag当中声明多个namespace,但是声明的方式必须是PrefixAttName,即xmlns:Name="....."。所声明的namespace的prefix可以不在当前的element中使用,甚至不用都可以。
可以看出 带有前缀cont的namespace是在Address的start-tag中声明的,但是前缀cont却在子元素中使用,同样,表示子元素的Element type Address与Tel 属于名字为“http://www.google.com/contact"的namespace。

再来看下[color=red]Default namespace的作用范围[/color]
所谓Default namespace 即是用DefaultAttName声明的namespace,xmlns="...."
[quote]
The scope of a

default namespace declaration extends from the beginning of the start-tag in which it appears to the end of the corresponding end-tag, excluding the scope of any inner default namespace declarations. In the case of an empty tag, the scope is the tag itself
[/quote]
对于Default namespace的声明,其作用范围和 Prefix namespace声明 是一样的,但是需要注意的是以下几点
[quote]A default namespace declaration applies to all unprefixed element names within its scope. Default namespace declarations do not apply directly to attribute names; the interpretation of unprefixed attributes is determined by the element on which they appear. [/quote]
1,Default namespace的声明,在其作用范围之内,对所有的unprefixed element type(无前缀的元素)都有 [color=red]默认将其添加到此namespace[/color]的作用,也就是说 如果在一个element的start-tag当中以 xmlns="...."方式声明了一个namespace,那么其当前元素及其子元素的所有的[color=red]unprefixed element type[/color]都是属于这个namespace的。
再重复一遍,既然这些unprefixed element type都属于这个namespace,那么他们的namespace name就是这个URI,local name当然还是自己了。

2,Default namespace的声明,在其作用范围之内,对所有的 [color=red]unprefixed attribute是没有直接作用的[/color],也就是说在这个作用范围之内的无前缀的attribute 并不属于这个默认的namespace,所以它们的namespace name是no value的,local name仍然是自己本身。
例如
<?xml version="1.0"?>
<Address xmlns="http//www.google.com/address">
<Street number="7">XinHua</Street>
<City>BeiJing</City>
</Address>

Element type Address,Street,City都是属于名字为"http://www.google.com/address"的namespace,但是 在element street中的属性number并不属于这个namespace。number的namespace name has no value,local name is number。

这时候,你肯定会想,假如我不想让其中的一个Element type属于这个默认的namespace,该怎么办。
在上面提到 对与attribute,xmlns或者xmlns:Name,他们的attribute value必须是URI或者是空字符“”,这里就用到了
<?xml version="1.0"?>
<Address xmlns="http//www.google.com/address">
<Street number="7">XinHua</Street>
<City xmlns="">BeiJing</City>
</Address>

可以在一个element的start-tag中声明 xmlns="",可以将此element及所有的子元素都跳出这个默认的namespace,当然对于Element type City来讲 它的namespace name是 has no value的,其local name 仍然是 City。


[size=large]Qualified Name[/size]

Qualified Name 分为两种

PrefixedName(有前缀)
UnPrefixedName(无前缀)

PrefixedName 格式是 Prefix:LocalName
UnPrefixedName 格式是 LocalName
注意此处的Prefix 并不是任何形式的字符都可以,Prefix必须是bound(附于)namespace 的前缀,即xmlns:Prefix="....."

Qualified Name 有两种不同的体现形式,一是在Element Type的体现
<?xml version="1.0"?>
<bk:Book xmlns:bk="http//www.google.com/book" price="500">
<bk:Title>I have a dream</bk:Title>
</bk:Book>

对于Element type Book,它的qualified name 是 bk:Book,
local name 是Book。
Element type Title,qualified name 是bk:Title
local name 是Title
二者的namespace name都为“http//www.google.com/book"
<?xml version="1.0"?>
<Book price="500">
<Title>I have a dream<Title>
<Book>
此处的 Element Type Book 的 qualified name是 Book
local name 是 Book
Element Type Title 的 qualified name是 Title
local name 是 Title
二者的namespace name 都是没有值的,has no value。

Qualified Name另一种体现形式 是在 Attribute 上的体现

首先来看下XML中 Attribute的格式

1,NSAttName=Attribute Value
2,Qualified Name=Attribute Value

NSAttName,上面已经说过是xmlns与xmlns:NAME的统称。
第一种格式 主要体现在 声明namespace(Namespace declaration)上。
注意 xmlns,xmlns:NAME可以作为attribute name 但是attribute value必须是 URI reference或者Empty String (xmlns:Name=URI/xmlns="")
<?xml version="1.0"?>
<bk:Book xmlns:bk="http://www.google.com/book" bk:price="500">
<bk:Title bk:language="English">I have a dream</bk:Title>
</bk:Book>
对于Attribute price,其qualified name 是 bk:price
local name是price
当然value 是 500
对于 Attribute language 其qualified name 是 bk:language
local name 是 language
二者的namespace name 是 “http://www.google.com/book"

最后需要注意的是 namespace name,local name,qualified name 都是针对 Element Type(Element Name) 或者 Attribute 而言的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值