4.7 使用<list…/>派生列表类型
Schema还允许由单个数据类型派生成相应的列表类型,就像在DTD中由IDREF派生出IDREFS那样。不同的是,Schema可以由任何类型派生出对应的列表类型,而且这种列表类型不仅可用于指定属性类型,也可用于指定元素的类型。
Schema内置类型中的IDREFS是IDREF的列表类型,ENTITIES是ENTITY的列表类型,NMTOKENS是NMTOKEN的列表类型。
Schema中定义列表类型使用<list…/>元素,它可由单个数据类型扩展出列表类型,因此使用该元素时必须指定列表元素的类型,为<list…/>元素指定列表元素类型有两种方式:
为<list…/>元素的itemType属性指定列表元素的数据类型。
为<list…/>元素增加<simpleType…/>子元素来指定列表元素的数据类型。
提示
上面两种用法依然是全局命名类型和局部匿名类型之间的区别。第1种用法中的item Type属性值必须是一个全局命名类型;而第2种用法中<simpleType…/>子元素定义的则是一种局部匿名类型。
下面的Schema文档使用<list…/>元素定义了一个列表类型:
程序清单:codes\04\4.7\list.xsd
上面的Schema中使用<simpleType…/>子元素为<list…/>元素指定列表元素类型,因此该列表元素类型是0~100之间的任意整数。如下XML文档是有效的:
程序清单:codes\04\4.7\list.xml
实际上,<list…/>元素也可以使用itemType属性指定列表元素的数据类型,因此完全可以将上面的Schema改为如下形式:
需要指出的是,列表类型的值是以空白作为分隔符的,因此通常没有必要使用为string、normalizedString、token等元素建立列表类型,因为它们本身就可包含空格。
注意
列表类型对空白的处理方式是先将所有空白(包括回车、换行和制表符)替换成空格,然后去除内容前后的空格,再将内容中间的多个连续空格压缩成单个空格——这个空格将作为列表元素的分隔符。
4.7.1 限制列表类型
列表类型同样可通过添加约束来派生新的列表类型,Schema允许为列表类型增加如下几类约束:
长度约束:length、maxLength和minLength。
枚举约束:enumeration。
正则表达式约束:pattern。
空白处理:whiteSpace。
其中length用于限制列表类型的值所包含的列表元素必须是length个;类似地,maxLength和minLength分别用于限制列表类型的值所包含的列表元素必须小于等于maxLenth个和大于等于minLength个。
whiteSpace约束的值则只能是collapse。
假设需要定义一个<price…/>元素,该元素的内容必须是4个价格,每个价格都是0~100之间的decimal数值,且小数点后必须有2位数字。其代码如下:
程序清单:codes\04\4.7\price_list.xsd
上面的Schema中使用<simpleType…/>元素定义了一个匿名的列表类型作为<restriction…/>元素的子元素,也就是作为被限制的基类型,接着使用length约束指定该列表类型必须包含4项列表值。对于上面的Schema文档,如下XML文档是有效的:
程序清单:codes\04\4.7\price_list.xml
enumeration和pattern两种约束用起来非常容易混淆,其主要原因是对列表类型增加enumeration和epattern约束时,是对整个列表内容起作用,而不是对单个的列表项起作用。
例如定义一个<emails…/>元素,如果希望该元素的内容是一个满足指定正则表达式的列表,则应该按如下方式定义Schema:
程序清单:codes\04\4.7\emails_list.xsd
对于上面的Schema,如下XML文档是有效的:
程序清单:codes\04\4.7\emails_list.xml
细心的读者可能已经发现,上面在定义Schema时并没有为<list…/>元素增加pattern约束,而是先为string类型增加pattern约束派生出email_Type类型,然后再将email_Type派生成对应的列表类型。如果将上面的Schema文档改为如下形式:
程序清单:codes\04\4.7\emails_list2.xsd
如上所示Schema才是对列表类型应用pattern约束,但这种约束要求列表内容整体(多个列表项及空格组成的整体)必须匹配指定的正则表达式,这显然不是我们想要的结果。
注意
对于列表类型应用enumeration和pattern约束时,是对列表内容整体(多个列表项及括空格组成的整体)起作用,而不是对单个的列表元素起作用。