欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java 中的 XML: Java 文檔模型的用法
簡(jiǎn)要探討 Java 中不同 XML 文檔模型的工作原理

Dennis M. Sosnoski
總裁, Sosnoski Software Solutions, Inc.
2002 年 2 月

本文中,XML 工具觀(guān)察家 Dennis Sosnoski 對比了幾種 Java 文檔模型的可用性。當選取一種模型時(shí)并不總是很清楚有哪些折衷,而且如果您稍后改了主意,那么可能需要進(jìn)行大量重新編碼工作才能轉換。作者將樣本代碼與模型 API 的分析相結合,對哪些模型可能真正使您的工作方便給出了建議。本文包含顯示五種不同文檔模型的方法的代碼樣本。

在本系列的第一篇文章中,我研究了一些用 Java 編寫(xiě)的主要的 XML 文檔模型的性能。但是,在開(kāi)始選擇這種類(lèi)型的技術(shù)時(shí),性能只是問(wèn)題的一部分。使用方便至少是同樣重要的,并且它已是一個(gè)主要理由,來(lái)支持使用 Java 特定的模型,而不是與語(yǔ)言無(wú)關(guān)的 DOM 。

為切實(shí)了解哪個(gè)模型真正的作用,您需要知道它們在可用性程度上是如何排名的。本文中,我將嘗試進(jìn)行這個(gè)工作,從樣本代碼開(kāi)始,來(lái)演示如何在每個(gè)模型中編碼公共類(lèi)型的操作。并對結果進(jìn)行總結來(lái)結束本文,而且提出了促使一種表示比另一種更容易使用的一些其它因素。

請參閱以前的文章(請參閱 參考資料或本文“內容”下的便捷鏈接)來(lái)獲取這個(gè)對比中使用的各個(gè)模型的背景資料,包含實(shí)際的版本號。還可以參閱“參考資料”一節中關(guān)于源代碼下載、到模型主頁(yè)的鏈接以及其它相關(guān)信息。

代碼對比
在對不同文檔表示中用法技術(shù)的這些對比中,我將顯示如何在每種模型中實(shí)現三種基本操作:

  • 根據輸入流構建文檔
  • 遍歷元素和內容,并做一些更改:
    • 從文本內容中除去前導和尾隨的空白。
    • 如果結果文本內容為空,就刪除它。
    • 否則,將它包裝到父元素的名稱(chēng)空間中一個(gè)名為“text”的新元素中。
  • 將已修改的文檔寫(xiě)入輸出流

這些示例的代碼是以我在上篇文章中使用的基準程序為基礎的,并進(jìn)行了一些簡(jiǎn)化?;鶞食绦虻慕裹c(diǎn)是為了顯示每個(gè)模型的最佳性能;對于本文,我將嘗試顯示在每種模型中實(shí)現操作的最簡(jiǎn)便方法。

我已經(jīng)將每個(gè)模型的示例結構化為兩個(gè)獨立的代碼段。第一段是讀取文檔、調用修改代碼和編寫(xiě)已修改文檔的代碼。第二段是真正遍歷文檔表示和執行修改的遞歸方法。為避免分散注意力,我已在代碼中忽略了異常處理。

您可以從本頁(yè)底部 參考資料一節鏈接到下載頁(yè),以獲取所有樣本的完整代碼。樣本的下載版本包括一個(gè)測試驅動(dòng)程序,還有一些添加的代碼用于通過(guò)計算元素、刪除和添加的個(gè)數來(lái)檢查不同模型的操作。

即使您不想使用 DOM 實(shí)現,但還是值得瀏覽下面對 DOM 用法的描述。因為 DOM 示例是第一個(gè)示例,所以與后面的模型相比,我用它來(lái)探究有關(guān)該示例的一些問(wèn)題和結構的更詳細信息。瀏覽這些內容可以補充您想知道的一些細節,如果直接閱讀其它模型之一,那么將錯過(guò)這些細節。

DOM
DOM 規范涵蓋了文檔表示的所有類(lèi)型的操作,但是它沒(méi)有涉及例如對文檔的語(yǔ)法分析和生成文本輸出這樣的問(wèn)題。包括在性能測試中的兩種 DOM 實(shí)現,Xerces 和 Crimson,對這些操作使用不同的技術(shù)。清單 1 顯示了 Xerces 的頂級代碼的一種形式。

清單 1. Xerces DOM 頂級代碼
 1  // parse the document from input stream ("in") 2  DOMParser parser = new DOMParser(); 3  parser.setFeature("http://xml.org/sax/features/namespaces", true); 4  parser.parse(new InputSource(in)); 5  Document doc = parser.getDocument(); 6  // recursively walk and modify document 7  modifyElement(doc.getDocumentElement()); 8  // write the document to output stream ("out") 9  OutputFormat format = new OutputFormat(doc);10  XMLSerializer serializer = new XMLSerializer(out, format);11  serializer.serialize(doc.getDocumentElement());

正如我在注釋中指出的,清單 1 中的第一塊代碼(第 1-5 行)處理對輸入流的語(yǔ)法分析,以構建文檔表示。Xerces 定義了 DOMParser 類(lèi),以便從 Xerces 語(yǔ)法分析器的輸出構建文檔。 InputSource 類(lèi)是 SAX 規范的一部分,它能適應供 SAX 分析器使用的幾種輸入形式的任何之一。通過(guò)單一調用進(jìn)行實(shí)際的語(yǔ)法分析和文檔構造,如果成功完成了這一操作,那么應用程序就可以檢索并使用已構造的 Document 。

第二個(gè)代碼塊(第 6-7 行)只是將文檔的根元素傳遞給我馬上要談到的遞歸修改方法。這些代碼與本文中所有文檔模型的代碼在本質(zhì)上是相同的,所以在剩余的示例中我將跳過(guò)它,不再做任何討論。

第三個(gè)代碼塊(第 8-11 行)處理將文檔作為文本寫(xiě)入輸出流。這里, OutputFormat 類(lèi)包裝文檔,并為格式化生成的文本提供了多種選項。 XMLSerializer 類(lèi)處理輸出文本的實(shí)際生成。

Xerces 的 modify 方法只使用標準 DOM 接口,所以它還與任何其它 DOM 實(shí)現兼容。清單 2 顯示了代碼。

清單 2. DOM Modify 方法
 1  protected void modifyElement(Element element) { 2    // loop through child nodes 3    Node child; 4    Node next = (Node)element.getFirstChild(); 5    while ((child = next) != null) { 6      // set next before we change anything 7      next = child.getNextSibling(); 8      // handle child by node type 9      if (child.getNodeType() == Node.TEXT_NODE) {10        // trim whitespace from content text11        String trimmed = child.getNodeValue().trim();12        if (trimmed.length() == 0) {13          // delete child if nothing but whitespace14          element.removeChild(child);15        } else {16          // create a "text" element matching parent namespace17          Document doc = element.getOwnerDocument();18          String prefix = element.getPrefix();19          String name = (prefix == null) ? "text" : (prefix + ":text");20          Element text = 21            doc.createElementNS(element.getNamespaceURI(), name);22          // wrap the trimmed content with new element23          text.appendChild(doc.createTextNode(trimmed));24          element.replaceChild(text, child);25        }26      } else if (child.getNodeType() == Node.ELEMENT_NODE) {27        // handle child elements with recursive call28        modifyElement((Element)child);29      }30    }31  }

清單 2 中顯示的方法所使用的基本方法與所有文檔表示的方法相同。 通過(guò)一個(gè)元素調用它,它就依次遍歷那個(gè)元素的子元素。如果找到文本內容子元素,要么刪除文本(如果它只是由空格組成的),要么通過(guò)與包含元素相同的名稱(chēng)空間中名為“text”的新元素來(lái)包裝文本(如果有非空格的字符)。如果找到一個(gè)子元素,那么這個(gè)方法就使用這個(gè)子元素,遞歸地調用它本身。

對于 DOM 實(shí)現,我使用一對引用: childnext 來(lái)跟蹤子元素排序列表中我所處的位置。在對當前子節點(diǎn)進(jìn)行任何其它處理之前,先裝入下個(gè)子節點(diǎn)的引用(第 7 行)。這樣做使得我能夠刪除或替代當前的子節點(diǎn),而不丟失我在列表中的蹤跡。

當我創(chuàng )建一個(gè)新元素來(lái)包裝非空白的文本內容(第 16-24 行)時(shí),DOM 接口開(kāi)始有點(diǎn)雜亂。用來(lái)創(chuàng )建元素的方法與文檔關(guān)聯(lián)并成為一個(gè)整體,所以我需要在所有者文檔中檢索當前我正在處理的元素(第 17 行)。我想將這個(gè)新元素放置在與現有的父元素相同的名稱(chēng)空間中,并且在 DOM 中,這意味著(zhù)我需要構造元素的限定名稱(chēng)。根據是否有名稱(chēng)空間的前綴,這個(gè)操作會(huì )有所不同(第 18-19 行)。利用新元素的限定名稱(chēng),以及現有元素中的名稱(chēng)空間 URI,我就能創(chuàng )建新元素(第 20-21 行)。

一旦創(chuàng )建了新元素,我只要創(chuàng )建和添加文本節點(diǎn)來(lái)包裝內容 String ,然后用新創(chuàng )建的元素來(lái)替代原始文本節點(diǎn)(第 22-24 行)。

清單 3. Crimson DOM 頂級代碼
 1  // parse the document from input stream 2  System.setProperty("javax.xml.parsers.DocumentBuilderFactory", 3      "org.apache.crimson.jaxp.DocumentBuilderFactoryImpl"); 4  DocumentBuilderFactory dbf = DocumentBuilderFactoryImpl.newInstance(); 5  dbf.setNamespaceAware(true); 6  DocumentBuilder builder = dbf.newDocumentBuilder(); 7  Document doc = builder.parse(in); 8  // recursively walk and modify document 9  modifyElement(doc.getDocumentElement());10  // write the document to output stream11  ((XmlDocument)doc).write(out);

清單 3 中的 Crimson DOM 示例代碼使用了用于語(yǔ)法分析的 JAXP 接口。JAXP 為語(yǔ)法分析和轉換 XML 文檔提供了一個(gè)標準化的接口。本示例中的語(yǔ)法分析代碼還可以用于 Xerces(對文檔構建器類(lèi)名稱(chēng)的特性設置有適當的更改)來(lái)替代較早給定的 Xerces 特定的示例代碼。

在本示例中,我首先在第 2 行到第 3 行中設置系統特性來(lái)選擇要構造的 DOM 表示的構建器工廠(chǎng)類(lèi)(JAXP 僅直接支持構建 DOM 表示,不支持構建本文中討論的任何其它表示)。僅當想選擇一個(gè)要由 JAXP 使用的特定 DOM 時(shí),才需要這一步;否則,它使用缺省實(shí)現。出于完整性起見(jiàn),我在代碼中包含了設置這個(gè)特性,但是更普遍的是將它設置成一個(gè) JVM 命令行參數。

接著(zhù)我在第 4 行到第 6 行中創(chuàng )建構建器工廠(chǎng)的實(shí)例,對使用那個(gè)工廠(chǎng)實(shí)例構造的構建器啟用名稱(chēng)空間支持,并從構建器工廠(chǎng)創(chuàng )建文檔構建器。最后(第 7 行),我使用文檔構建器來(lái)對輸入流進(jìn)行語(yǔ)法分析并構造文檔表示。

為了寫(xiě)出文檔,我使用 Crimson 中內部定義的基本方法。不保證在 Crimson 未來(lái)版本中支持這個(gè)方法,但是使用 JAXP 轉換代碼來(lái)將文檔作為文本輸出的替代方法需要諸如 Xalan 那樣的 XSL 處理器的。那超出了本文的范圍,但是要獲取詳細信息,可以查閱 Sun 中的 JAXP 教程。

JDOM
使用 JDOM 的頂級代碼比使用 DOM 實(shí)現的代碼稍微簡(jiǎn)單一點(diǎn)。為構建文檔表示(第 1-3 行),我使用帶有由參數值禁止驗證的 SAXBuilder 。通過(guò)使用提供的 XMLOutputter 類(lèi),將已修改的文檔寫(xiě)入輸出流同樣簡(jiǎn)單(第 6-8 行)。

清單 4. JDOM 頂級代碼
 1  // parse the document from input stream 2  SAXBuilder builder = new SAXBuilder(false); 3  Document doc = builder.build(in); 4  // recursively walk and modify document 5  modifyElement(doc.getRootElement()); 6  // write the document to output stream 7  XMLOutputter outer = new XMLOutputter(); 8  outer.output(doc, out);

清單 5 中 JDOM 的 modify 方法也比 DOM 的同一方法簡(jiǎn)單。我獲取包含元素所有內容的列表并掃描了這張列表,檢查文本(象 String 對象那樣的內容)和元素。這張列表是“活的”,所以我能直接對它進(jìn)行更改,而不必調用父元素上的方法。

清單 5. JDOM modify 方法
 1  protected void modifyElement(Element element) { 2    // loop through child nodes 3    List children = element.getContent(); 4    for (int i = 0; i < children.size(); i++) { 5      // handle child by node type 6      Object child = children.get(i); 7      if (child instanceof String) { 8        // trim whitespace from content text 9        String trimmed = child.toString().trim();10        if (trimmed.length() == 0) {11          // delete child if only whitespace (adjusting index)12          children.remove(i--);13        } else {14          // wrap the trimmed content with new element15          Element text = new Element("text", element.getNamespace());16          text.setText(trimmed);17          children.set(i, text);18        }19      } else if (child instanceof Element) {20        // handle child elements with recursive call21        modifyElement((Element)child);22      }23    }24  }

創(chuàng )建新元素的技術(shù)(第 14-17 行)非常簡(jiǎn)單,而且與 DOM 版本不同,它不需要訪(fǎng)問(wèn)父文檔。

dom4j
dom4j 的頂級代碼比 JDOM 的稍微復雜些,但是它們的代碼行非常類(lèi)似。這里的主要區別是我保存了用來(lái)構建 dom4j 文檔表示的 DocumentFactory (第 5 行),并在輸出已修改的文檔文本之后刷新了 writer(第 10 行)。

清單 6. dom4j 的頂級代碼
 1  // parse the document from input stream 2  SAXReader reader = new SAXReader(false); 3  Document doc = reader.read(in); 4  // recursively walk and modify document 5  m_factory = reader.getDocumentFactory(); 6  modifyElement(doc.getRootElement()); 7  // write the document to output stream 8  XMLWriter writer = new XMLWriter(out); 9  writer.write(doc);10  writer.flush();

正如您在清單 6 中看到的,dom4j 使用一個(gè)工廠(chǎng)方法來(lái)構造文檔表示(從語(yǔ)法分析構建)中包含的對象。根據接口來(lái)定義每個(gè)組件對象,所以實(shí)現其中一個(gè)接口的任何類(lèi)型的對象都能包含在表示中(與 JDOM 相反,它使用具體類(lèi):這些類(lèi)在某些情況中可以劃分子類(lèi)和被繼承,但是在文檔表示中使用的任何類(lèi)都需要以原始 JDOM 類(lèi)為基礎)。通過(guò)使用不同工廠(chǎng)進(jìn)行 dom4j 文檔構建,您能獲取不同系列的組件中構造的文檔。

在樣本代碼(第 5 行)中,我檢索了用于構建文檔的(缺?。┪臋n工廠(chǎng),并將它存儲在一個(gè)實(shí)例變量( m_factory )中以供 modify 方法使用。并不嚴格需要這一步 — 可以在一個(gè)文檔中同時(shí)使用來(lái)自不同工廠(chǎng)的組件,或者可以繞過(guò)工廠(chǎng)而直接創(chuàng )建組件的實(shí)例 — 但在該例中,我只想創(chuàng )建與在文檔其余部分中使用的同一類(lèi)型的組件,并且使用相同的工廠(chǎng)來(lái)確保完成這個(gè)步驟。

清單 7. dom4j modify 方法
 1  protected void modifyElement(Element element) { 2    // loop through child nodes 3    List children = element.content(); 4    for (int i = 0; i < children.size(); i++) { 5      // handle child by node type 6      Node child = (Node)children.get(i); 7      if (child.getNodeType() == Node.TEXT_NODE) { 8        // trim whitespace from content text 9        String trimmed = child.getText().trim();10        if (trimmed.length() == 0) {11          // delete child if only whitespace (adjusting index)12          children.remove(i--);13        } else {14          // wrap the trimmed content with new element15          Element text = m_factory.createElement16            (QName.get("text", element.getNamespace()));17          text.addText(trimmed);18          children.set(i, text);19        }20      } else if (child.getNodeType() == Node.ELEMENT_NODE) {21        // handle child elements with recursive call22        modifyElement((Element)child);23      }24    }25  }

清單 7 中 dom4j modify 方法與 JDOM 中使用的方法非常類(lèi)似。不通過(guò)使用 instanceof 運算符來(lái)檢查內容項的類(lèi)型,我可以通過(guò) Node 接口方法 getNodeType 來(lái)獲取類(lèi)型代碼(也可以使用 instanceof ,但類(lèi)型代碼方法看起來(lái)更清晰)。通過(guò)使用 QName 對象來(lái)表示元素名稱(chēng)和通過(guò)調用已保存的工廠(chǎng)的方法來(lái)構建元素可以區別新元素的創(chuàng )建技術(shù)(第 15-16 行)。

Electric XML
清單 8 中 Electric XML(EXML)的頂級代碼是任何這些示例中最簡(jiǎn)單的一個(gè),通過(guò)單一方法調用就可以讀取和編寫(xiě)文檔。

清單 8. EXML 頂級代碼
 1  // parse the document from input stream 2  Document doc = new Document(in); 3  // recursively walk and modify document 4  modifyElement(doc.getRoot()); 5  // write the document to output stream 6  doc.write(out);

清單 9 中 EXML modify 方法盡管與 JDOM 一樣,需要使用 instanceof 檢查,但它與 DOM 方法最相似。在 EXML 中,無(wú)法創(chuàng )建一個(gè)帶名稱(chēng)空間限定的名稱(chēng)的元素,所以取而代之,我創(chuàng )建新元素,然后設置其名稱(chēng)來(lái)達到相同的效果。

清單 9. EXML modify 方法
 1  protected void modifyElement(Element element) { 2    // loop through child nodes 3    Child child; 4    Child next = element.getChildren().first(); 5    while ((child = next) != null) { 6      // set next before we change anything 7      next = child.getNextSibling(); 8      // handle child by node type 9      if (child instanceof Text) {10        // trim whitespace from content text11        String trimmed = ((Text)child).getString().trim();12        if (trimmed.length() == 0) {13          // delete child if only whitespace14          child.remove();15        } else {16          // wrap the trimmed content with new element17          Element text = new Element();18          text.addText(trimmed);19          child.replaceWith(text);20          text.setName(element.getPrefix(), "text");21        }22      } else if (child instanceof Element) {23        // handle child elements with recursive call24        modifyElement((Element)child);25      }26    }27  }

XPP
XPP 的頂級代碼(在清單 10 中)是所有示例中最長(cháng)的一個(gè),與其它模型相比,它需要相當多的設置。

清單 10. XPP 頂級代碼
 1  // parse the document from input stream 2  m_parserFactory = XmlPullParserFactory.newInstance(); 3  m_parserFactory.setNamespaceAware(true); 4  XmlPullParser parser = m_parserFactory.newPullParser(); 5  parser.setInput(new BufferedReader(new InputStreamReader(in))); 6  parser.next(); 7  XmlNode doc = m_parserFactory.newNode(); 8  parser.readNode(doc); 9  // recursively walk and modify document10  modifyElement(doc);11  // write the document to output stream12  XmlRecorder recorder = m_parserFactory.newRecorder();13  Writer writer = new OutputStreamWriter(out);14  recorder.setOutput(writer);15  recorder.writeNode(doc);16  writer.close();

因為使用 JAXP 接口,所以我必須首先創(chuàng )建分析器工廠(chǎng)的實(shí)例并在創(chuàng )建分析器實(shí)例之前啟用名稱(chēng)空間處理(第 2-4 行)。一旦獲取了分析器實(shí)例,我就能將輸入設置到分析器中,并真正構建文檔表示(第 5-8 行),但是這涉及比其它模型更多的步驟。

輸出處理(第 11-16 行)也涉及比其它模型更多的步驟,主要因為 XPP 需要 Writer 而不是直接將 Stream 作為輸出目標接受。

清單 11 中 XPP modify 方法盡管需要更多代碼來(lái)創(chuàng )建新元素(第 13-21 行),但它與 JDOM 方法最類(lèi)似。名稱(chēng)空間處理在這里有點(diǎn)麻煩。我首先必須創(chuàng )建元素的限定名稱(chēng)(第 15-16 行),然后創(chuàng )建元素,最后在稍后設置名稱(chēng)和名稱(chēng)空間 URI(第 18-21 行)。

清單 11. XPP modify 方法
 1  protected void modifyElement(XmlNode element) throws Exception { 2    // loop through child nodes 3    for (int i = 0; i < element.getChildrenCount(); i++) { 4      // handle child by node type 5      Object child = element.getChildAt(i); 6      if (child instanceof String) { 7        // trim whitespace from content text 8        String trimmed = child.toString().trim(); 9        if (trimmed.length() == 0) {10          // delete child if only whitespace (adjusting index)11          element.removeChildAt(i--);12        } else {13          // construct qualified name for wrapper element15          String prefix = element.getPrefix();16          String name = (prefix == null) ? "text" : (prefix + ":text");17          // wrap the trimmed content with new element18          XmlNode text = m_parserFactory.newNode();19          text.appendChild(trimmed);20          element.replaceChildAt(i, text);21          text.modifyTag(element.getNamespaceUri(), "text", name);22        }23      } else if (child instanceof XmlNode) {24        // handle child elements with recursive call25        modifyElement((XmlNode)child);26      }27    }28  }

結束語(yǔ)
DOM、dom4j 和 Electric XML 都得到這些幾乎同樣易于使用的代碼樣本,其中 EXML 可能最簡(jiǎn)單,而 dom4j 受一些小條件限制而較困難。DOM 提供了與語(yǔ)言無(wú)關(guān)的非常實(shí)在的好處,但是如果你只使用 Java 代碼,那么通過(guò)與 Java 特定的模型相比較,它看上去有點(diǎn)麻煩。我認為這表明 Java 特定的模型通常成功地實(shí)現簡(jiǎn)化 Java 代碼中的 XML 文檔處理這個(gè)目標。

超越基礎:真實(shí)世界可用性
代碼樣本顯示 JDOM 和 EXML 為基本文檔操作(使用元素、屬性和文本)提供了簡(jiǎn)單和清晰的接口。根據我的經(jīng)驗,它們的方法并不能很好地完成處理整個(gè)文檔表示的編程任務(wù)。要完成這些類(lèi)型的任務(wù),DOM 和 dom4j 使用的組件方法 ― 其中從屬性到名稱(chēng)空間的所有文檔組件實(shí)現一些公共接口 ― 工作得更好。

相關(guān)的例子是最近我為 JDOM 和 dom4j 實(shí)現的 XML 流型(XML Streaming (XMLS) )編碼。這個(gè)代碼遍歷整個(gè)文檔并編碼每個(gè)組件。JDOM 實(shí)現比 dom4j 實(shí)現復雜得多,主要是因為 JDOM 使用一些沒(méi)有公共接口的獨特類(lèi)來(lái)表示每個(gè)組件。

因為 JDOM 缺少公共接口,所以即使處理 Document 對象的代碼與處理 Element 對象的代碼都有一些諸如子組件那樣相同類(lèi)型的組件,但是它們必須有所不同。還需要特殊方法來(lái)檢索與其它類(lèi)型的子組件相對的 Namespace 組件。甚至當處理被認為是內容的子組件類(lèi)型時(shí),您需要在組件類(lèi)型上使用多個(gè)帶 instanceof 檢查的 if 語(yǔ)句,而不是使用一條更清晰更快速的 switch 語(yǔ)句。

具有諷刺意味的可能是 JDOM 的最初目標之一是利用 Java Collection 類(lèi),這些類(lèi)本身在很大程度上以接口為基礎。庫中接口的使用增加了許多靈活性,而這是以增加了一些復雜性為代價(jià)的,并且這對于為重用而設計的代碼來(lái)說(shuō),通常是一個(gè)很好的折衷。這可能還主要歸功于 dom4j,它達到一個(gè)成熟并且穩定的狀態(tài),比 JDOM 要快得多。

盡管如此,對于使用多種語(yǔ)言的開(kāi)發(fā)人員來(lái)說(shuō),DOM 仍是一個(gè)非常好的選擇。DOM 實(shí)現廣泛應用于多種編程語(yǔ)言。它還是許多其它與 XML 相關(guān)的標準的基礎,所以即使您使用 Java 特定的模型,也還有一個(gè)您逐步熟悉 DOM 所需要的好機會(huì )。因為它正式獲得 W3C 推薦(與基于非標準的 Java 模型相對),所以在某些類(lèi)型的項目中可能也需要它。

就使用方便這一范疇而言,在 JDOM、dom4j 和 Electric XML 這三個(gè)主要競爭者中,dom4j 與其它兩個(gè)的區別在于它使用帶有多個(gè)繼承層的基于接口的方法。這會(huì )使得遵循 API JavaDocs 更為困難些。例如,您正在尋找的一個(gè)方法(例如 content() ,在我們 dom4j 的 modify 方法示例的第 3 行中使用的)可能是 Element 擴展的 Branch 接口的一部分,而不是 Element 接口本身的一部分。盡管如此,這種基于接口的設計添加了許多靈活性(請參閱側欄 超越基礎:真實(shí)世界可用性)??紤]到 dom4j 的性能、穩定性和特性設置的優(yōu)點(diǎn),您應把它當作多數項目中的一個(gè)有力的候選者。

在任一 Java 特定的文檔模型之中,JDOM 可能擁有最廣泛的用戶(hù)基礎,并且它的確是使用起來(lái)最簡(jiǎn)單的模型之一。盡管如此,作為項目開(kāi)發(fā)的一個(gè)選擇,它還是必須容忍 API 的不固定性和從一個(gè)版本到下一個(gè)版本的更新,在性能對比中它也表現得很糟糕?;诋斍皩?shí)現,我愿為著(zhù)手新項目的人們推薦 dom4j,而不是 JDOM。

除了 XPP 以外,EXML 比其它任何模型占用的資源都要少得多,并且考慮到 EXML 易于使用的優(yōu)點(diǎn),您應肯定會(huì )認為它適用于 jar 文件大小很重要的應用程序。但是,EXML 的 XML 支持的局限性和受限的許可證,以及在較大文件上所表現出的相對拙劣的性能,不得不在許多應用程序中放棄使用它。

XPP 在語(yǔ)法分析和編寫(xiě)文本文檔時(shí)需要更多步驟,并且在處理名稱(chēng)空間時(shí)也需要更多步驟。如果 XPP 打算添加一些便利的方法來(lái)處理其中一些常見(jiàn)情況,那么在對比中它可能會(huì )更勝一籌。正如它現在所表現的,上篇文章中性能方面的領(lǐng)先者卻成了本文中的可用性方面的失敗者。盡管如此,因為 XPP 性能方面的優(yōu)勢,所以對于需要較小的 jar 文件大小的應用程序還是值得將它作為 EXML 的替代方法。

下一次...
到目前為止在我寫(xiě)的兩篇文章中,涉及到用 Java 編寫(xiě)的 XML 文檔模型的性能和可用性。在本系列的后兩篇文章中,我將討論用 Java 技術(shù)進(jìn)行 XML 數據綁定的方法。這些方法與文檔模型的方法有許多相似處,但是它們更進(jìn)一步將 XML 文檔映射到實(shí)際應用程序數據結構中。我們將看到這一操作在使用的簡(jiǎn)便性和提高性能方面是如何做得如此好的。

回到 developerWorks,檢查 Java 代碼的 XML 數據綁定的實(shí)質(zhì)。同時(shí),您可以通過(guò)下面鏈接的論壇,給出您對本文的評論和問(wèn)題。

參考資料

關(guān)于作者
Dennis Sosnoski( dms@sosnoski.com)是西雅圖地區 Java 咨詢(xún)公司 Sosnoski Software Solutions, Inc.的共同創(chuàng )始人和首席顧問(wèn)。他已經(jīng)有 30 多年專(zhuān)業(yè)軟件開(kāi)發(fā)經(jīng)歷,最近幾年他一直關(guān)注服務(wù)器端的 Java 技術(shù),包括 servlet、Enterprise JavaBean 和 XML。他已經(jīng)發(fā)表了 Java 性能問(wèn)題和常規服務(wù)器端 Java 技術(shù)的許多文章,而且擔任 Seattle Java-XML SIG的總裁。


本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
用JDOM完成Java更新XML文件的方法
DOM4J解析xml文件
用 JDOM 簡(jiǎn)化 XML 編程
賽迪網(wǎng)_IT門(mén)戶(hù)_技術(shù)天地_tech_ccidnet教您快速上手使用JDOM處理XML文檔的技巧 -
dom4j使用基本指南
Java程序員從笨鳥(niǎo)到菜鳥(niǎo)之(二十七)XML之Jdom和DOM4J解析
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久