有的xsd文件的开头是这样写的:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.abc.com"
xmlns:ps="http://www.abc.com"
elementFormDefault="qualified">
一个schema中声明的元素或者类型只能归到两个命名空间中的某一个去,这两个是,无名命名空间和由targetSchema属性指明的目标命名空间。而targetSchema属性只能在xs:schema的定义中声明,因而,一个schema中的定义的元素或类型只可能归属于一个有名命名空间(但是还有可能归属于无名命名空间)。
需要明白的是,elementFormDefault="?" 是有作用域的,并且是被继承的,除非在子定义中覆盖父定义。
下面三个例子说明了elementFormDefault的使用效果。红色表示属于已命名空间的元素,蓝色表示属于未命名空间的元素。
1.定义了目标命名空间, 全局elementFormDefault=“unqualified”。这时除了全局元素或者类型将归于目标命名空间外,局部元素将归于无名命名空间。
unqualified.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="aaaa" elementFormDefault="unqualified" attributeFormDefault="unqualified">
<xs:element name="c">
<xs:complexType>
<xs:sequence>
<xs:element name="c1" type="xs:double"/>
<xs:element name="c2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
unqualified.xml
<?xml version="1.0" encoding="UTF-8"?>
<n:c xmlns:n="aaaa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="aaaa unqualified.xsd">
<c1> 3.141593E0</c1>
<c2> String</c2>
</n:c>
2. 定义了目标命名空间, 全局elementFormDefault=“qualified”。这时全局元素或者类型将归于目标命名空间,局部元素将以缺省方式归于目标命名空间。
qualified.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="aaaa" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="c">
<xs:complexType>
<xs:sequence>
<xs:element name="c1" type="xs:double"/>
<xs:element name="c2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
qualified.xml
<?xml version="1.0" encoding="UTF-8"?>
<c xmlns="aaaa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="aaaa qualified.xsd">
<c1> 3.141593E0</c1>
<c2> String</c2>
</c>
3. 定义了目标命名空间, 全局elementFormDefault=“unqualified”。这时全局元素(c)或者类型将归于目标命名空间。局部元素(c1,c2)以缺省方式归于无名命名空间。局部元素(c3)在局部定义中使用form=“qualified”覆盖全局设定的 unqualified,这使得c3归于目标命名空间(如果它有子元素,子元素将以缺省方式归于目标命名空间)。
qualified2.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="aaaa" elementFormDefault="unqualified" attributeFormDefault="unqualified">
<xs:element name="c">
<xs:complexType>
<xs:sequence>
<xs:element name="c1" type="xs:double"/>
<xs:element name="c2" type="xs:string"/>
<xs:element name="c3" type="xs:integer" form="qualified" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
qualified2.xml
<?xml version="1.0" encoding="UTF-8"?>
<n:c xmlns:n="aaaa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="aaaa qualified2.xsd">
<c1> 3.141593E0</c1>
<c2> String</c2>
<n:c3> 0</n:c3>
</n:c>
相信使用过这个属性的朋友大都会被这个属性搞得比较迷惑,使用过程中经常会莫名其妙的校验报错,对照文档解释,觉得没什么错啊,如果换一种写法或者设置又可以了,但是就是说不清为什么。
关于这个属性官方文档上的语焉不详,网上网友就这个属性讨论也是各有各的看法,莫衷一是。网上比较典型的一个讨论帖子是:请问Schema中elementFormDefault="qualified"是起什么作用呀?(http://www.xml.org.cn/dispbbs.asp?BoardID=23&id=25672&replyID=17053&star=1&skin=0)
以下是在做了许多试验,对照MSDN上的说法,参照网友的讨论得出的看法
先看MSDN中elementFormDefault 属性的解释:
在该架构的目标命名空间中声明的元素的形式。该值必须是下列字符串之一:qualified 或 unqualified。默认值为 unqualified。
如果该值是 unqualified,则无须通过命名空间前缀限定目标命名空间的元素。
如果该值是 qualified,则必须通过命名空间前缀限定目标命名空间的元素。
MSDN的描述不完整,完整的应该是:
如果该值是 unqualified,实例xml的根元素必须有命名空间的的限定,这个命名空间必须是schema中定义的targetNameSpace。但是其下子元素无须也不允许用命名空间前缀限定目标命名空间。 子元素的命名空间为空命名空间。
如果该值是 qualified,实例xml根元素及其下所有子元素都必须通过命名空间前缀限定目标命名空间。这个命名空间必须是schema中定义的targetNameSpace。
再看xml实例中根元素和子元素的命名空间的设置:
1. 通过prefix定义命名空间
在根元素的属性中使用 xmlns:xxx = url 的语法来定义一个名称空间的前缀xxx,然后在需要用这个名称空间限定的元素前面加上前缀和冒号,例如:
<?xml version="1.0" encoding="UTF-8"?>
<n:c xmlns:n="aaaa">
<n:c1>3.141593E0 </n:c1>
<n:c2>String</n:c2>
<c3>0</c3>
</n:c>
这个xml实例中定义了一个叫“aaaa”的前缀,在元素名称前面加了”n:”的元素都会拥有”aaaa”的命名空间,没有加前缀的元素(c3)将没有命名空间的限定,它的命名空间属性为””。
2. 通过默认命名空间定义全部元素的命名空间
根元素的单独的xmlns 属性定义一个xml实例的默认命名空间,其下的元素除了另外设置了前缀,都将被默认命名空间限定。例如:
<?xml version="1.0" encoding="UTF-8"?>
<c xmlns ="aaaa">
<c1>3.141593E0 </c1>
<c2>String</ c2>
<c3>0</c3>
</n:c>
这个xml实例中所有元素(c,c1,c2,c3)的命名空间都是“aaaa”
总结:
elementFormDefault 属性只是用来设置xml的实例中子元素是否一定需要有命名空间限定,不控制xml实例中各元素归属哪个命名空间。xml实例中元素的命名空间由xml实例本身的设置决定。