這篇文章主要介紹在Java中如何使用DOM和XPath進行有效的XML處理,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)公司一直秉承“誠信做人,踏實做事”的原則,不欺瞞客戶,是我們最起碼的底線! 以服務為基礎,以質(zhì)量求生存,以技術求發(fā)展,成交一個客戶多一個朋友!為您提供網(wǎng)站設計制作、做網(wǎng)站、成都網(wǎng)頁設計、小程序設計、成都網(wǎng)站開發(fā)、成都網(wǎng)站制作、成都軟件開發(fā)、重慶App定制開發(fā)是成都本地專業(yè)的網(wǎng)站建設和網(wǎng)站設計公司,等你一起來見證!
文檔對象模型
DOM 規(guī)范被設計成可與任何編程語言一起使用。因此,它嘗試使用在所有語言中都可用的一組通用的、核心的功能部件。DOM 規(guī)范同樣嘗試保持其接口定義方面的無關性。這就允許 Java 程序員在使用 Visual Basic 或 Perl 時應用他們的 DOM 知識,反之亦然。
該規(guī)范同樣將文檔的每個部分看成由類型和值組成的節(jié)點。這為處理文檔的所有方面提供了***的概念性框架。例如,下面的 XML 片段
the Italicized portion. |
就是通過以下的 DOM 結構表示的:
圖 1:XML 文檔的 DOM 表示
樹的每個Document 、 Element 、 Text 和 Attr 部分都是 DOM Node 。
***的抽象確實付出了代價。考慮 XML 片段: Value 。您或許會認為文本的值可以通過普通的 Java String 對象來表示,并且通過簡單的 getValue 調(diào)用可訪問。實際上,文本被當成 tagname 節(jié)點下的一個或多個子 Node 。因此,為了獲取文本值,您需要遍歷 tagname 的子節(jié)點,將每個值整理成一個字符串。這樣做有充分的理由: tagname 可能包含其它嵌入的 XML 元素,在這種情況下獲取其文本值沒有多大意義。然而,在現(xiàn)實世界中,我們看到由于缺乏便利的函數(shù)導致頻繁的編碼錯誤占了 80% 的情況,這樣做的確有意義。
設計問題
DOM 語言無關性的缺點是通常在每個編程語言中使用的一整套工作方法和模式不能被使用。例如,不能使用熟悉的 Java new 構造創(chuàng)建新的 Element ,開發(fā)者必須使用工廠構造器方法。 Node 的集合被表示成 NodeList ,而不是通常的 List 或 Iterator 對象。這些微小的不便意味著不同尋常的編碼實踐和增多的代碼行,并且它們迫使程序員學習 DOM 的行事方法而不是用直覺的方法。
DOM 使用“一切都是節(jié)點”的抽象。這就意味著幾乎 XML 文檔的每個部分,例如: Document 、 Element 和 Attr ,全都繼承( extend ) Node 接口。這不僅是概念上***,而且還允許每個 DOM 的不同實現(xiàn)通過標準接口使其自身的類可見,并且沒有通過中間包裝類所導致的性能損失。
由于存在的節(jié)點類型數(shù)量及其訪問方法缺乏一致性,“一切都是節(jié)點”的抽象喪失了一些意義。例如, insertData 方法被用來設置 CharacterData 節(jié)點的值,而通過使用 setValue 方法來設置 Attr (屬性)節(jié)點的值。由于對于不同的節(jié)點存在不同的接口,模型的一致性和***性降低了,而學習曲線增加了。
JDOM
JDOM 是使 DOM API 適應 Java 的研究計劃,從而提供了更自然和易用的接口。由于認識到語言無關 DOM 構造的棘手本質(zhì),JDOM 目標在于使用內(nèi)嵌的 Java 表示和對象,并且為常用任務提供便利的函數(shù)。
例如,JDOM 直接處理“一切都是節(jié)點”和 DOM 特定構造的使用(如 NodeList )。JDOM 將不同的節(jié)點類型(如 Document 、 Element 和 Attribute )定義為不同的 Java 類,這意味著開發(fā)者可以使用 new 構造它們,避免頻繁類型轉換的需要。JDOM 將字符串表示成 Java String ,并且通過普通的 List 和 Iterator 類來表示節(jié)點的集合。(JDOM 用其本身類替代 DOM 類。)
JDOM 為提供更完善的接口做了相當有益的工作。它已經(jīng)被接受成為 JSR(正式的 Java Specification Request),而且它將來很可能會被包含到核心的 Java 平臺中。但是,因其還不是核心 Java API 的一部分,一些人對于使用它還心存猶豫。這兒還有關于與 Iterator 和 Java 對象頻繁創(chuàng)建相關的性能問題的報告。(請參閱 參考資料)。
如果您對 JDOM 的接受性和可用性已經(jīng)滿足,并且如果您也沒有將 Java 代碼和程序員轉移到其它語言的直接需求,JDOM 是個值得探索的好選擇。JDOM 還不能滿足本文探討的項目所在的公司需要,因而他們使用了非常普遍的 DOM。本文也是這樣做的。
常見編碼問題
幾個大型 XML 項目分析揭示了使用 DOM 中的一些常見問題。下面對其中的幾個進行介紹。
代碼臃腫
在我們研究中查看的所有項目,本身都出現(xiàn)一個突出的問題:花費許多行代碼行來做簡單的事情。在某個示例中,使用 16 行代碼檢查一個屬性的值。而同樣的任務,帶有改進的健壯性和出錯處理,可以使用 3 行代碼實現(xiàn)。DOM API 的低級本質(zhì)、方法和編程模式的不正確應用以及缺乏完整 API 的知識,都會致使代碼行數(shù)增加。下面的摘要介紹了關于這些問題的特定實例。
遍歷 DOM
在我們探討的代碼中,最常見的任務是遍歷或搜索 DOM。 清單 1 演示了需要在文檔的 config 節(jié)里查找一個稱為“header”節(jié)點的濃縮版本代碼:
清單 1 中,從根開始通過檢索頂端元素遍歷文檔,獲取其***個子節(jié)點( configNode ),并且最終單獨檢查 configNode 的子節(jié)點。不幸的是,這種方法不僅冗長,而且還伴隨著脆弱性和潛在的錯誤。
例如,第二行代碼通過使用 getFirstChild 方法獲取中間的 config 節(jié)點。已經(jīng)存在許多潛在的問題。根節(jié)點的***個子節(jié)點實際上可能并不是用戶正在搜索的節(jié)點。由于盲目地跟隨***個子節(jié)點,我忽視了標記的實際名稱并且可能搜索不正確的文檔部分。當源 XML 文檔的根節(jié)點后包含空格或回車時,這種情況中發(fā)生一個頻繁的錯誤;根節(jié)點的***個子節(jié)點實際是 Node.TEXT_NODE 節(jié)點,而不是所希望的元素節(jié)點。您可以自己試驗一下,從 參考資料下載樣本代碼并且編輯 sample.xml 文件 ― 在 sample 和 config 標記之間放置一個回車。代碼立即異常而終止。要正確瀏覽所希望的節(jié)點,需要檢查每個 root 的子節(jié)點,直到找到非 Text 的節(jié)點,并且那個節(jié)點有我正在查找的名稱為止。
清單 1 還忽視了文檔結構可能與我們期望有所不同的可能性。例如,如果 root 沒有任何子節(jié)點, configNode 將會被設置為 null ,并且示例的第三行將產(chǎn)生一個錯誤。因此,要正確瀏覽文檔,不僅要單獨檢查每個子節(jié)點以及核對相應的名稱,而且每步都得檢查以確保每個方法調(diào)用返回的是一個有效值。編寫能夠處理任意輸入的健壯、無錯的代碼,不僅需要非常關注細節(jié),而且需要編寫很多行代碼。
最終,如果最初的開發(fā)者了解它的話,清單 1 中示例的所有功能應該可以通過利用對 getElementsByTagName 函數(shù)的簡單調(diào)用實現(xiàn)。這是下面要討論的。
檢索元素中的文本值
在所分析的項目中,DOM 遍歷以后,第二項最常進行的任務是檢索在元素中包含的文本值??紤] XML 片段 The Value 。如果已經(jīng)導航到 sometag 節(jié)點,如何獲取其文本值( The Value )呢?一個直觀的實現(xiàn)可能是:
sometagElement.getData(); |
正如您所猜測到的,上面的代碼并不會執(zhí)行我們希望的動作。由于實際的文本被存儲為一個或多個子節(jié)點,因此不能對 sometag 元素調(diào)用 getData 或類似的函數(shù)。更好的方法可能是:
sometag.getFirstChild().getData(); |
第二種嘗試的問題在于值實際上可能并不包含在***個子節(jié)點中;在 sometag 內(nèi)可能會發(fā)現(xiàn)處理指令或其它嵌入的節(jié)點,或是文本值包含在幾個子節(jié)點而不是單單一個子節(jié)點中??紤]到空格經(jīng)常作為文本節(jié)點表示,因此對 sometag.getFirstChild() 的調(diào)用可能僅讓您得到標記和值之間的回車。實際上,您需要遍歷所有子節(jié)點,以核對 Node.TEXT_NODE 類型的節(jié)點,并且整理它們的值直到有完整的值為止。
注意,JDOM 已經(jīng)利用便利的函數(shù) getText 為我們解決了這個問題。DOM 級別 3 也將有一個使用規(guī)劃的 getTextContent 方法的解答。教訓:盡可能使用較高級的 API 是不會錯的。
getElementsByTagName
DOM 級別 2 接口包含一個查找給定名稱的子節(jié)點的方法。例如,調(diào)用:
NodeList names = someElement.getElementsByTagName("name"); |
將返回一個包含在 someElement 節(jié)點中稱為 names 的節(jié)點 NodeList 。這無疑比我所討論的遍歷方法更方便。這也是一組常見錯誤的原因。
問題在于 getElementsByTagName 遞歸地遍歷文檔,從而返回所有匹配的節(jié)點。假定您有一個包含客戶信息、公司信息和產(chǎn)品信息的文檔。所有這三個項中都可能含有 name 標記。如果調(diào)用 getElementsByTagName 搜索客戶名稱,您的程序極有可能行為失常,除了檢索出客戶名稱,還會檢索出產(chǎn)品和公司名稱。在文檔的子樹上調(diào)用該函數(shù)可能會降低風險,但由于 XML 的靈活本質(zhì),使確保您所操作的子樹包含您期望的結構,且沒有您正在搜索的名稱的虛假子節(jié)點就變得十分困難。
DOM 的有效使用
考慮到由 DOM 設計強加的限制,如何才能有效和高效的使用該規(guī)范呢?下面是使用 DOM 的幾條基本原則和方針,以及使工作更方便的函數(shù)庫。
基本原則
如果您遵循幾條基本原則,您使用 DOM 的經(jīng)驗將會顯著提高:
◆ 不要使用 DOM 遍歷文檔。
◆ 盡可能使用 XPath 來查找節(jié)點或遍歷文檔。
◆ 使用較高級的函數(shù)庫來更方便地使用 DOM。
這些原則直接從對常見問題的研究中得到。正如上面所討論的,DOM 遍歷是出錯的主要原因。但它也是最常需要的功能之一。如何通過不使用 DOM 而遍歷文檔呢?
Path
XPath 是尋址、搜索和匹配文檔的各個部分的語言。它是 W3C 推薦標準(Recommendation),并且在大多數(shù)語言和 XML 包中實現(xiàn)。您的 DOM 包可能直接支持 XPath 或通過加載件(add-on)支持。本文的樣本代碼對于 XPath 支持使用 Xalan 包。
XPath 使用路徑標記法來指定和匹配文檔的各個部分,該標記法與文件系統(tǒng)和 URL 中使用的類似。例如,XPath: /x/y/z 搜索文檔的根節(jié)點 x ,其下存在節(jié)點 y ,其下存在節(jié)點 z 。該語句返回與指定路徑結構匹配的所有節(jié)點。
更為復雜的匹配可能同時在包含文檔的結構方面以及在節(jié)點及其屬性的值中。語句 /x/y/* 返回父節(jié)點為 x 的 y 節(jié)點下的任何節(jié)點。 /x/y[@name='a'] 匹配所有父節(jié)點為 x 的 y 節(jié)點,其屬性稱為 name ,屬性值為 a 。請注意,XPath 處理篩選空格文本節(jié)點以獲得實際的元素節(jié)點 ― 它只返回元素節(jié)點。
詳細探討 XPath 及其用法超出了本文的范圍。請參閱 參考資料獲得一些優(yōu)秀教程的鏈接?;c時間學習 XPath,您將會更方便的處理 XML 文檔。
函數(shù)庫
當研究 DOM 項目時令我們驚奇的一個發(fā)現(xiàn),是存在的拷貝和粘貼代碼的數(shù)量。為什么有經(jīng)驗的開發(fā)者沒有使用良好的編程習慣,卻使用拷貝和粘貼方法而不是創(chuàng)建助手(helper)庫呢?我們相信這是由于 DOM 的復雜性加深了學習的難度,并使開發(fā)者要理解能完成他們所需要的***段代碼。開發(fā)產(chǎn)生構成助手庫規(guī)范的函數(shù)所需的專門技術需要花費大量的時間。
要節(jié)省一些走彎路的時間,這里是一些將使您自己的庫可以運轉起來的基本助手函數(shù)。
findValue
使用 XML 文檔時,最常執(zhí)行的操作是查找給定節(jié)點的值。正如上所討論的,在遍歷文檔以查找期望的值和檢索節(jié)點的值中都出現(xiàn)難度。可以通過使用 XPath 來簡化遍歷,而值的檢索可以一次編碼然后重用。在兩個較低級函數(shù)的幫助下,我們實現(xiàn)了 getValue 函數(shù),這兩個低級函數(shù)是:由 Xalan 包提供的 XPathAPI.selectSingleNode (用來查找和返回與給定的 XPath 表達式匹配的***個節(jié)點);以及 getTextContents ,它非遞歸地返回包含在節(jié)點中的連續(xù)文本值。請注意,JDOM 的 getText 函數(shù),或將出現(xiàn)在 DOM 級別 3 中規(guī)劃的 getTextContent 方法,都可用來代替 getTextContents 。 清單 2包含了一個簡化的清單;您可以通過下載樣本代碼來訪問所有函數(shù)(請參閱 參考資料)。
通過同時傳入要開始搜索的節(jié)點和指定要搜索節(jié)點的 XPath 語句來調(diào)用 findValue 。函數(shù)查找***個與給定 XPath 匹配的節(jié)點,并且抽取其文本值。
setValue
另一項常用的操作是將節(jié)點的值設置為希望的值,如 清單 3 所示。該函數(shù)獲取一個起始節(jié)點和一條 XPath 語句 ― 就象 findValue ― 以及一個用來設置匹配的節(jié)點值的字符串。它查找希望的節(jié)點,除去其所有子節(jié)點(因此除去包含在其中的任何文本和其它元素),并將其文本內(nèi)容設置為傳入的(passed-in)字符串。
appendNode
雖然某些程序查找和修改包含在 XML 文檔中的值,而另一些則通過添加和除去節(jié)點來修改文檔本身的結構。這個助手函數(shù)簡化了文檔節(jié)點的添加,如 清單 4所示。
該函數(shù)的參數(shù)有:要將新節(jié)點添加到其下的節(jié)點,要添加的新節(jié)點名稱,以及指定要將節(jié)點添加到其下位置的 XPath 語句(也就是,新節(jié)點的父節(jié)點應當是哪個)。新節(jié)點被添加到文檔的指定位置。
以上是“在Java中如何使用DOM和XPath進行有效的XML處理”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
新聞名稱:在Java中如何使用DOM和XPath進行有效的XML處理
網(wǎng)站路徑:http://m.rwnh.cn/article16/ipghgg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供、網(wǎng)站收錄、網(wǎng)站維護、企業(yè)建站、全網(wǎng)營銷推廣、品牌網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)