自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用CAM機(jī)制提高XML驗(yàn)證水平

原創(chuàng)
開發(fā)
本文詳細(xì)敘述了CAM即內(nèi)容裝配機(jī)制(Content Assembly Mechanism)的基礎(chǔ)用法,優(yōu)勢以及一些驗(yàn)證實(shí)例。CAM是一個(gè)XML結(jié)構(gòu)驗(yàn)證方法,近年來開發(fā)非常迅速。它不僅是一門schema語言,其設(shè)計(jì)目的是更好地滿足業(yè)務(wù)交流和互操作性要求,它提供了強(qiáng)有力的機(jī)制來驗(yàn)證XML結(jié)構(gòu)和語義,使其簡潔、易于使用和易于維護(hù)。

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

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ù);它提供了一個(gè)上下文機(jī)制 -- 一種基于XML自身其它部分或外部參數(shù)來動(dòng)態(tài)調(diào)整那些應(yīng)被視為有效的XML實(shí)例。

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

因此,在寫本文的時(shí)候,CAM文檔還很潦草:有一個(gè)正式的規(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文檔是元素的多層次組合,它是一個(gè)用于存儲任何數(shù)量文字或數(shù)據(jù)結(jié)構(gòu)的樹狀存儲結(jié)構(gòu),XML文檔需要很好的格式,這意味著它只有一個(gè)根,其元素和屬性必須符合簡單的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)證這個(gè)XML片段,你通常會定義一個(gè)如下的結(jié)構(gòu):

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

這些限制條件指出﹤address_street﹥元素必須存在,并且必須包含在﹤address﹥元素內(nèi),還必須包含一個(gè)字符串。對于一個(gè)地址而言,一個(gè)簡單的字符串值可能是適當(dāng)?shù)模渌侄文銘?yīng)該使用更具體的東西,要么是一個(gè)專門的字符串(一種衍生的,有限制的字符串)、日期、整數(shù)或其它定義類型。
XML Schema是一種基于語法的系統(tǒng),在它里面你需要同時(shí)為語義和結(jié)構(gòu)定義語法;另一方面,Schematron是一個(gè)基于規(guī)則的系統(tǒng),你可以使用規(guī)則同時(shí)指定語義和結(jié)構(gòu),即你不僅使用規(guī)則指定address_street是一個(gè)字符串,還用規(guī)則指定﹤address_street﹥必須顯示在﹤address﹥元素內(nèi),XML Schema和Schematron從根本上說語義和結(jié)構(gòu)都是糾纏在一起的。在編程方面耦合度很高,這是不可取的。
相比之下,CAM是一個(gè)混合系統(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模板表示是一個(gè)使用%street number and number%占位符替換真實(shí)數(shù)據(jù)的XML實(shí)例。
﹤as:Structure﹥小節(jié)補(bǔ)充了部分語義,它定義了一個(gè)元素包含了哪些其他元素,以及順序,和Schematron不一樣,你不需要費(fèi)力地編寫規(guī)則代碼定義結(jié)構(gòu),CAM以所見即所得的形式指定結(jié)構(gòu),而Schematron不得不自己動(dòng)手寫代碼,就和使用微軟Word字處理軟件一樣方便,所見即所得形式相對使用RTF文本生成Word文檔而言,編寫RTF實(shí)在是太乏味、太困難了,而且容易犯錯(cuò),如圖1所示。

圖1
圖1

所見即所得示例,微軟Word使用更直觀的形式編輯文檔(左側(cè)),但這兩種方式實(shí)際上都在完成同一件事情
即使有一些很酷的工具如XmlSpy或Liquid XML Studio可以幫助你實(shí)現(xiàn)所見即所得的感覺,XML Schema也不是所見即所得的,思考一下下面的示例代碼,它定義了一個(gè)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﹥

下面顯示的兩個(gè)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)目 DTD XML Schema CAM 示例/注釋
1 隔離結(jié)構(gòu)和業(yè)務(wù)規(guī)則  
2 當(dāng)前節(jié)點(diǎn)固定驗(yàn)證 ﹤quantity﹥將一個(gè)整數(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í)可以設(shè)計(jì)出復(fù)雜的結(jié)構(gòu)
14 所見即所得 使用擴(kuò)展框架 使用擴(kuò)展框架 固有的 業(yè)務(wù)規(guī)則語句和它們執(zhí)行時(shí)幾乎是一致的,真正做到了按原文所見即所得,
15 采用情況 成熟 成熟 初生嬰兒 成熟的穩(wěn)定性更好,支持也多
16 API Java、Perl、Ruby、.Net Java、Perl、Ruby、.Net Java  
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)證)。
為了啟動(dòng)CAM編輯器,你可能需要從零開始或從一個(gè)現(xiàn)有的XML文件或XSD文件創(chuàng)建一個(gè)模板,你會發(fā)現(xiàn)實(shí)際上創(chuàng)建一個(gè)模板還是瞞簡單的,我們還是使用W3C的Purchase Order模型開始,將這個(gè)文件存儲到本地,命名為po.xsd,在編輯器中,選擇‘文件’?‘從模型新建模板’,指定你剛剛存儲的文件的目錄和文件名(如圖2所示),在處理這個(gè)文件時(shí)程序可能會停頓幾秒鐘,處理完畢后,它會填滿根元素comment區(qū)域。

圖2
圖2

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

Comment元素是po.xsd文件中所有﹤xsd:element﹥節(jié)點(diǎn)的第一個(gè)節(jié)點(diǎn)(按字母順序)的名字,這個(gè)文件包含兩個(gè)節(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)擊‘確定’生成模板,此時(shí)程序會提示你保存模板,保存后模板就在CAM模板編輯器中打開了,如圖3所示:

圖3
圖3

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

編輯器中的每個(gè)標(biāo)簽容器都涉及到一個(gè)視圖,結(jié)構(gòu)視圖以樹形結(jié)構(gòu)顯示XML的層次,圖3顯示定單有一個(gè)orderData屬性和四個(gè)子節(jié)點(diǎn):shipTo,billTo,comment和items。items節(jié)點(diǎn)可能包括多個(gè)item子節(jié)點(diǎn)。CAM編輯器精確地反映了基礎(chǔ)XML CAM模板文件(PurchaseOrder/purchaseOrder_from_schema.cam),如下所示,這個(gè)文件中的﹤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ù)成本更高,下面是一個(gè)完整CAM文件的頂層框架,顯示了兩個(gè)主要的元素:

﹤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ī)則存儲在文件中時(shí)與規(guī)則視圖不一樣,表2將規(guī)則視圖中的規(guī)則集中在一起了,在沒有研究這些規(guī)則的詳細(xì)情況時(shí),你可以從它們發(fā)現(xiàn):

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

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

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

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

條件 項(xiàng)目 行為
  //purchaseOrder/@orderDate makeOptional()
string-length(.) ﹤ 11 //purchaseOrder/@orderDate setDateMask(YYYY-MM-DD)
string-length(.) ﹥ 10 //purchaseOrder/@orderDate setDateMask(YYYY-MM-DDZ)
  //shipTo/@country makeOptional()
  //shipTo/@country datatype(NMTOKEN)
  //shipTo/zip setNumberMask(######.##)
  //billTo/@country makeOptional()
  //billTo/@country datatype(NMTOKEN)
  //billTo/zip setNumberMask(######.##)
  //purchaseOrder/comment makeOptional()
  //items/item makeRepeatable()
  //items/item makeOptional()
  //item/quantity setNumberMask(######)
  //item/quantity setNumberRange(1-999999)
  //item/USPrice setNumberMask(######.##)
  //item/comment makeOptional()
  //item/shipDate makeOptional()
string-length(.) ﹤ 11 //item/shipDate setDateMask(YYYY-MM-DD)
string-length(.) ﹥ 10 //item/shipDate setDateMask(YYYY-MM-DDZ)

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

#p#

CAM驗(yàn)證示例

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

圖4
圖4

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

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

圖5
圖5

XML視圖:當(dāng)你打開一個(gè)XML文件時(shí),以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(這個(gè)結(jié)構(gòu)的根)來識別,點(diǎn)擊‘完成’關(guān)閉這個(gè)對話框開始驗(yàn)證,結(jié)果顯示在主窗口中下方的運(yùn)行結(jié)果視圖中,注意驗(yàn)證過程發(fā)現(xiàn)了兩個(gè)錯(cuò)誤,盡管在圖6中只顯示了一個(gè),如果你仔細(xì)一看,你會發(fā)現(xiàn)有錯(cuò)誤的節(jié)點(diǎn)上會有一個(gè)黃色或紅色的圖標(biāo),在本例中,錯(cuò)誤發(fā)生在﹤zip﹥元素上,它的父元素﹤shipTo﹥也顯示了一個(gè)錯(cuò)誤圖標(biāo),甚至根元素﹤purchaseOrder﹥也顯示了一個(gè)錯(cuò)誤圖標(biāo)。同樣,你可以推斷第二個(gè)錯(cuò)誤是隱藏在﹤billTo﹥元素中的。

圖6
圖6

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

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

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

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

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

#p#

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

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

圖7
圖7

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

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

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

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

占位符為兩個(gè)角色服務(wù),CAM處理程序單獨(dú)使用它確定某個(gè)元素的內(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個(gè)字符的zip代碼。

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

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

//shipTo/zip setNumberMask(#####) setStringMask(00000)
90952 Pass Pass
90952.1 Fail Fail
123456 Fail Fail
90952-1234 Fail Fail
1 Pass Fail
(blank entry) Fail Fail
90952a Fail Fail
-12345 Pass Fail
(123) Fail Fail

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

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

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

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

字符 描述

字符串特征碼

X 任何字符,強(qiáng)制性
A 強(qiáng)制性字母數(shù)字字符或空格
a 非強(qiáng)制性字母數(shù)字字符或空格
? 任何單一字符
* 0或更多字符0
U 一個(gè)可以被轉(zhuǎn)換為大寫的字符
^ 大寫,非強(qiáng)制
L 一個(gè)可以被轉(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 特征碼的第一個(gè)字符,可能調(diào)用Java格式化方法處理特征碼,當(dāng)傳遞給Java時(shí),文字J被忽略

日期型特征碼

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

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

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

【編輯推薦】

  1. XML結(jié)構(gòu)與語法入門詳解
  2. XML新手入門 創(chuàng)建構(gòu)造良好的XML
  3. 使用SAXParser處理XML文檔
責(zé)任編輯:yangsai 來源: 51CTO.com
相關(guān)推薦

2017-12-12 16:43:54

SparkHadoop水平

2012-02-02 15:04:02

軟件開發(fā)

2009-07-16 16:51:56

WebWork驗(yàn)證機(jī)制

2023-07-11 10:38:24

區(qū)塊鏈文件驗(yàn)證安全

2012-06-21 16:19:30

程序員

2020-12-14 12:17:47

MySQL記錄語句

2009-09-16 08:44:46

學(xué)習(xí)CCNA和CCNP

2022-06-01 14:10:46

物聯(lián)網(wǎng)5G蜂窩技術(shù)

2022-03-24 15:11:49

區(qū)塊鏈云計(jì)算數(shù)據(jù)

2010-09-07 16:34:47

DB2 XML

2009-01-04 16:58:48

LINQ to XMLLINQXML

2020-11-08 14:32:01

JavaScript變量內(nèi)存管理

2010-10-29 10:56:46

ORACLE用戶驗(yàn)證

2011-08-11 11:08:09

2023-12-22 15:32:20

2010-09-09 13:15:59

提高VPN質(zhì)量

2017-05-18 09:16:54

前端CSS技巧

2021-01-14 09:34:35

量子量子網(wǎng)絡(luò)量子通信

2021-03-31 10:15:27

人工智能美國技術(shù)

2014-07-23 09:55:11

程序員
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號