日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
使用CAM機(jī)制提高XML驗(yàn)證水平

【獨(dú)家特稿】CAM即內(nèi)容裝配機(jī)制(Content Assembly Mechanism),它是一個XML結(jié)構(gòu)驗(yàn)證方法,由于它是一個新生事物,文檔很少,因此本文就當(dāng)掃盲了。

站在用戶的角度思考問題,與客戶深入溝通,找到宜興網(wǎng)站設(shè)計(jì)與宜興網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、主機(jī)域名、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋宜興地區(qū)。

XML文檔的驗(yàn)證需要確認(rèn)文檔是完整的,并且符合在文檔類型定義(Document Type Definition 即DTD)中指定的規(guī)則,DTD是最早的規(guī)范說明方法,它提供了有用但有限的功能來驗(yàn)證XML文檔結(jié)構(gòu),但只有一點(diǎn)語義;接著出現(xiàn)了XML Schema,它提供了更多靈活性和功能,增強(qiáng)了對結(jié)構(gòu)的支持,并且很好地支持了語義,Schematron,RelaxNG已經(jīng)嘗試提升對語義的支持,但都沒有取得什么進(jìn)展;現(xiàn)在一種全新的技術(shù)在OASIS的保護(hù)下開發(fā)出來了,它就是CAM。

CAM不僅是一門schema語言,其設(shè)計(jì)目的是更好地滿足業(yè)務(wù)交流和互操作性要求,它提供了強(qiáng)有力的機(jī)制來驗(yàn)證XML結(jié)構(gòu)和語義,使其簡潔、易于使用和易于維護(hù);它提供了一個上下文機(jī)制 -- 一種基于XML自身其它部分或外部參數(shù)來動態(tài)調(diào)整那些應(yīng)被視為有效的XML實(shí)例。

CAM是一個令人興奮的技術(shù),它的未來充滿希望,但它是一個新技術(shù),可能有好有壞;CAM的開發(fā)非常迅速,因此在本文中,你可能會發(fā)現(xiàn)很多‘在寫本文的時候’的字眼。開發(fā)團(tuán)隊(duì)也很勤奮,你反饋的問題可能很快就會得到修復(fù),而且有些問題可能你還沒有發(fā)現(xiàn)就已經(jīng)被修復(fù)了。

因此,在寫本文的時候,CAM文檔還很潦草:有一個正式的規(guī)范,一份白皮書,一份PowerPoint演示文稿和一些簡要介紹了編輯器和API的網(wǎng)頁。還沒有明確的指導(dǎo)和教程,本文的目標(biāo)就是:“CAM:缺少的手冊”,擴(kuò)大CAM文檔陣營。

你需要

◆基本上熟悉XPath,CAM大量使用了Xpath定義業(yè)務(wù)規(guī)則,請參考w3School的Xpath教程溫習(xí)一下。

◆基本上熟悉XML Schema,雖然本文表面上看起來是XML Schema的繼承,因?yàn)樗鼜V泛地依賴于與XML Schema的對比,作為最有效的溝通方法,請參考w3School的XML Schema教程溫習(xí)一下。

規(guī)定合法XML

XML文檔是元素的多層次組合,它是一個用于存儲任何數(shù)量文字或數(shù)據(jù)結(jié)構(gòu)的樹狀存儲結(jié)構(gòu),XML文檔需要很好的格式,這意味著它只有一個根,其元素和屬性必須符合簡單的XML語法規(guī)則,在XML沒有映射到特定的問題域(如數(shù)學(xué)、書籍協(xié)作或金融交易)之前,它都沒什么用處,這種映射將抽象的XML區(qū)域以一種專業(yè)XML語言與你的特定問題對應(yīng)起來,任何專用語義都必須事先定義好,否則就會被認(rèn)為是無效的,遭到拒絕。

思考一下下面的顧客地址:

﹤address﹥
﹤address_street﹥221B Baker Street﹤/address_street﹥
. . .
﹤/address﹥

為了在XML Schema中驗(yàn)證這個XML片段,你通常會定義一個如下的結(jié)構(gòu):

﹤xs:element name="address"/﹥
. . .
﹤xs:element name="address_street" type="xs:string"/﹥
. . .
﹤/xs:element﹥

這些限制條件指出﹤address_street﹥元素必須存在,并且必須包含在﹤address﹥元素內(nèi),還必須包含一個字符串。對于一個地址而言,一個簡單的字符串值可能是適當(dāng)?shù)模渌侄文銘?yīng)該使用更具體的東西,要么是一個專門的字符串(一種衍生的,有限制的字符串)、日期、整數(shù)或其它定義類型。
XML Schema是一種基于語法的系統(tǒng),在它里面你需要同時為語義和結(jié)構(gòu)定義語法;另一方面,Schematron是一個基于規(guī)則的系統(tǒng),你可以使用規(guī)則同時指定語義和結(jié)構(gòu),即你不僅使用規(guī)則指定address_street是一個字符串,還用規(guī)則指定﹤address_street﹥必須顯示在﹤address﹥元素內(nèi),XML Schema和Schematron從根本上說語義和結(jié)構(gòu)都是糾纏在一起的。在編程方面耦合度很高,這是不可取的。
相比之下,CAM是一個混合系統(tǒng),它將結(jié)構(gòu)從語義中獨(dú)立出來(低耦合),使用規(guī)則指定語義,例如address示例看起來象:

﹤as:Structure﹥
﹤address﹥
﹤address_street﹥%street number and name%﹤/address_street﹥
. . .
﹤/address﹥
﹤/as:Structure﹥

﹤as:Rules﹥
﹤as:constraint action="datatype(//address_street,string)" /﹥
﹤/as:Rules﹥

CAM模板的﹤as:Structure﹥小節(jié)定義了XML文檔的層次結(jié)構(gòu),實(shí)際上它是從XML文檔示例復(fù)制過來的,只不過將真實(shí)數(shù)據(jù)替換成占位符(以百分號標(biāo)志出來)而已,因此前面的CAM模板表示是一個使用%street number and number%占位符替換真實(shí)數(shù)據(jù)的XML實(shí)例。
﹤as:Structure﹥小節(jié)補(bǔ)充了部分語義,它定義了一個元素包含了哪些其他元素,以及順序,和Schematron不一樣,你不需要費(fèi)力地編寫規(guī)則代碼定義結(jié)構(gòu),CAM以所見即所得的形式指定結(jié)構(gòu),而Schematron不得不自己動手寫代碼,就和使用微軟Word字處理軟件一樣方便,所見即所得形式相對使用RTF文本生成Word文檔而言,編寫RTF實(shí)在是太乏味、太困難了,而且容易犯錯,如圖1所示。

圖1

所見即所得示例,微軟Word使用更直觀的形式編輯文檔(左側(cè)),但這兩種方式實(shí)際上都在完成同一件事情
即使有一些很酷的工具如XmlSpy或Liquid XML Studio可以幫助你實(shí)現(xiàn)所見即所得的感覺,XML Schema也不是所見即所得的,思考一下下面的示例代碼,它定義了一個cost,范圍在1-999,保留2位小數(shù)。

﹤xs:element name="cost"﹥
﹤xs:simpleType﹥
﹤xs:restriction base="xs:decimal"﹥
﹤xs:fractionDigits value="2" /﹥
﹤xs:totalDigits value="5" /﹥
﹤xs:minInclusive value="1" /﹥
﹤xs:maxInclusive value="999" /﹥
﹤/xs:restriction﹥
﹤/xs:simpleType﹥
﹤/xs:element﹥

下面顯示的兩個CAM語法是等同的:

﹤as:constraint action="setNumberMask(//Part/cost,###.##)" /﹥
﹤as:constraint action="setNumberRange(//Part/cost,1-999)" /﹥

CAM模板的﹤as:Rules﹥小節(jié)定義了在﹤as:Structure﹥小節(jié)中明確嵌入的語義之外的所有語義,包括數(shù)據(jù)類型、約束、基數(shù)、條件等。

CAM的優(yōu)勢

表1總結(jié)了相對于XML Schema和DTD,CAM的關(guān)鍵優(yōu)勢,表這每行將會在本文后面介紹,或以后的文章中介紹。

表1

序號項(xiàng)目DTDXML SchemaCAM示例/注釋
1隔離結(jié)構(gòu)和業(yè)務(wù)規(guī)則 
2當(dāng)前節(jié)點(diǎn)固定驗(yàn)證﹤quantity﹥將一個整數(shù)固定在1到100之間
3當(dāng)前節(jié)點(diǎn)條件驗(yàn)證受限的﹤zip﹥必須是5位數(shù)或10位數(shù)
4跨節(jié)點(diǎn)條件驗(yàn)證受限的如果﹤state﹥是FL,NV,SD,TX,WA,WY,NH或TN,﹤taxable﹥必須是no,否則就是yes
5上下文機(jī)制依賴于條件A或B是否符合
6結(jié)構(gòu)可變性訂購數(shù)量超過25kg的顧客必須選擇一種物流運(yùn)送方式
7參數(shù)化引用從加拿大采購必須符合條件x、y和z,從新西蘭訂購必須符合條件a、b和c
8命名空間感知 
9定義自己的數(shù)據(jù)類型不行可以可以﹤bookNumber﹥必須是8位字符串
10語法和文檔一樣不行可以可以 
11代碼重用受限的可以可以﹤shipTo﹥和﹤billTo﹥地址包含相同的驗(yàn)證規(guī)則
12工具/編輯器1 
13圖形化設(shè)計(jì)器使用XML Schema設(shè)計(jì)器時可以設(shè)計(jì)出復(fù)雜的結(jié)構(gòu)
14所見即所得使用擴(kuò)展框架使用擴(kuò)展框架固有的業(yè)務(wù)規(guī)則語句和它們執(zhí)行時幾乎是一致的,真正做到了按原文所見即所得,
15采用情況成熟成熟初生嬰兒成熟的穩(wěn)定性更好,支持也多
16APIJava、Perl、Ruby、.NetJava、Perl、Ruby、.NetJava 
17開放標(biāo)準(zhǔn) 

表 1 重要的驗(yàn)證特性,DTD,XML Schema和CAM對比表

#p#

CAM編輯器介紹

從http://www.jcam.org.uk/下載最新版本的CAM編輯器,你可以選擇下載CAM模板編輯器或Jcam引擎,本文中大部分地方你只需要CAM模板編輯器就夠了(Jcam引擎執(zhí)行CAM驗(yàn)證)。
為了啟動CAM編輯器,你可能需要從零開始或從一個現(xiàn)有的XML文件或XSD文件創(chuàng)建一個模板,你會發(fā)現(xiàn)實(shí)際上創(chuàng)建一個模板還是瞞簡單的,我們還是使用W3C的Purchase Order模型開始,將這個文件存儲到本地,命名為po.xsd,在編輯器中,選擇‘文件’?‘從模型新建模板’,指定你剛剛存儲的文件的目錄和文件名(如圖2所示),在處理這個文件時程序可能會停頓幾秒鐘,處理完畢后,它會填滿根元素comment區(qū)域。

圖2

從模型新建模板對話框,指定你的XSD文件的路徑和文件名,然后從模型中選擇根元素,以便CAM編輯器為你創(chuàng)建一個基礎(chǔ)的CAM模板

Comment元素是po.xsd文件中所有﹤xsd:element﹥節(jié)點(diǎn)的第一個節(jié)點(diǎn)(按字母順序)的名字,這個文件包含兩個節(jié)點(diǎn):comment和purchaseOrder。在下面的節(jié)選中以粗體顯示。你可以在清單1中查看完整的模型。

﹤xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"﹥

﹤xsd:annotation﹥
﹤xsd:documentation xml:lang="en"﹥
Purchase order schema for Example.com.
Copyright 2000 Example.com. All rights reserved.
﹤/xsd:documentation﹥
﹤/xsd:annotation﹥

﹤xsd:element name="purchaseOrder"
type="PurchaseOrderType"/﹥

﹤xsd:element name="comment" type="xsd:string"/﹥

﹤xsd:complexType name="PurchaseOrderType"﹥
﹤xsd:sequence﹥
﹤xsd:element name="shipTo" type="USAddress"/﹥
﹤xsd:element name="billTo" type="USAddress"/﹥
﹤xsd:element ref="comment" minOccurs="0"/﹥
﹤xsd:element name="items" type="Items"/﹥
﹤/xsd:sequence﹥
﹤xsd:attribute name="orderDate" type="xsd:date"/﹥
﹤/xsd:complexType﹥

...

﹤/xsd:schema﹥

清單1 Po.xsd模型

下面是從w3c獲得了原始po.xsd模型,本文將使用它構(gòu)建CAM模板:

﹤xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"﹥

﹤xsd:annotation﹥
﹤xsd:documentation xml:lang="en"﹥
Purchase order schema for Example.com.
Copyright 2000 Example.com. All rights reserved.
﹤/xsd:documentation﹥
﹤/xsd:annotation﹥

﹤xsd:element name="purchaseOrder" type="PurchaseOrderType"/﹥

﹤xsd:element name="comment" type="xsd:string"/﹥

﹤xsd:complexType name="PurchaseOrderType"﹥
﹤xsd:sequence﹥
﹤xsd:element name="shipTo" type="USAddress"/﹥
﹤xsd:element name="billTo" type="USAddress"/﹥
﹤xsd:element ref="comment" minOccurs="0"/﹥
﹤xsd:element name="items" type="Items"/﹥
﹤/xsd:sequence﹥
﹤xsd:attribute name="orderDate" type="xsd:date"/﹥
﹤/xsd:complexType﹥

﹤xsd:complexType name="USAddress"﹥
﹤xsd:sequence﹥
﹤xsd:element name="name" type="xsd:string"/﹥
﹤xsd:element name="street" type="xsd:string"/﹥
﹤xsd:element name="city" type="xsd:string"/﹥
﹤xsd:element name="state" type="xsd:string"/﹥
﹤xsd:element name="zip" type="xsd:decimal"/﹥
﹤/xsd:sequence﹥
﹤xsd:attribute name="country" type="xsd:NMTOKEN"
fixed="US"/﹥
﹤/xsd:complexType﹥

﹤xsd:complexType name="Items"﹥
﹤xsd:sequence﹥
﹤xsd:element name="item" minOccurs="0" maxOccurs="unbounded"﹥
﹤xsd:complexType﹥
﹤xsd:sequence﹥
﹤xsd:element name="productName" type="xsd:string"/﹥
﹤xsd:element name="quantity"﹥
﹤xsd:simpleType﹥
﹤xsd:restriction base="xsd:positiveInteger"﹥
﹤xsd:maxExclusive value="100"/﹥
﹤/xsd:restriction﹥
﹤/xsd:simpleType﹥
﹤/xsd:element﹥
﹤xsd:element name="USPrice" type="xsd:decimal"/﹥
﹤xsd:element ref="comment" minOccurs="0"/﹥
﹤xsd:element name="shipDate" type="xsd:date" minOccurs="0"/﹥
﹤/xsd:sequence﹥
﹤xsd:attribute name="partNum" type="SKU" use="required"/﹥
﹤/xsd:complexType﹥
﹤/xsd:element﹥
﹤/xsd:sequence﹥
﹤/xsd:complexType﹥

﹤!-- Stock Keeping Unit, a code for identifying products --﹥
﹤xsd:simpleType name="SKU"﹥
﹤xsd:restriction base="xsd:string"﹥
﹤xsd:pattern value="\d{3}-[A-Z]{2}"/﹥
﹤/xsd:restriction﹥
﹤/xsd:simpleType﹥

﹤/xsd:schema﹥

你實(shí)際上想要purchaseOrder作為根,因此在對話框中將根元素切換成purchaseOrder,然后點(diǎn)擊‘確定’生成模板,此時程序會提示你保存模板,保存后模板就在CAM模板編輯器中打開了,如圖3所示:

圖3

CAM編輯器,從po.xsd模型生成模板后,編輯器同時顯示了結(jié)構(gòu)和規(guī)則

編輯器中的每個標(biāo)簽容器都涉及到一個視圖,結(jié)構(gòu)視圖以樹形結(jié)構(gòu)顯示XML的層次,圖3顯示定單有一個orderData屬性和四個子節(jié)點(diǎn):shipTo,billTo,comment和items。items節(jié)點(diǎn)可能包括多個item子節(jié)點(diǎn)。CAM編輯器精確地反映了基礎(chǔ)XML CAM模板文件(PurchaseOrder/purchaseOrder_from_schema.cam),如下所示,這個文件中的﹤as:AssemblyStructure﹥小節(jié)顯示的內(nèi)容實(shí)際上與圖3中結(jié)構(gòu)視圖中的信息是一致的:

﹤as:AssemblyStructure﹥
﹤as:Structure taxonomy="XML" ID="purchaseOrder" reference=""﹥
﹤purchaseOrder orderDate="%YYYY-MM-DDZ%"﹥
﹤shipTo country="US"﹥
﹤name﹥%string%﹤/name﹥
﹤street﹥%string%﹤/street﹥
﹤city﹥%string%﹤/city﹥
﹤state﹥%string%﹤/state﹥
﹤zip﹥%54321.00%﹤/zip﹥
﹤/shipTo﹥
﹤billTo country="US"﹥
﹤name﹥%string%﹤/name﹥
﹤street﹥%string%﹤/street﹥
﹤city﹥%string%﹤/city﹥
﹤state﹥%string%﹤/state﹥
﹤zip﹥%54321.00%﹤/zip﹥
﹤/billTo﹥
﹤comment﹥%string%﹤/comment﹥
﹤items﹥
﹤item partNum="%string%"﹥
﹤productName﹥%string%﹤/productName﹥
﹤quantity﹥%1%﹤/quantity﹥
﹤USPrice﹥%54321.00%﹤/USPrice﹥
﹤comment﹥%string%﹤/comment﹥
﹤shipDate﹥%YYYY-MM-DDZ%﹤/shipDate﹥
﹤/item﹥
﹤/items﹥
﹤/purchaseOrder﹥
﹤/as:Structure﹥
﹤/as:AssemblyStructure﹥

相比之下,XSD文件混合了結(jié)構(gòu)和業(yè)務(wù)規(guī)則,因此維護(hù)成本更高,下面是一個完整CAM文件的頂層框架,顯示了兩個主要的元素:

﹤as:CAM
xmlns:as="http://www.oasis-open.org/committees/cam"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:camed="http://jcam.org.uk/editor"
CAMlevel="1"
version="1.0"﹥
﹤as:Header /﹥
﹤as:AssemblyStructure /﹥
﹤as:BusinessUseContext /﹥
﹤/as:CAM﹥

你可以在清單2中查看完整的CAM模板文件。

清單2 生成的CAM模板

從原始XML模型文件生成的purchaseOrder_from_schema.cam模板:

﹤as:CAM xmlns:as="http://www.oasis-open.org/committees/cam"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:camed="http://jcam.org.uk/editor" CAMlevel="1" version="1.0"﹥
﹤as:Header﹥
﹤as:Description﹥Generated for : purchaseOrder﹤/as:Description﹥
﹤as:Owner﹥To be Completed﹤/as:Owner﹥
﹤as:Version﹥0.1 generator v1.18﹤/as:Version﹥
﹤as:DateTime﹥2008-12-08T12:31:34﹤/as:DateTime﹥
﹤/as:Header﹥
﹤as:AssemblyStructure﹥
﹤as:Structure taxonomy="XML" ID="purchaseOrder" reference=""﹥
﹤purchaseOrder orderDate="%YYYY-MM-DDZ%"﹥
﹤shipTo country="US"﹥
﹤name﹥%string%﹤/name﹥
﹤street﹥%string%﹤/street﹥
﹤city﹥%string%﹤/city﹥
﹤state﹥%string%﹤/state﹥
﹤zip﹥%54321.00%﹤/zip﹥
﹤/shipTo﹥
﹤billTo country="US"﹥
﹤name﹥%string%﹤/name﹥
﹤street﹥%string%﹤/street﹥
﹤city﹥%string%﹤/city﹥
﹤state﹥%string%﹤/state﹥
﹤zip﹥%54321.00%﹤/zip﹥
﹤/billTo﹥
﹤comment﹥%string%﹤/comment﹥
﹤items﹥
﹤item partNum="%string%"﹥
﹤productName﹥%string%﹤/productName﹥
﹤quantity﹥%1%﹤/quantity﹥
﹤USPrice﹥%54321.00%﹤/USPrice﹥
﹤comment﹥%string%﹤/comment﹥
﹤shipDate﹥%YYYY-MM-DDZ%﹤/shipDate﹥
﹤/item﹥
﹤/items﹥
﹤/purchaseOrder﹥
﹤/as:Structure﹥
﹤/as:AssemblyStructure﹥
﹤as:BusinessUseContext﹥
﹤as:Rules﹥
﹤as:default﹥
﹤as:context﹥
﹤as:constraint action="makeOptional(//purchaseOrder/@orderDate)" /﹥
﹤as:constraint condition="string-length(.) ﹤11"
action="setDateMask(//purchaseOrder/@orderDate,YYYY-MM-DD)" /﹥
﹤as:constraint condition="string-length(.) ﹥10"
action="setDateMask(//purchaseOrder/@orderDate,YYYY-MM-DDZ)" /﹥
﹤as:constraint action="makeOptional(//shipTo/@country)" /﹥
﹤as:constraint action="datatype(//shipTo/@country,NMTOKEN)" /﹥
﹤as:constraint action="setNumberMask(//shipTo/zip,######.##)" /﹥
﹤as:constraint action="makeOptional(//billTo/@country)" /﹥
﹤as:constraint action="datatype(//billTo/@country,NMTOKEN)" /﹥
﹤as:constraint action="setNumberMask(//billTo/zip,######.##)" /﹥
﹤as:constraint action="makeOptional(//purchaseOrder/comment)" /﹥
﹤as:constraint action="makeRepeatable(//items/item)" /﹥
﹤as:constraint action="makeOptional(//items/item)" /﹥
﹤as:constraint action="setNumberMask(//item/quantity,######)" /﹥
﹤as:constraint action="setNumberRange(//item/quantity,1-999999)" /﹥
﹤as:constraint action="setNumberMask(//item/USPrice,######.##)" /﹥
﹤as:constraint action="makeOptional(//item/comment)" /﹥
﹤as:constraint action="makeOptional(//item/shipDate)" /﹥
﹤as:constraint condition="string-length(.) ﹤11"
action="setDateMask(//item/shipDate,YYYY-MM-DD)" /﹥
﹤as:constraint condition="string-length(.) ﹥10"
action="setDateMask(//item/shipDate,YYYY-MM-DDZ)" /﹥
﹤/as:context﹥
﹤/as:default﹥
﹤/as:Rules﹥
﹤/as:BusinessUseContext﹥
﹤/as:CAM﹥

規(guī)則視圖(圖3中高亮顯示)顯示了所有的業(yè)務(wù)規(guī)則,組成了模板的語義,與結(jié)構(gòu)不同,規(guī)則存儲在文件中時與規(guī)則視圖不一樣,表2將規(guī)則視圖中的規(guī)則集中在一起了,在沒有研究這些規(guī)則的詳細(xì)情況時,你可以從它們發(fā)現(xiàn):

◆規(guī)則可能是有條件的或絕對的,例如orderDate依賴于它的長度格式要求改變。

◆項(xiàng)目和條件是通過XPath指定的,在CAM中會廣泛使用到XPath,它提供了極大的靈活性和清晰度,相比之下,XML Schema 1.0只為高級的xs:unique和xs:key concepts使用XPath。

◆規(guī)則可能適用于很廣的元素范圍,也可能只能適用于很少的元素,XPath支持選擇文檔的中任何一部分:一個元素、一個屬性、所有你給定名稱的元素、所有在樹中確定位置的元素等。

◆規(guī)則是壓縮的、簡潔的、非常直觀的。實(shí)際上,正如你將會看到的,編寫CAM規(guī)則和編寫應(yīng)用程序需求是一樣的。

條件項(xiàng)目行為
  //purchaseOrder/@orderDatemakeOptional()
string-length(.) ﹤ 11//purchaseOrder/@orderDatesetDateMask(YYYY-MM-DD)
string-length(.) ﹥ 10//purchaseOrder/@orderDatesetDateMask(YYYY-MM-DDZ)
  //shipTo/@countrymakeOptional()
  //shipTo/@countrydatatype(NMTOKEN)
  //shipTo/zipsetNumberMask(######.##)
  //billTo/@countrymakeOptional()
  //billTo/@countrydatatype(NMTOKEN)
  //billTo/zipsetNumberMask(######.##)
  //purchaseOrder/commentmakeOptional()
  //items/itemmakeRepeatable()
  //items/itemmakeOptional()
  //item/quantitysetNumberMask(######)
  //item/quantitysetNumberRange(1-999999)
  //item/USPricesetNumberMask(######.##)
  //item/commentmakeOptional()
  //item/shipDatemakeOptional()
string-length(.) ﹤ 11//item/shipDatesetDateMask(YYYY-MM-DD)
string-length(.) ﹥ 10//item/shipDatesetDateMask(YYYY-MM-DDZ)

表 2 編輯器中的業(yè)務(wù)規(guī)則:為定單轉(zhuǎn)換XML Schema,讓CAM自動生成這些規(guī)則。

#p#

CAM驗(yàn)證示例

現(xiàn)在你可以使用手中的模板驗(yàn)證XML文件,W3C網(wǎng)站上除了提供定單模型外,還提供了一個定單實(shí)例(PurchaseOrder/po.xml),但下載下來的會有一個印刷錯誤,圖4高亮顯示了錯誤,如果你嘗試打開或驗(yàn)證畸形的XML文件,CAM編輯器會顯示堆棧轉(zhuǎn)儲信息和錯誤消息(也看圖4),并拒絕載入文件。

圖4

畸形XML文件:這個圖顯示了為什么原始的po.xml文件不是合適的,將其載入CAM編輯器時顯示出其錯誤

當(dāng)你通過將感嘆號和左半邊尖括號對換位置修復(fù)這個錯誤后(正確的文件是PurchaseOrder/po_corrected.xml),你可以使用CAM編輯器載入這個XML文件,CAM編輯器以XML視圖形式顯示這個文件,繪制成如結(jié)構(gòu)視圖那樣的樹狀結(jié)構(gòu),如圖5所示,目前在模板中相同的元素顯示的是真實(shí)的值而不是占位符。

圖5

XML視圖:當(dāng)你打開一個XML文件時,以XML視圖形式顯示樹形結(jié)構(gòu),可以折疊和展開

為了驗(yàn)證文檔,選擇‘運(yùn)行’?‘運(yùn)行JCam’,你將會看到如圖6所示的Jcam運(yùn)行對話框,默認(rèn)情況下,Jcam選擇載入的XML文件,應(yīng)該可以通過它的結(jié)構(gòu)ID如purchaseOrder(這個結(jié)構(gòu)的根)來識別,點(diǎn)擊‘完成’關(guān)閉這個對話框開始驗(yàn)證,結(jié)果顯示在主窗口中下方的運(yùn)行結(jié)果視圖中,注意驗(yàn)證過程發(fā)現(xiàn)了兩個錯誤,盡管在圖6中只顯示了一個,如果你仔細(xì)一看,你會發(fā)現(xiàn)有錯誤的節(jié)點(diǎn)上會有一個黃色或紅色的圖標(biāo),在本例中,錯誤發(fā)生在﹤zip﹥元素上,它的父元素﹤shipTo﹥也顯示了一個錯誤圖標(biāo),甚至根元素﹤purchaseOrder﹥也顯示了一個錯誤圖標(biāo)。同樣,你可以推斷第二個錯誤是隱藏在﹤billTo﹥元素中的。

圖6

執(zhí)行驗(yàn)證:驗(yàn)證結(jié)果顯示在運(yùn)行結(jié)果視圖中,每個驗(yàn)證失敗的元素或?qū)傩远加幸粋€錯誤標(biāo)記,它的上級元素就有一個警告標(biāo)記

這個XML文件在任何XML Schema編輯器中驗(yàn)證都沒有錯誤,為什么在這里驗(yàn)證就失敗了呢?運(yùn)行結(jié)果視圖中的錯誤指出zip代碼根據(jù)CAM模板的定義是無效的,這個模板會檢查是否是一個浮點(diǎn)數(shù),因?yàn)樵诿绹鴝ip代碼要么是5位要么是9位的整數(shù),zip代碼的CAM模板規(guī)則來自XSD規(guī)格說明XSD規(guī)格說明簡單說明了zip代碼是一個十進(jìn)制數(shù),這一點(diǎn)你可以從清單1中看到:在USAddress復(fù)雜類型中查找zip字段,CAM模板生成程序應(yīng)該避免不用的輸入輸出。但你可能不同意,我提交的XSD規(guī)格說明太寬松了,數(shù)據(jù)類型應(yīng)該是一個整數(shù)而不是一個十進(jìn)制數(shù),下面的部分將會介紹如何使用CAM編輯器來糾正這個錯誤。

當(dāng)你按照本文的例子進(jìn)行研究時,你可能會遇到模板沒有象預(yù)期那樣運(yùn)轉(zhuǎn),在這種時候要檢查兩樣?xùn)|西:

◆點(diǎn)擊‘工具’→‘驗(yàn)證CAM模板’菜單項(xiàng)查找所有問題。

◆如果你在運(yùn)行JCam對話框中點(diǎn)擊‘完成’按鈕,似乎什么事情都不會發(fā)生,按‘取消’關(guān)閉對話框,然后查看控制臺視圖中的錯誤消息,例如,如果你忘記指定要驗(yàn)證的XML文件了,對話框不會禁用完成按鈕,控制臺視圖中報(bào)告的錯誤是‘模板是空的’,這多少會讓人有些誤解。如果控制臺視圖什么都沒有顯示,那就表示一切ok。

#p#

創(chuàng)建業(yè)務(wù)規(guī)則

在結(jié)構(gòu)視圖中選擇﹤shipTo﹥元素下的﹤zip﹥元素,附加到這個元素的規(guī)則顯示在項(xiàng)目規(guī)則(ItemRules)視圖中,在本例中只有一個規(guī)則,使用的是setNumberMask謂詞。在類別(category)列中的規(guī)則上點(diǎn)擊右鍵打開這個規(guī)則的上下文菜單,然后選擇‘編輯規(guī)則’,打開編輯約束規(guī)則對話框,如圖7所示。

圖7

編輯約束規(guī)則:為了修復(fù)setNumberMask謂詞附加到//shipTo/zip元素,選擇結(jié)構(gòu)視圖中的元素,打開它的上下文菜單,選擇編輯規(guī)則打開編輯約束規(guī)則對話框,點(diǎn)擊數(shù)字特征碼字段明確指定特征碼

在數(shù)字特征碼字段上點(diǎn)擊,打開另一個對話框編輯特征碼,現(xiàn)在只需要將######.##修改為#####即可,關(guān)閉這兩個對話框,在主編輯器窗口中,你會看到更新后的規(guī)則,重新執(zhí)行一次驗(yàn)證,//shipTo/zip錯誤應(yīng)該不會再出現(xiàn),只留下//billTo/zip錯誤,很明顯這是一個相同的錯誤,因此你可以使用相同的手段修復(fù)它,但因?yàn)?/billTo/zip和//shipTo zip的值應(yīng)該一樣,這樣就可以使用一個通用的規(guī)則而不用每個指定一條規(guī)則了,本文的第二部分將會詳細(xì)地介紹如何使用通用規(guī)則。

規(guī)則更新后你也應(yīng)該更新占位符(圖7中的項(xiàng)目1),如果你和圖6比較,你會發(fā)現(xiàn)值從%54321.00%變成%54321%了,它更能代表zip代碼,在這個特殊的例子中,元素的占位符和關(guān)聯(lián)的規(guī)則的緊密相關(guān)的,假設(shè)它們自動相互跟蹤是合理的,但在許多情況下,關(guān)系并不是直接的,元素和規(guī)則是多對多的關(guān)系:你可以對一個元素應(yīng)用多個規(guī)則,或者一個規(guī)則應(yīng)用給多個元素。

為了更新圖7所示的元素占位符,在結(jié)構(gòu)視圖中//shipTo/zip字段上打開上下文菜單,選擇‘編輯文本’,在對話框中將54321.00%修改成%54321%。

占位符為兩個角色服務(wù),CAM處理程序單獨(dú)使用它確定某個元素的內(nèi)容是否已被修復(fù),這是由圍繞在占位符兩邊的百分比符號確定的,注意在更新元素的占位符前,你要重新驗(yàn)證//shipTo/zip字段,確認(rèn)在百分比符號中間的值被CAM處理程序忽略。

百分比符號之間的值應(yīng)該是準(zhǔn)確、簡明地指出包含什么元素,通常上下文已經(jīng)為你完成了大部分工作:元素的名字是‘zip’,在美國它會被立即認(rèn)為是5、9或10位整數(shù),通過設(shè)置占位符為%54321%,你告訴用戶模板只接受5個字符的zip代碼。

強(qiáng)度測試驗(yàn)證

現(xiàn)在你已經(jīng)更新了占位符和規(guī)則,但只修改這兩個地方就足夠驗(yàn)證zip代碼了嗎?為了測試它,你需要為CAM處理程序提供不同的測試用例,最簡單的方法是打開包含你要驗(yàn)證的數(shù)據(jù)的XML視圖,修改//shipTo/zip的值,然后再重新驗(yàn)證,你可以在XML視圖中象結(jié)構(gòu)視圖那樣編輯節(jié)點(diǎn):打開上下文菜單選擇編輯文本,確定最小值以便覆蓋到所有范圍,讓每個值都被驗(yàn)證一次,表3提供了這樣一個列表,從這個表中可以看到有兩個地方一個是pass掉,而另一個卻沒有過,只有這兩個驗(yàn)證函數(shù)都過了才行。

//shipTo/zipsetNumberMask(#####)setStringMask(00000)
90952PassPass
90952.1FailFail
123456FailFail
90952-1234FailFail
1PassFail
(blank entry)FailFail
90952aFailFail
-12345PassFail
(123)FailFail

表 3 zip代碼測試用例:這個表顯示了使用數(shù)字型特征碼#####和使用字符串型特征碼00000進(jìn)行驗(yàn)證的結(jié)果,結(jié)果以綠色表示的是正確的,以紅色表示的是錯誤的

這兩個測試都通過具有相同的原因:特征碼是數(shù)字,這兩個測試都是有效的數(shù)字。雖然zip代碼只包含數(shù)字,實(shí)際上它是一個字符串,從數(shù)字上來說,00001和1是相等的,在zip代碼域中,00001代表一個有效的代碼,而1不是。因此要使用numeric特征碼代替textual特征碼,為//shipTo/zip打開編輯約束對話框,將行為從setNumberMask修改成setStringMask,在String Mask字段上點(diǎn)擊打開特征碼編輯器,輸入5個0,或者按數(shù)字0-9之間任何一個數(shù)字5次,然后退出這兩個對話框,如果你現(xiàn)在重新驗(yàn)證表3中的每個測試用例,你會發(fā)現(xiàn)它們所有的測試結(jié)果都是正確的。

在正式的CAM規(guī)格說明書的3.4.3節(jié)(CAM內(nèi)容特征碼語法)列出了有效的特征碼字符,表4就是改變自它的。

表 4 特征碼字符:當(dāng)規(guī)則行為需要特征碼時,這些字符有特定的含義

字符描述

字符串特征碼

X任何字符,強(qiáng)制性
A強(qiáng)制性字母數(shù)字字符或空格
a非強(qiáng)制性字母數(shù)字字符或空格
?任何單一字符
*0或更多字符0
U一個可以被轉(zhuǎn)換為大寫的字符
^大寫,非強(qiáng)制
L一個可以被轉(zhuǎn)換為小寫的字符
_小寫,非強(qiáng)制
0數(shù)字、后綴和前端插入的0,前端插入的正負(fù)號
#數(shù)字、后綴和前端插入的0被取消,前端插入的正負(fù)號
' '轉(zhuǎn)義字符

數(shù)字型特征碼

0數(shù)字、后綴和前端插入的0,前端插入的正負(fù)號
#數(shù)字、后綴和取消前端插入的0,前端插入的正負(fù)號
.小數(shù)點(diǎn)
J特征碼的第一個字符,可能調(diào)用Java格式化方法處理特征碼,當(dāng)傳遞給Java時,文字J被忽略

日期型特征碼

DD一月中的某天
DDD一年中的某天
DDDD一月中的相對某天
MM一年中的月份
MMM...月名,如January(一月),字段會被填充或截?cái)喑?-10個數(shù)字
YY兩位數(shù)的年
YYYY四位數(shù)的年
W一周的某天
WWW...期名,字段會被填充或截?cái)喑?-10個數(shù)字
/斜號,日期分隔符
-連字符,另一個日期分隔符

如果你想找一個具有完整、清晰文檔,并且所有的bug都被消除的工具,那這個可能會讓你失望,但你如果不介意寶石周圍那一點(diǎn)點(diǎn)瑕疵,我相信在你的兵器庫中CAM會是一個偉大的工具,最后,我要告訴那些熱心的開發(fā)者們,CAM編輯器和CAM引擎最近的版本(我用的是1.6.2版)中的行為完全是合理的。

這是第一部分的內(nèi)容,到此就結(jié)束了,現(xiàn)在你至少知道其實(shí)使用CAM設(shè)計(jì)時還是很簡單的,在本文的第二部分中,你將會看到CAM的強(qiáng)大之處,另外,你還將會看到關(guān)于開發(fā)模板和規(guī)則使用的技術(shù)更深入的討論,包括:通用結(jié)構(gòu)和通用規(guī)則,基于內(nèi)部或外部因子的條件驗(yàn)證,詳細(xì)比較XSD關(guān)于數(shù)據(jù)類型、排序和基數(shù)。最后還將介紹如何避免常犯的錯誤。

【編輯推薦】

  1. XML結(jié)構(gòu)與語法入門詳解
  2. XML新手入門 創(chuàng)建構(gòu)造良好的XML
  3. 使用SAXParser處理XML文檔

本文題目:使用CAM機(jī)制提高XML驗(yàn)證水平
網(wǎng)頁鏈接:http://www.dlmjj.cn/article/ccehhoe.html