在前面的XSD筆記中,基本上是以數據類型為主線來寫的,而在我的實際開發過程中,是先設計好了XML的結構(元素、屬性),並寫好了一份示例,然后再反過來寫XSD文件(在工具生成的基礎上修改),也就是說,是以XML結構為主線的。而我在學習XSD的時候,則是以能否看懂spring-beans-3.2.xsd這個文件來檢測自己,我的想法很簡單,這個文件已經夠復雜——對我來說——如果能夠看懂這個文件,那基本上已經夠我用的了,倘若實際開發的時候遇到超出這個范圍的,那到時候再找相關資料學習也不晚。
一、為XML結構編寫相應XSD片段
1、定義一個沒有屬性也沒有內容的元素——沒有屬性的空元素:
<xs:element name="emptyElement"> <xs:complexType> <!--既然XML文件中所有能出現的元素和屬性都必須在XSD中出現,那么什么都沒定義的意思就是什么都不能出現了--> </xs:complexType> </xs:element>
2、定義一個沒有內容的元素,但是這個元素有兩個屬性,一個必須的id屬性,一個可選的name屬性:
<xs:element name="emptyElementWithAttribute"> <xs:complexType> <xs:attribute name="id" type="xs:ID" use="required"/> <xs:attribute name="name" type="xs:NMTOKEN" default="未定義"/> </xs:complexType> </xs:element>
3、定義有內容但是沒有屬性的元素——簡單元素
<!--1.使用內建類型,內容為字符串--> <xs:element name="simpleElement1" type="xs:string"/> <!--2.使用約束派生,內容為長度在6至16之間的字符串--> <xs:element name="simpleElement2"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:annotation> <xs:documentation><![CDATA[ 長度大於或等於6,小於或等於16的字符串 ]]></xs:documentation> </xs:annotation> <xs:minLength value="6"/> <xs:maxLength value="16"/> </xs:restriction> </xs:simpleType> </xs:element> <!--3.使用列表派生,內容為已經存在的一個或多個ID類型數據的列表--> <xs:element name="simpleElement3"> <xs:simpleType> <xs:list itemType="xs:IDREF"/> </xs:simpleType> </xs:element> <!--4.使用聯合派生,內容可以是整型,也可以是NMTOKEN類型--> <xs:element name="simpleElement4"> <xs:simpleType> <xs:union memberTypes="xs:int xs:NMTOKEN"/> </xs:simpleType> </xs:element>
4、定義只包含子元素的元素,不能包含內容,但可以包含屬性
<!-- 空類型 --> <xs:complexType name="emptyType"> </xs:complexType> <!-- 表類別類型(簡單枚舉類型) --> <xs:simpleType name="tableTypeType"> <xs:restriction base="xs:string"> <xs:enumeration value="系統表"/> <xs:enumeration value="參數表"/> <xs:enumeration value="數據表"/> </xs:restriction> </xs:simpleType> <!-- 名稱類型(2-30位的字符串) --> <xs:simpleType name="nameType"> <xs:restriction base="xs:NCName"> <xs:minLength value="2"/> <xs:maxLength value="30"/> </xs:restriction> </xs:simpleType> <!-- 注釋類型(2-1024位的字符串) --> <xs:simpleType name="commentType"> <xs:restriction base="xs:string"> <xs:minLength value="2"/> <xs:maxLength value="1024"/> </xs:restriction> </xs:simpleType> <!-- 字段元素(含屬性不含內容元素)--> <xs:element name="field"> <xs:complexType> <xs:complexContent> <xs:extension base="emptyType"> <xs:attribute name="fieldName" type="nameType" use="required"/> <xs:attribute name="dataType" type="xs:NCName" use="required"/> <xs:attribute name="length" type="xs:int" use="optional"/> <xs:attribute name="comment" type="commentType" use="optional"/> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> <!-- 表元素(含屬性和子元素的元素) --> <xs:element name="table"> <xs:complexType> <xs:sequence> <xs:element minOccurs="1" maxOccurs="unbounded" ref="field" /> </xs:sequence> <xs:attribute name="tableName" type="nameType" use="required"/> <xs:attribute name="tableType" type="tableTypeType" use="required"/> <xs:attribute name="comment" type="commentType" use="optional"/> </xs:complexType> <xs:key name="fieldKey"> <xs:selector xpath="field"/> <xs:field xpath="@fieldName"/> </xs:key> </xs:element>
這里有一個疑問,在最后定義的時候,我添加了一個key約束,本意是想在一個table元素里所有的field元素中fieldName屬性必須存在且唯一,但是我在實際配置XML文檔時,在兩個field中相同的fieldName也沒有報錯,不知道是哪里寫錯了。
5、定義既包含子元素又包含內容的混合元素,同時也可以擁有屬性
比如將上面例子中<table>元素修改為可以包括內容,可以在<xs:complexType>加一個mixed="true"屬性:
<!-- 表元素(含屬性、內容和子元素的元素) --> <xs:element name="table"> <xs:complexType mixed="true"> <xs:sequence> <xs:element minOccurs="1" maxOccurs="unbounded" ref="field" /> </xs:sequence> <xs:attribute name="tableName" type="nameType" use="required"/> <xs:attribute name="tableType" type="tableTypeType" use="required"/> <xs:attribute name="comment" type="commentType" use="optional"/> </xs:complexType> </xs:element>
二、spring-beans-3.2.xsd
我將這個文件放在這里,每次看的時候都能夠檢測一下(其中以<annotation>元素描述的注釋內容去掉了,並簡單修改了一小部分寫法):
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <xsd:schema xmlns="http://www.springframework.org/schema/beans" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.springframework.org/schema/beans"> <!--導入命名空間,並保持原命名空間--> <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> <!--定義抽象的id標識類型,供后文引用,而不能直接在XML中使用--> <xsd:complexType name="identifiedType" abstract="true"> <xsd:attribute name="id" type="xsd:string"/> </xsd:complexType> <!--定義根元素beans,包含子元素的復雜類型元素--> <xsd:element name="beans"> <xsd:complexType> <xsd:sequence> <!--首先是描述信息,可以出現,也可以不出現--> <xsd:element ref="description" minOccurs="0"/> <!--然后是主體部分,這里使用相當於DTD中的 (e1|e2|e3)* 結構實現自由組合的無序元素 --> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="import"/> <xsd:element ref="alias"/> <xsd:element ref="bean"/> <!--除了使用當前XSD文件的元素,還以使用導入的其它XSD文件中定義的元素,不過必須先獲取相應的XSD文件,並做嚴格的校驗--> <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/> </xsd:choice> <!--從這里可以看到,原來beans這個元素還可以嵌套,大體作用相當於import吧,只是import導入的就不是本地的配置,而嵌套的應該還屬於本地的配置(?)--> <xsd:element ref="beans" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> <xsd:attribute name="profile" use="optional" type="xsd:string"/> <!--對於多個地方都使用的true|false|default,將其定義為一個自定義數據類型,然后再在需要的地方引用--> <xsd:attribute name="default-lazy-init" default="default" type="defaultable-boolean"/> <xsd:attribute name="default-merge" default="default" type="defaultable-boolean"/> <xsd:attribute name="default-autowire" default="default"> <xsd:simpleType> <!--通過限制定義自動包裝的枚舉類型--> <xsd:restriction base="xsd:NMTOKEN"> <xsd:enumeration value="default"/> <xsd:enumeration value="no"/> <xsd:enumeration value="byName"/> <xsd:enumeration value="byType"/> <xsd:enumeration value="constructor"/> </xsd:restriction> </xsd:simpleType> </xsd:attribute> <xsd:attribute name="default-autowire-candidates" type="xsd:string"/> <xsd:attribute name="default-init-method" type="xsd:string"/> <xsd:attribute name="default-destroy-method" type="xsd:string"/> <!--還可以有其它命名空間的屬性,並且不會做強制的檢查--> <xsd:anyAttribute namespace="##other" processContents="lax"/> </xsd:complexType> </xsd:element> <!--定義描述信息元素,混合內容元素--> <xsd:element name="description"> <xsd:complexType mixed="true"> <xsd:choice minOccurs="0" maxOccurs="unbounded"/> </xsd:complexType> </xsd:element> <xsd:element name="import"> <xsd:complexType> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="resource" type="xsd:string" use="required"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="alias"> <xsd:complexType> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="name" type="xsd:string" use="required"/> <xsd:attribute name="alias" type="xsd:string" use="required"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:group name="beanElements"> <xsd:sequence> <xsd:element ref="description" minOccurs="0"/> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="meta"/> <xsd:element ref="constructor-arg"/> <xsd:element ref="property"/> <xsd:element ref="qualifier"/> <xsd:element ref="lookup-method"/> <xsd:element ref="replaced-method"/> <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/> </xsd:choice> </xsd:sequence> </xsd:group> <xsd:attributeGroup name="beanAttributes"> <xsd:attribute name="name" type="xsd:string"/> <xsd:attribute name="class" type="xsd:string"/> <xsd:attribute name="parent" type="xsd:string"/> <xsd:attribute name="scope" type="xsd:string"/> <xsd:attribute name="abstract" type="xsd:boolean"/> <xsd:attribute name="lazy-init" default="default" type="defaultable-boolean"/> <xsd:attribute name="autowire" default="default"> <xsd:simpleType> <xsd:restriction base="xsd:NMTOKEN"> <xsd:enumeration value="default"/> <xsd:enumeration value="no"/> <xsd:enumeration value="byName"/> <xsd:enumeration value="byType"/> <xsd:enumeration value="constructor"/> </xsd:restriction> </xsd:simpleType> </xsd:attribute> <xsd:attribute name="depends-on" type="xsd:string"/> <xsd:attribute name="autowire-candidate" default="default" type="defaultable-boolean"/> <xsd:attribute name="primary" type="xsd:boolean"/> <xsd:attribute name="init-method" type="xsd:string"/> <xsd:attribute name="destroy-method" type="xsd:string"/> <xsd:attribute name="factory-method" type="xsd:string"/> <xsd:attribute name="factory-bean" type="xsd:string"/> <xsd:anyAttribute namespace="##other" processContents="lax"/> </xsd:attributeGroup> <xsd:element name="meta" type="metaType"/> <xsd:complexType name="metaType"> <xsd:attribute name="key" type="xsd:string" use="required"/> <xsd:attribute name="value" type="xsd:string" use="required"/> </xsd:complexType> <xsd:element name="bean"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="identifiedType"> <xsd:group ref="beanElements"/> <xsd:attributeGroup ref="beanAttributes"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="constructor-arg"> <xsd:complexType> <xsd:sequence> <xsd:element ref="description" minOccurs="0"/> <xsd:choice minOccurs="0" maxOccurs="1"> <xsd:element ref="bean"/> <xsd:element ref="ref"/> <xsd:element ref="idref"/> <xsd:element ref="value"/> <xsd:element ref="null"/> <xsd:element ref="array"/> <xsd:element ref="list"/> <xsd:element ref="set"/> <xsd:element ref="map"/> <xsd:element ref="props"/> <xsd:any namespace="##other" processContents="strict"/> </xsd:choice> </xsd:sequence> <xsd:attribute name="index" type="xsd:string"/> <xsd:attribute name="type" type="xsd:string"/> <xsd:attribute name="name" type="xsd:string"/> <xsd:attribute name="ref" type="xsd:string"/> <xsd:attribute name="value" type="xsd:string"/> </xsd:complexType> </xsd:element> <xsd:element name="property" type="propertyType"/> <xsd:element name="qualifier"> <xsd:complexType> <xsd:sequence> <xsd:element ref="attribute" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> <xsd:attribute name="type" type="xsd:string" default="org.springframework.beans.factory.annotation.Qualifier"/> <xsd:attribute name="value" type="xsd:string"/> </xsd:complexType> </xsd:element> <xsd:element name="attribute" type="metaType"/> <xsd:element name="lookup-method"> <xsd:complexType> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="name" type="xsd:string"/> <xsd:attribute name="bean" type="xsd:string"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="replaced-method"> <xsd:complexType> <xsd:sequence> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="arg-type"/> </xsd:choice> </xsd:sequence> <xsd:attribute name="name" type="xsd:string"/> <xsd:attribute name="replacer" type="xsd:string"/> </xsd:complexType> </xsd:element> <xsd:element name="arg-type"> <xsd:complexType mixed="true"> <xsd:choice minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="match" type="xsd:string"/> </xsd:complexType> </xsd:element> <xsd:element name="ref"> <xsd:complexType> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="bean" type="xsd:string"/> <xsd:attribute name="local" type="xsd:string"/> <xsd:attribute name="parent" type="xsd:string"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="idref"> <xsd:complexType> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="bean" type="xsd:string"/> <xsd:attribute name="local" type="xsd:string"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="value"> <xsd:complexType mixed="true"> <xsd:choice minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="type" type="xsd:string"/> </xsd:complexType> </xsd:element> <xsd:element name="null"> <xsd:complexType mixed="true"> <xsd:choice minOccurs="0" maxOccurs="unbounded"/> </xsd:complexType> </xsd:element> <!-- Collection Elements --> <xsd:group name="collectionElements"> <xsd:sequence> <xsd:element ref="description" minOccurs="0"/> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="bean"/> <xsd:element ref="ref"/> <xsd:element ref="idref"/> <xsd:element ref="value"/> <xsd:element ref="null"/> <xsd:element ref="array"/> <xsd:element ref="list"/> <xsd:element ref="set"/> <xsd:element ref="map"/> <xsd:element ref="props"/> <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="unbounded"/> </xsd:choice> </xsd:sequence> </xsd:group> <xsd:element name="array"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="listOrSetType"> <xsd:attribute name="merge" default="default" type="defaultable-boolean"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="list"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="listOrSetType"> <xsd:attribute name="merge" default="default" type="defaultable-boolean"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="set"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="listOrSetType"> <xsd:attribute name="merge" default="default" type="defaultable-boolean"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="map"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="mapType"> <xsd:attribute name="merge" default="default" type="defaultable-boolean"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="entry" type="entryType"/> <xsd:element name="props"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="propsType"> <xsd:attribute name="merge" default="default" type="defaultable-boolean"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> <xsd:element name="key"> <xsd:complexType> <xsd:group ref="collectionElements"/> </xsd:complexType> </xsd:element> <xsd:element name="prop"> <xsd:complexType mixed="true"> <xsd:choice minOccurs="0" maxOccurs="unbounded"/> <xsd:attribute name="key" type="xsd:string" use="required"/> </xsd:complexType> </xsd:element> <xsd:complexType name="propertyType"> <xsd:sequence> <xsd:element ref="description" minOccurs="0"/> <xsd:choice minOccurs="0" maxOccurs="1"> <xsd:element ref="meta"/> <xsd:element ref="bean"/> <xsd:element ref="ref"/> <xsd:element ref="idref"/> <xsd:element ref="value"/> <xsd:element ref="null"/> <xsd:element ref="array"/> <xsd:element ref="list"/> <xsd:element ref="set"/> <xsd:element ref="map"/> <xsd:element ref="props"/> <xsd:any namespace="##other" processContents="strict"/> </xsd:choice> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required"/> <xsd:attribute name="ref" type="xsd:string"/> <xsd:attribute name="value" type="xsd:string"/> </xsd:complexType> <!-- base type for collections that have (possibly) typed nested values --> <xsd:complexType name="collectionType"> <xsd:attribute name="value-type" type="xsd:string"/> </xsd:complexType> <!-- 'list' and 'set' collection type --> <xsd:complexType name="listOrSetType"> <xsd:complexContent> <xsd:extension base="collectionType"> <xsd:group ref="collectionElements"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> <!-- 'map' element type --> <xsd:complexType name="mapType"> <xsd:complexContent> <xsd:extension base="collectionType"> <xsd:sequence> <xsd:element ref="description" minOccurs="0"/> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="entry"/> </xsd:choice> </xsd:sequence> <xsd:attribute name="key-type" type="xsd:string"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> <!-- 'entry' element type --> <xsd:complexType name="entryType"> <xsd:sequence> <xsd:element ref="key" minOccurs="0"/> <xsd:group ref="collectionElements"/> </xsd:sequence> <xsd:attribute name="key" type="xsd:string"/> <xsd:attribute name="key-ref" type="xsd:string"/> <xsd:attribute name="value" type="xsd:string"/> <xsd:attribute name="value-ref" type="xsd:string"/> <xsd:attribute name="value-type" type="xsd:string"/> </xsd:complexType> <!-- 'props' collection type --> <xsd:complexType name="propsType"> <xsd:complexContent> <xsd:extension base="collectionType"> <xsd:sequence> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="prop"/> </xsd:choice> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <!-- 將true|false|default定義為枚舉布爾類型--> <xsd:simpleType name="defaultable-boolean"> <xsd:restriction base="xsd:NMTOKEN"> <xsd:enumeration value="default"/> <xsd:enumeration value="true"/> <xsd:enumeration value="false"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>