用過 XML 的人都知道可用 DTD(Document Type Definition) 來驗證語法,不過微軟主導了新一代驗證語法的 XML Schema,並且風頭正勁,大有一統江湖之勢。看看我們身邊的幾個變化就明白了。
web.XML 從 web-app_2_3.dtd 到 web-app_2_4.xsd
spring 配置文件從 spring-beans.dtd 到 spring-beans-2.0.dtd 到 spring-beans-2.0.xsd,直至靈活的自定義 Schema
quartz_jobs.XML 配置文件從 job_scheduling_data_1_5.dtd 到 job_scheduling_data_1_5.xsd
XML Schema 簡介
XML Schema 是一個比 DTD 具有更細致描述語法功能的驗證技術,並且它本身也是一個 XML 文件,不像 DTD 用是是獨有的語法。既然 XML Schema 和 DTD 都是用來驗證 XML 的,並能大搶風頭,固然有它值得稱道的地方。所以先說說 DTD 的的不足和 XML Schema 的特點。
1)DTD 使用自有語法,XML Schema 本身就為 XML 件,避免了學習新的語法。
2)DTD 對數據類型支持極有限,也就 #PCDATA,而 XML Schema 可支持字符串、整數、浮點數;布爾值、時間、日期等。
3)DTD 所支持的結構定義靈活性過低,可以表示 ?(零個或一個),*(零個或多個),+(一個或多個),但對於像正則表達式的 {m,n} 無能為力;而 XML Schema 有了 minOccur 和 maxOccur 達到控制子元素出現 的次數的目的。
4)DTD 屬於封閉式架構,也就是所有 XML 文件中所要用的標記與屬性都必須先在 DTD 中聲明才能被使用。而 XML Schema 采用開放式架構,不要求 XML 中所有的元素與屬性必須先聲明再使用。
5)一個 XML 的 DTD 將會作用於整份 XML 文件,而無法將 XML 文件的某部分指定另外的 DTD。而 XML Schema 可針對個別元素指定不同的 Schema,最小的切割單位可以是一個標記。
這就是我們看到應用 DTD 的 web.XML 要在最前面寫上 <!DOCTYPE web-app PUBLIC ......web-app_2_3.dtd">,它作用與整份文檔。
注意到應用 XML Shema 的 web.xml,Shema 是指定為 web-app 的屬性,<web-app xsi:schemaLocation="......web-app_2_4.xsd">,其他元素可單獨指定 XML Schema。
6)XML Schema 由於是一個 XML 文件,所以可通過 DOM 動態修改語法規則,而 DTD 做不到。除此之外,XML Schema Extension 還允許新增一些額外的信息以輔助描述數據。
7)XML Schema 使用的是命名空間,因此具有可擴展性。這一點在 spring 2.x 的配置文件中身手大顯,支持自定的 XML Schema,如引入 spring-aop-2.0.xsd 和 spring-tx-2.0.xsd,分別用 <aop:config> 和 <tx:advice> 等。
XML Schema 的基礎
XML Schema 雖然是由微軟首先提出,也已被 W3C 接受並審查,但仍然衍生出兩個標准來,MS 的和 W3C 的。微軟的 XML Schema 版本稱為 XDR(XML Data Reduced),Schema 擴展名為 "xml";而 W3C 的 XML Schema 版本則稱為 XSD(XML Schema Definition) 或 XSDL(XML Schema Definition Language),擴展名為 "xsd"。而本人主要守在 Java 陣營,基本使用的都是 XSD,看我們的新式 web.xml 和 spring 配置文件就用的 xsd 文件,因此以 W3C 標准來介紹 XML Schema 的使用。
XML 都可以在內部或外面使用 DTD 或 Schema,但對於外部的 DTD 用的是 <!DOCTYPE> 指定,而外部的 Schema,XML 要借助於命名空間。如
<programming_team xmlns="x-schema:schema1.XML">
<programmer>Fred Samson</programmer>
</programming_team>
微軟件的東西(像 Internet Explorer)看到了以 "x-schema:" 開頭的命名空間就知道是指向一個模式(關於如果在 XML 內部聲明使用 Schema,可以參考 BlogJava 的數據備份生成的 MyBlogData.XML 文件)。
然而一般情況下(W3C),為文檔節點指向一個模式的命名空間,參照 Spring 2.0 的 applicationContext.XML 就能很好的理解:
<?XML version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" XMLns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<aop:config>
<aop:advisor id="userManagerTx" advice-ref="userManagerTxAdvice" pointcut="execution(* *..service.IUserManager.*(..))"/>
</aop:config>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
.....................
</tx:attributes>
</tx:advice>
<bean id="userManager" class="com.com.security.service.UserManagerImpl">
<property name="userDao" ref="userDao"/>
</bean>
.....................
</beans>
<?XML version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" XMLns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<aop:config>
<aop:advisor id="userManagerTx" advice-ref="userManagerTxAdvice" pointcut="execution(* *..service.IUserManager.*(..))"/>
</aop:config>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
.....................
</tx:attributes>
</tx:advice>
<bean id="userManager" class="com.com.security.service.UserManagerImpl">
<property name="userDao" ref="userDao"/>
</bean>
.....................
</beans>
必須為文檔中的元素聲明一個指向模式的命名空間(如:xmlns="http://www.springframework.org/schema/beans"),XML 解析器從描述中尋找模式,在 xsi:schemaLocation 的屬性就能看到命名空間與 Schema xsd 文件 URI(http://www.springframework.org/schema/beans/spring-beans-2.0.xsd) 的對應,在這個 xsd 文件裡有一個目標命名空間(targetNamespace),解析器驗證了這個目標命名空間與文檔的相同時,就可以用它來驗證文檔的有效性了。
欲加深印象,還可以看看別的使用了 Schema 的常見 XML 文檔,如 2.4 的 web.xml 文件,本篇限於篇幅,暫告一段落,後續將更詳細說明 W3C 的 XML Schema 的用法。
剛剛看到一個 Tapestry 5 的一個自定義模板寫法是(from http://www.Javaeye.com/news/3331):
<Html XMLns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
<title>Tapestry5 Experiments</title>
</head>
<body>
<div id="wrap">
<t:body/>
</div>
</body>
</Html>
<Html XMLns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
<title>Tapestry5 Experiments</title>
</head>
<body>
<div id="wrap">
<t:body/>
</div>
</body>
</Html>
這裡 XMLns:t 指定的 http://tapestry.apache.org/schema/tapestry_5_0_0.xsd 除了這是一個 Namespace 的 URI,同時也是一個 Schema 嗎?應該不能兼做 Schema 驗證的功能。