乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      JAXP 驗(yàn)證-使用 JAXP 1.3 的新功能驗(yàn)證 XML

       jinzq 2007-09-24
      http://www-128.ibm.com/developerworks/cn/xml/x-jaxpval.html

      JAXP 驗(yàn)證

      使用 JAXP 1.3 的新功能驗(yàn)證 XML

      developerWorks

      級(jí)別: 中級(jí)

      Brett McLaughlin (brett@newInstance.com), 作家/編輯, O‘Reilly Media, Inc.

      2005 年 11 月 03 日

      Java™ 編程語(yǔ)言的最新版本 Java 5.0 包括經(jīng)過(guò)改進(jìn)和擴(kuò)展的 Java API for XML Processing(JAXP)版本。JAXP 主要增加了新的驗(yàn)證 API,它提供了更好的交互性,支持 XML Schema 和 RELAX NG,能夠在驗(yàn)證的同時(shí)即時(shí)修改。經(jīng)過(guò)這些改進(jìn),為 Java 開(kāi)發(fā)人員提供了一種工業(yè)強(qiáng)度的 XML 驗(yàn)證解決方案。本文詳細(xì)介紹這種新的 API,包括基本特性和更高級(jí)的特性。

      幾 年來(lái),Java API for XML Processing(JAXP)一直是一種穩(wěn)定、有點(diǎn)兒沉悶的 API。這并不是壞事。沉悶常常意味著可靠,對(duì)軟件來(lái)說(shuō)總是好事。不過(guò) JAXP 的遲鈍已經(jīng)讓開(kāi)發(fā)人員不再尋求新的特性。從 Java 1.3 到 1.4,除了支持最新版本的 SAX 和 DOM 規(guī)范(請(qǐng)參閱 參考資料)以外,JAXP 沒(méi)有很大變化。但是在 Java 5.0 和 JAXP 1.3 中,Sun 大大擴(kuò)展了 JAXP。除了支持 XPath 以外,最值得一提的還有驗(yàn)證。本文詳細(xì)介紹了 JAXP 1.3 的驗(yàn)證特性,該特性在 javax.xml.validation 包中實(shí)現(xiàn)。

      簡(jiǎn)要的歷史回顧

      無(wú)所不在的模式

      本文中(而且一般來(lái)說(shuō)),模式(schema) 指的是跟隨一種 XML 格式的任何約束模型。XML Schema 是一種模式,但模式不一定是 XML Schema(按照 W3C 規(guī)范的定義)。比如,模式 也可用于 RELAX NG 模式。使用一般意義的 模式 更便于指稱某種特定的方法(基于 XML 的約束模型)而不局限于具體的實(shí)現(xiàn)。

      詳細(xì)了解這種驗(yàn)證 API 的具體細(xì)節(jié)之前,必須充分了解 JAXP 1.3 之前驗(yàn)證是如何完成的。此外,顯然 Sun 仍將支持過(guò)去的 DTD 驗(yàn)證方法,但是建議使用基于模式的新的驗(yàn)證 API。因此即便您義無(wú)反顧地要使用 javax.xml.validation 包,仍然需要理解使用 DTD 驗(yàn)證文檔的方法。

      創(chuàng)建解析器工廠

      在一般的 JAXP 處理中,都是從 工廠 開(kāi)始的。SAXParserFactory 用于 SAX 解析,DocumentBuilderFactory 則用于 DOM 解析。這兩種工廠都使用靜態(tài)方法 newInstance() 創(chuàng)建,如清單 1 所示。


      清單 1. 創(chuàng)建 SAXParserFactory 和 DocumentBuilderFactory
      				// Create a new SAX Parser factorySAXParserFactory factory = SAXParserFactory.newInstance();// Create a new DOM Document Builder factoryDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

      打開(kāi)驗(yàn)證

      一個(gè)工廠,多個(gè)解析器

      對(duì)工廠設(shè)置的選項(xiàng)影響該工廠創(chuàng)建的所有解析器。如果用 true 調(diào)用 setValidating(),則明確地告訴工廠創(chuàng)建的所有解析器都必須是進(jìn)行驗(yàn)證的。要記住,很容易出現(xiàn)這種情況:在工廠中打開(kāi)驗(yàn)證,在寫了 100 行代碼之后忘了這個(gè)設(shè)置,也就忘了生成的解析器是進(jìn)行驗(yàn)證的。

      雖然 SAXParserFactoryDocumentBuilderFactory 有分別適合 SAX 和 DOM 的不同特性和性質(zhì),但是對(duì)驗(yàn)證來(lái)說(shuō)它們都有一個(gè)共同的方法:setValidating()。如您所料,要打開(kāi)驗(yàn)證,只需要把 true 傳遞給該方法。但是使用工廠是為了創(chuàng)建解析器而不是直接解析文檔。創(chuàng)建工廠之后就可以調(diào)用 newSAXParser()(SAX)或 newDocumentBuilder()(DOM)。清單 2 顯示了這兩個(gè)方法,都打開(kāi)了驗(yàn)證。


      清單 2. 打開(kāi)驗(yàn)證(DTD)
      				// Create a new SAX Parser factorySAXParserFactory factory = SAXParserFactory.newInstance();// Turn on validationfactory.setValidating(true);// Create a validating SAX parser instanceSAXParser parser = factory.newSAXParser();// Create a new DOM Document Builder factoryDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// Turn on validationfactory.setValidating(true);// Create a validating DOM parserDocumentBuilder builder = factory.newDocumentBuilder(); 

      無(wú)論哪種情況,都將得到一個(gè)能夠解析 XML 并在解析過(guò)程中驗(yàn)證 XML 的對(duì)象(SAXParserDocumentBuilder)。但是要記住,這樣做 限于 DTD 解析。setValidating(true) 調(diào)用對(duì)基于 XML 的解析完全沒(méi)有作用。





      回頁(yè)首


      javax.xml.validation 簡(jiǎn)介

      5 年前,用一個(gè)漂亮的方法打開(kāi) DTD 驗(yàn)證就足夠了。甚至兩年前,XML Schema 和 RELAX NG 之類的模式語(yǔ)言仍然在忙于解決自己的問(wèn)題。但今天,用模式驗(yàn)證文檔與 DTD 方式一樣常見(jiàn)。這兩種方法同時(shí)存在很大程度上是因?yàn)檫z留文檔仍然使用 DTD。今后幾年內(nèi),DTD 將和 Lisp 一樣消失,成為歷史遺跡而不是主流技術(shù)。

      JAXP 1.3 通過(guò)引入 javax.xml.validation 包支持模式驗(yàn)證已經(jīng)在開(kāi)發(fā)人員中引起了很大反響。這個(gè)包易于使用,結(jié)構(gòu)緊湊,已經(jīng)成為 Java 語(yǔ)言的標(biāo)準(zhǔn)組成部分。更好的是,如果您曾經(jīng)通過(guò) JAXP 使用過(guò) SAX 和 DOM,那么掌握如何驗(yàn)證就更簡(jiǎn)單了。模型是類似的,您會(huì)發(fā)現(xiàn)使用這種 API 進(jìn)行驗(yàn)證簡(jiǎn)直輕而易舉。

      使用 SchemaFactory

      通過(guò) 簡(jiǎn)要的歷史回顧 您知道,使用 SAX 的第一步是創(chuàng)建新的 SAXParserFactory。如果使用 DOM 則首先創(chuàng)建 DocumentBuilderFactory。因此毫不奇怪,進(jìn)行模式驗(yàn)證首先要?jiǎng)?chuàng)建 SchemaFactory 類的實(shí)例,如清單 3 所示。


      清單 3. 創(chuàng)建 SchemaFactory
      				import javax.xml.XMLConstants;import javax.xml.validation.SchemaFactory;...SchemaFactory schemaFactory =      SchemaFactory.newInstance(XMLConstants.W3C_SCHEMA_NS_URI);

      這和其他工廠的創(chuàng)建類似,只不過(guò)增加了傳遞給 newInstance() 方法的參數(shù)。必須向該方法傳遞另一個(gè)類中定義的常量,即 javax.xml.XMLConstants 類,對(duì)這個(gè)類也需要非常熟悉。這個(gè)類定義了 JAXP 應(yīng)用程序中使用的所有常量,不過(guò)現(xiàn)在只需要知道兩個(gè):

      • 用于 RELAX NG 模式的 XMLConstants.RELAXNG_NS_URI
      • 用于 W3C XML Schema 的 XMLConstants.W3C_XML_SCHEMA_NS_URI

      因?yàn)?SchemaFactory 是與具體的約束模型聯(lián)系在一起的,所以必須在工廠構(gòu)造的時(shí)候提供這個(gè)值。

      SchemaFactory 類還有其他幾個(gè)選項(xiàng)。這些內(nèi)容在后面的 深入了解驗(yàn)證 一節(jié)中再介紹。對(duì)于一般的 XML 驗(yàn)證,預(yù)設(shè)的工廠就夠了。

      針對(duì)模式進(jìn)行驗(yàn)證

      Use the Source, Luke

      盡管這個(gè)標(biāo)題威嚴(yán)、一語(yǔ)雙關(guān),其實(shí)在整個(gè) JAXP 中 Source 接口非常重要。該接口源自 XML 轉(zhuǎn)換處理,已經(jīng)成為各種 JAXP 結(jié)構(gòu)的輸入標(biāo)準(zhǔn),至少對(duì)于沒(méi)有直接使用 Java 語(yǔ)言 IO 類的情況是這樣。如果從未使用過(guò) Source 及其實(shí)現(xiàn),請(qǐng)看一下 參考資料 中關(guān)于 XML 轉(zhuǎn)換的文檔和文章。

      建立工廠后還需要裝入需要使用的約束集。可以通過(guò)工廠的 newSchema() 方法來(lái)完成。但是工廠以 javax.xml.transform.Source 實(shí)現(xiàn)作為輸入,因此需要一個(gè)中間步驟:將模式轉(zhuǎn)化成 Source 表示。這個(gè)過(guò)程很簡(jiǎn)單,如清單 4 所示。


      清單 4. 從約束到 Schema
      				import javax.xml.XMLConstants;import javax.xml.transform.Source;import javax.xml.transform.stream.StreamSource;import javax.xml.validation.SchemaFactory;import javax.xml.validation.Schema;...SchemaFactory schemaFactory =     SchemaFactory.newInstance(XMLConstants.W3C_SCHEMA_NS_URI);Source schemaSource =      new StreamSource(new File("constraints.xml"));Schema schema = schemaFactory.newSchema(schemaSource);			

      如果熟悉 JAXP,那么這些代碼都非常直觀。清單 4 中加載了一個(gè)名為 constraints.xml 的文件。可以使用任何方法得到 Source 中的數(shù)據(jù),包括使用 SAX 或 DOM(分別通過(guò) SAXSourceDOMSource)讀取約束,甚至使用 URL。

      一旦得到了 Source 實(shí)現(xiàn),就將其傳遞給工廠的 newSchema() 方法。返回的就是 Schema。現(xiàn)在,對(duì)文檔進(jìn)行驗(yàn)證就很簡(jiǎn)單了。請(qǐng)參閱清單 5。


      清單 5. 驗(yàn)證 XML
      				import javax.xml.XMLConstants;import javax.xml.transform.Source;import javax.xml.transform.stream.StreamSource;import javax.xml.validation.SchemaFactory;import javax.xml.validation.Schema;import javax.xml.validation.Validator;...SchemaFactory schemaFactory =      SchemaFactory.newInstance(XMLConstants.W3C_SCHEMA_NS_URI);Source schemaSource = new StreamSource(new File("constraints.xml"));Schema schema = schemaFactory.newSchema(schemaSource);Validator validator = schema.newValidator();validator.validate(new StreamSource("my-file.xml"));			

      這里同樣沒(méi)有什么大的變化。只要知道要使用的類和調(diào)用的方法就很容易了。因?yàn)橐M(jìn)行驗(yàn)證,所以必須使用 Validator 類。可以使用 newValidator() 方法從 Schema 得到這個(gè)類的實(shí)例。最后可以調(diào)用 validate() 并再次傳遞 Source 實(shí)現(xiàn),不過(guò)這一次它代表要解析和驗(yàn)證的 XML。

      調(diào)用該方法之后就會(huì)解析和驗(yàn)證目標(biāo) XML。要記住,即使用 DOMSource 提供 XML(解析過(guò)的 XML 表示),解析也可能再次發(fā)生。驗(yàn)證仍然和解析緊密聯(lián)系在一起,因此驗(yàn)證過(guò)程需要一點(diǎn)兒時(shí)間。

      如果出現(xiàn)錯(cuò)誤,就會(huì)拋出異常說(shuō)明出了問(wèn)題。JAXP 的多數(shù)實(shí)現(xiàn)都包括行號(hào),有時(shí)候還有列號(hào),幫助定位違反約束模型的位置。當(dāng)然,僅僅拋出異常并不一定是解決問(wèn)題的最佳方式。我將在 下一節(jié) 介紹一種更好的方法。

      看起來(lái)似乎工作不少:得到工廠,得到模式,得到驗(yàn)證器。讓 JAXP 提供一個(gè)工廠方法來(lái)完成這一切是完全可能的,比方說(shuō) validate(Source schema, Source xmlDocument) 這樣的方法。但是模塊化有一定的好處,在 下一節(jié) 中將看到同時(shí)使用 SchemaValidator 類,可以解決 XML 處理中某些非常奇特的個(gè)別情況。而且如果確實(shí)需要可以自己編寫,不妨當(dāng)作一個(gè)很好的練習(xí)!





      回頁(yè)首


      深入了解驗(yàn)證

      對(duì)于很多應(yīng)用程序來(lái)說(shuō),上面介紹的這些內(nèi)容就足夠了。您可以把輸入文檔和模式交給一個(gè)方法讓它去驗(yàn)證。簡(jiǎn)單的 Exception 告訴您遇到了問(wèn)題,甚至還提供了一些解決問(wèn)題的基本信息。對(duì)于將 XML 作為數(shù)據(jù)格式的應(yīng)用程序,可能僅僅是傳遞某些信息,關(guān)于 JAXP 的驗(yàn)證功能可能知道這些就足夠了。

      但是,我們生活在一個(gè)到處都是 XML 編輯器、文件和代碼生成器以及 Web 服務(wù)的世界中。對(duì)于這類應(yīng)用程序,XML 就不僅僅起輔助作用,而 應(yīng)用程序本身,基本的驗(yàn)證常常就不夠了。對(duì)于這類應(yīng)用程序,JAXP 提供了很多特性,這是下面要討論的。

      處理錯(cuò)誤

      首先,人們認(rèn)為 Exception 表明發(fā)生了異常的行為。但是對(duì)于基于 XML 的應(yīng)用程序而言,文件驗(yàn)證失敗可能根本不是異常,僅僅可能的結(jié)果之一。比方說(shuō)支持 XML 的編輯器或者 IDE。在這些環(huán)境中,無(wú)效的 XML 不應(yīng)該造成系統(tǒng)崩潰和關(guān)閉。另外,如果只能以 Exception 形式報(bào)告錯(cuò)誤 ,就過(guò)于沉重了。

      當(dāng)然,對(duì)于 JAXP 老手這并不新鮮,您可能已經(jīng)習(xí)慣為 SAXParserDocumentBuilder 提供 org.xml.sax.ErrorHandler。這個(gè)接口提供的三個(gè)方法 warning()、error()fatalError() 簡(jiǎn)化了解析中的錯(cuò)誤處理。幸運(yùn)的是,驗(yàn)證 XML 時(shí)也有相同的設(shè)施可用。更好的是,使用的還是同一個(gè)接口。正是如此,ErrorHandler 接口在驗(yàn)證中與在解析中一樣有用。清單 6 提供了一個(gè)簡(jiǎn)單的例子。


      清單 6. 處理驗(yàn)證錯(cuò)誤
      				import javax.xml.XMLConstants;import javax.xml.transform.Source;import javax.xml.transform.stream.StreamSource;import javax.xml.validation.SchemaFactory;import javax.xml.validation.Schema;import javax.xml.validation.Validator;import org.xml.sax.ErrorHandler;...SchemaFactory schemaFactory =     SchemaFactory.newInstance(XMLConstants.W3C_SCHEMA_NS_URI);Source schemaSource = new StreamSource(new File("constraints.xml"));Schema schema = schemaFactory.newSchema(schemaSource);Validator validator = schema.newValidator();ErrorHandler mySchemaErrorHandler = new MySchemaErrorHandler();validator.setErrorHandler(mySchemaErrorHandler);validator.validate(new StreamSource("my-file.xml")); 

      和 SAX 一樣,可以使用該接口自定義錯(cuò)誤的處理。從而讓應(yīng)用程序從容地退出驗(yàn)證、打印錯(cuò)誤消息,甚至可以嘗試從錯(cuò)誤中恢復(fù)并繼續(xù)驗(yàn)證。如果熟悉這個(gè)接口,完全不需要再重新學(xué)習(xí)!

      裝入多個(gè)模式

      一個(gè)又一個(gè) setErrorHandler()

      如果閱讀 javax.xml.validation 包的 JavaDoc,可能會(huì)注意到 SchemaFactory 以及 Schema 類上的 setErrorHandler() 方法。如果為 SchemaFactory 設(shè)置異常處理程序,就可以處理在 newSchema() 調(diào)用過(guò)程中解析模式時(shí)出現(xiàn)的錯(cuò)誤。因此這也是驗(yàn)證 API 的一部分,不過(guò)不適用于模式驗(yàn)證錯(cuò)誤而是用于模式解析錯(cuò)誤。

      某些很少見(jiàn)的情況下,可能需要從多個(gè)模式構(gòu)造 Schema 對(duì)象。這有點(diǎn)兒費(fèi)解;一個(gè) Schema 不是 對(duì)應(yīng)一個(gè)模式或文件。相反,該對(duì)象表示一組約束。這些約束可以來(lái)一個(gè)文件,也可以來(lái)自多個(gè)文件。因此,可以通過(guò) newSchema(Source[] sourceList)newSchema() 方法提供一個(gè) Source 實(shí)現(xiàn)數(shù)組(表示多個(gè)約束)。返回的仍然是一個(gè) Schema 對(duì)象,表示所提供的模式的組合。

      可以預(yù)料,這種情況下會(huì)出現(xiàn)很多錯(cuò)誤。因此建議為 SchemaFactory 設(shè)置 ErrorHandler(更多信息參見(jiàn) 處理錯(cuò)誤 一節(jié))。很多地方都可能出問(wèn)題,因此要準(zhǔn)備好在出現(xiàn)的時(shí)候解決問(wèn)題。

      把驗(yàn)證集成到解析中

      到目前為止,我們一直把驗(yàn)證作為獨(dú)立于解析的單獨(dú)部分。但是并非必須如此。得到 Schema 對(duì)象后,就可以將其賦給 SAXParserFactoryDocumentBuilderFactory,都通過(guò) setSchema() 方法(參見(jiàn)清單 7)。


      清單 7. 把驗(yàn)證集成到解析中
      				// Load up the documentDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// Set up an XML Schema validator, using the supplied schemaSource schemaSource = new StreamSource(new File(args[1]));SchemaFactory schemaFactory = SchemaFactory.newInstance(  XMLConstants.W3C_XML_SCHEMA_NS_URI);Schema schema = schemaFactory.newSchema(schemaSource);// Instead of explicitly validating, assign the Schema to the factoryfactory.setSchema(schema);// Parsers from this factory will automatically validate against the//   associated schemaDocumentBuilder builder = factory.newDocumentBuilder();Document doc = builder.parse(new File(args[0])); 

      要注意,這里 需要使用 setValidating() 方法顯式地打開(kāi)驗(yàn)證。任何 Schema 不是 null 的工廠所創(chuàng)建的解析器都會(huì)使用那個(gè) Schema 進(jìn)行驗(yàn)證??梢灶A(yù)料,驗(yàn)證錯(cuò)誤都會(huì)報(bào)告給解析器設(shè)置的 ErrorHandler。





      回頁(yè)首


      重要的警告

      雖 然看起來(lái)不錯(cuò),我認(rèn)為還不夠好,JAXP 的新驗(yàn)證 API 存在一些嚴(yán)重的問(wèn)題。首先,即使在 Java 5.0 和 JAXP 1.3 正式版中,我也發(fā)現(xiàn)有很多錯(cuò)誤和奇怪的行為。新的 API 仍然在增加解析器支持,這意味著個(gè)別情況(很少使用的特性)僅僅部分實(shí)現(xiàn)了(有時(shí)候根本沒(méi)有實(shí)現(xiàn))。我發(fā)現(xiàn)很多時(shí)候,能夠通過(guò)獨(dú)立驗(yàn)證器如 xmllint(請(qǐng)參閱 參考資料)驗(yàn)證的文檔卻不能通過(guò) JAXP 的驗(yàn)證。

      直接使用 Validator 類和 validate() 方法,與將 Schema 賦給 SAXParserFactoryDocumentBuilderFactory 相比,似乎更可靠。建議您采用比較保險(xiǎn)的辦法。我并不是要求您避開(kāi)這種 API,而是說(shuō)應(yīng)該使用盡可能多的樣本文檔,并對(duì)驗(yàn)證結(jié)果檢查兩次,對(duì)錯(cuò)誤處理要小心謹(jǐn)慎。





      回頁(yè)首


      結(jié)束語(yǔ)

      坦白地說(shuō),JAXP 驗(yàn)證 API 并沒(méi)有明顯的新東西??梢岳^續(xù)使用 SAX 或 DOM 解析和驗(yàn)證 XML,并結(jié)合 SAX 的 ErrorHandler 類,通過(guò)巧妙的編程也能對(duì)驗(yàn)證錯(cuò)誤進(jìn)行即時(shí)處理。但是這需要對(duì) SAX 有充分的了解,需要很多時(shí)間去測(cè)試和調(diào)試并且仔細(xì)地管理內(nèi)存(如果最終創(chuàng)建 DOM Document 對(duì)象的話)。這正是 JAXP 驗(yàn)證 API 閃光的地方。它提供了一種經(jīng)過(guò)認(rèn)真測(cè)試的、可以隨時(shí)使用的解決方案,而不僅僅是是否啟用模式驗(yàn)證的一個(gè)開(kāi)關(guān)。它很容易與已有的 JAXP 代碼結(jié)合在一起,增加模式驗(yàn)證非常簡(jiǎn)單。我相信,長(zhǎng)期使用 XML 的 Java 開(kāi)發(fā)人員一定會(huì)發(fā)現(xiàn) JAXP 驗(yàn)證的一些優(yōu)點(diǎn)。

      http://blog.csdn.net/haydenwang8287/archive/2007/09/13/1784398.aspx

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多