国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

用Java訪問XML數據的簡單起步

2019-11-18 15:20:45
字體:
來源:轉載
供稿:網友

  xml 是現在非常流行的數據表達格式,其特點是可移植、與平臺無關以及具有直接可讀的形式。Document Object Model (DOM) 是應用程序存取 XML 數據的接口。不幸的是,DOM 是一種相當復雜的 API,因而較難以迅速把握。但是,如能知道所存取數據的 DTD,這時就輕易得多了。本文將通過若干簡單步驟,對如何利用 java 版的 DOM 來存取 XML 數據進行介紹。

可擴展標記語言 (XML) 已經相當普及,它是一種可移植的、與平臺無關的且直接可讀的數據格式。許多軟件廠商均已宣稱“支持 XML”,這通常是指他們的軟件產品將生成或用到 XML 格式的數據。

XML 也同樣被看作是企業間交流數據的通用格式。它答應企業在 XML 文檔類型定義(即 DTD)的基礎上對所交流的數據取得一致。這些 DTD 文件獨立于企業中所使用的數據類型。

許多標準化組織正在致力于規范交流數據的 DTD。其中一個例子就是國際出版通信委員會(請參見資源)已經定義了一個 XML 的 DTD,這個 DTD 可以使“所傳輸的帶有標記的新聞信息能夠輕松地轉換為電子出版格式”。這些市場標準將使不同應用程序之間能夠在未事先確定方式的情況下進行數據的交換。

由 W3C 定義的 XML 規范(請參見資源)中規定了 XML 的語法和語義。一個 XML 文檔必須經過語法分析才能被處理。假如每個程序都必須先對 XML 進行語法分析再去處理,那將是非常困難的,因為給出這種語言的語法和語義是很復雜的。W3C 已經定義了文檔對象模型(DOM)(請參見資源)來解決這一問題。DOM 是一個針對XML數據的應用編程接口。大部分 XML 語法分析器都為所分析的 XML 生成一個 DOM 描述。

DOM 標準
DOM API 被定義為一系列 CORBA IDL 接口(請參見資源)。它用一個抽象樹來描述一個經過語法分析的 XML 文檔。之所以說它是抽象的,這是因為只有這些接口反映出樹形的結構。而用來實現抽象樹的實際數據結構和算法不必是樹形結構。

由于 DOM API 是以 CORBA IDL 形式規定的,所以它被許多編程語言所支持,包括 Java 語言。我們假定本文中使用標準的 Java 語言。DOM 規范給出了具體的基于Java 接口。

DOM 第一層規范是在 1998 年被采用的。它留下一些保留部分,以根據后來的實踐經驗來進一步擴充。DOM 第二層規范在第一層的基礎上增加了對 XML 命名空間、文檔創建、視圖和式樣單等內容的支持。第二層規范尚有待公眾評價。雖然從技術上而言還沒有最終完成,但是也已經相當穩定。

對于一個 XML 文檔,許多 XML 語法分析器均可供 Java 程序使用,以生成 DOM 的第一層描述。因此,這里的代碼只假定為基于DOM 的第一層子集。

通用或特定 DTD 代碼
在Java中使用DOM API編寫的代碼要么是通用的,要么是基于特定的DTD。通用代碼在所有 XML 文檔中都能正常工作。通用代碼一般更難編寫,因為它通常必須遍歷整個 DOM 樹,考慮各種可能。代碼不能依靠任何特定的元素、屬性和文檔結構。通用代碼用于處理一般性事務,例如檢查文檔中的拼寫錯誤、計算文字數目、通過網絡發送文件,等等。

另一方面,特定 DTD 代碼是在根據特定的 DTD 寫出的。它不能用來操作由另一種 DTD 定義的 XML 文檔。特定的 DTD 比較輕易編寫,因為它假設 XML 文檔具有該特定 DTD 所指定的格式。例如,假設一個 DTD 聲明一個名為“NAME”的元素要求具有一個名為“GIVEN”的屬性,Java 代碼可以假設這個屬性存在并通過簡單地 DOM getAttribute() 調用來訪問它

這篇文章將幫助你編寫特定 DTD Java 代碼。在此之后的任務則是學習如何編寫通用 DTD 代碼。

一個示例
為了解釋怎樣在 Java 程序中使用 DOM API,我們將用一個定購程序作為例子,因為它是一個典型的基于 XML 的 B2B 應用,并且具有很豐富的 XML 結構。

下面是我們所用定購單的 DTD。

<?xml encoding="US-ASCII"?>
<!ELEMENT order (header,item+,PRice)>
<!ELEMENT header (billing,shipping)>
<!ELEMENT billing (name,address,creditCard)>
<!ELEMENT shipping (name,address)>
<!ELEMENT name EMPTY>
<!ATTLIST name
  given   CDATA #REQUIRED
  family  CDATA #REQUIRED
  >
<!ELEMENT address (street,city,state,zipcode,country,phone)>
<!ELEMENT item (prodId,prodName,quantity,price)>
<!ELEMENT creditCard (#PCDATA)>
<!ELEMENT street (#PCDATA)>
<!ELEMENT city (#PCDATA)>
<!ELEMENT state (#PCDATA)>
<!ELEMENT zipcode (#PCDATA)>
<!ELEMENT country (#PCDATA)>
<!ELEMENT phone (#PCDATA)>
<!ELEMENT prodId (#PCDATA)>
<!ELEMENT prodName (#PCDATA)>
<!ELEMENT quantity (#PCDATA)>
<!ELEMENT price (#PCDATA)>

 

下面是 包含100 個裝飾品的定購單的 XML 文檔:

<?xml version="1.0"?>
<!DOCTYPE order SYSTEM "order.dtd">
<order>
    <header>
        <billing>
            <name given="Jane" family="Doe"/>
            <address>
                <street>555 Main Street</street>
                <city>Mill Valley</city>
                <state>California</state>
                <zipcode>94520</zipcode>
                <country>USA</country>
                <phone>707 555-1000</phone>
            </address>
            <creditCard>4555 5555 5555 5555</creditCard>
        </billing>
        <shipping>
            <name given="John" family="Doe"/>
            <address>
                <street>100 Main Street</street>
                <city>Brisbane</city>
                <state>California</state>
                <zipcode>94005</zipcode>
                <country>USA</country>
                <phone>415 555-9999</phone>
            </address>
        </shipping>
    </header>
    <item>
        <prodId>5555555</prodId>
        <prodName>Widget</prodName>
        <quantity>100</quantity>
        <price>.25</price>
    </item>
    <price>25.00</price>
</order>

 

XML 語法分析器將上面的 XML 文檔抽象地描述成一個樹。這個樹形結構可以用圖形描述如下:

用Java訪問XML數據的簡單起步(圖一)

橢圓代表 XML 元素。方形代表數據,從name元素出發的直線代表 XML 屬性。圖中沒有具體標出 address 元素。

在 Java 程序中存取 XML 數據的一些簡單步驟
現在,我們用特定的 DTD JAVA 代碼來說明 DOM API 的一個重要部分。非凡的,我們給出以下DOM方法的用法。

getDocType 
getName 
getElementsByTagName 
item 
getFirstChild 
getNodeValue 
getAttribute 
getChildNodes 
getLength 
getTagName 
在本文的范例代碼中,所有帶下劃線的方法調用都是 DOM API 的一部分。另有完整的源代碼可供下載。

定義存取 DOM 文檔的一個簡單接口
第一步是先定義一個抽象接口,該接口能夠大大簡化使用 XML 文檔的代碼。對于我們所使用的范例 DTD,定義以下接口:

interface order {
    String creditCard();
    String billingName();
    double totalPrice(); 
    boolean authorizeCredit();
}

 

存取 XML 數據的代碼簡單地調用由接口定義的操作集。

應當注重的是,這個接口的實現可有多種不同方式,其中的一些與 XML 無關(例如,某個實現可向數據庫發出請求)。當然,這里我們只關心用DOM API 來實現處理 XML 數據的操作,這些數據同前面基于DTD的訂單一致。

實現接口
現在編寫一個實現該接口并封裝 DOM 文檔的類。例如,我們定義:

class orderImpl implements order {
    Document theDocument;

 

在構建器中將 DOM 文檔捆綁至封裝類
將 DOM 文檔傳遞給封裝類的構建器。構建器檢查文檔類型,以確定該文檔確實符合訂單 DTD。記住這些代碼只是針對這個 DTD 的,并對數據的結構和內容做出假設。

public orderImpl(Document document) throws Exception {
  theDocument = document;
  DocumentType docType = theDocument.getDoctype();
  if (docType==null) throw new Exception("Cannot determine document type.");
  if (!docType.getName().equals("order")) throw new ?
     Exception("Document is not an order.");
}

 

注重,代碼利用 getDoctype 操作來得到文檔類型,該操作是在 Document 接口中由DOM定義的。getDoctype 操作返回一個支持 DocumentType 接口的對象。它的名字代表了文檔的類型。

另請注重,一些 DOM 實現對 getDoctype 操作返回 null,這樣就不能用于這個構建器。

給出用于將該文檔捆綁至包裝類的代碼后,實現這個接口。在接口范例中給出的每項操作,說明了如何使用 DOM 完成特定任務。

返回特定元素的值
creditCard 方法說明了如何返回一個特定元素的值。它使用了在 Document 接口中定義的 getElementsByTagName 操作。

public String creditCard() {
    NodeList nl = theDocument.getElementsByTagName("creditCard");
    return nl.item(0).getFirstChild().getNodeValue();
}

 

通常,getElementsByTagName 返回一個元素列表。因為在我們的樣例 DTD 中只有一個名為“creditCard”的元素,所以這個列表中只包含一個元素,即 item(0)。這樣,nl.item(0) 可用下圖表示:

用Java訪問XML數據的簡單起步(圖二)

creditCard 元素的字符串值可通過在信用卡節點上調用 getFirstChild().getNodeValue() 方法得到。

注重,getElementsByTagName(elementName) 操作返回文檔中利用 elementName 來命名的所有元素。根據定義,它將前序遍歷文檔樹來返回元素。

由于元素名稱 creditCard 在我們的樣例中是唯一的,所以可以直接找到該元素。然而,其他的元素(例如 name)不是唯一的。我們不能直接使用 getElementsByTagName 返回的第一個元素。實際上,billing 的一個子元素的名稱為 name,另外 shipping 的一個子元素也叫做 name。

從唯一的子樹中返回一個元素的屬性值
在諸如 name 這樣的名稱不唯一的情況下,billingName 方法是獲得元素值的一種方法。注重 name 在這個文檔中不唯一,但是在 billing 子樹中卻是唯一的。另外還要注重,billing 元素在整個文檔中是唯一的。這樣,我們可以在文檔中簡單地調用 getElementsByTagName("billing"),然后在返回的 billing 元素中調用 getElementsByTagName。由于 getElementsByTagName 也是在 DOM API 中的 Element 接口中定義的,所以可以這樣做。

public String billingName() {
    NodeList bl = theDocument.getElementsByTagName("billing");
    NodeList nl = ((Element)bl.item(0)).getElementsByTagName("name");
    Element name = (Element)nl.item(0);
    return name.getAttribute("given")+" "+name.getAttribute("family");
}

 

利用 billingName 方法,還可以說明另一個技術,即獲得一個元素的屬性值。請注重,在我們的 DTD 中,name 元素被定義了兩個屬性:given 和 family。getAttribute 操作由 Element 接口定義,它返回屬性的文本值。

從多子樹中返回元素的值
現在考慮 price 元素。我們不能再使用剛才的方法,因為 price 是文檔的一個子元素,同時也是每個 item 元素的子元素。totalPrice 方法說明了另外一種查找非唯一元素值的方法。依據文檔結構可知,我們需要的是頂層的 price 元素。

public double totalPrice() {
    NodeList nl=theDocument.getDocumentElement().getChildNodes();
    Element candidateElement=null;
    for (int i=0; i<nl.getLength(); i++) {
      if (nl.item(i) instanceof Element) {
          candidateElement = (Element)nl.item(i);
          if (candidateElement.getTagName().equals("price")) break;
          }
      }
      return Double.parseDouble(candidateElement.getFirstChild().getNodeValue());
}

 

getDocumentElement 操作返回一個描述文檔的元素。從這里通過 getChildNodes 得到它的子節點。通過分析 DTD,可以看出子元素只有一個 header 元素,至少一個 item 元素和一個 price 元素。所以我們只要循環查找子節點,直到我們找到一個名為 price 的子元素。

同樣,我們一旦得到這個元素,則調用 getFirstChild().getNodeValue()來獲得它的值。

抽象
creditCard、billingName 及 totalPrice 在我們的接口中是基本的操作。它們簡單地查找并返回相應的 XML 元素。另一方面,我們的接口也包含抽象的 authorizeCredit 方法。在 XML 文檔中沒有與它相應的元素。

下面給出 authorizeCredit 實現。它簡單地使用我們已經在包裝類中實現的 billingName、creditCard 及 totalPrice 方法。

    public boolean authorizeCredit() {
        // illustrates abstraction
        return authorize(
                    this.billingName(),
                    this.creditCard(),
                    this.totalPrice());
    }

 

類的客戶端使用
我們定義了一個抽象接口來訪問我們的 XML 文檔并通過使用 10 個重要的 DOM 操作來在包裝類中實現了它們。接下來,我們介紹一下怎樣通過Java代碼來利用這些已經定義好的接口

下面的代碼簡單地調用語法分析器并將其返回的 DOM 文檔傳遞給我們的包裝類的構造器,然后調用我們實現的每一個方法。這些代碼的編寫使用了 IBM XML Parser for Java (參見資源)。其他語法分析器的使用大致相同。

import com.ibm.xml.XPk4j.xml4j2.*;
import java.io.*;

public class test {
    public static void main(String[] args) {
        XML4J2DOMSource parser = new XML4J2DOMSource();
        try  {
            parser.parse("order.xml");
            order theOrder = new orderImpl(parser.getDocument());
            System.out.println("The credit card is "+theOrder.creditCard());
            System.out.println("The total price is "+theOrder.totalPrice());
            System.out.println("The billing name is "+theOrder.billingName());
            theOrder.authorizeCredit()
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

 

我們通過這個非常簡單的例子向大家展示了 DOM API 的 10 個重要的操作。通過這些操作,我們說明了如何在已知 DTD 時進行查找、瀏覽、遍歷元素以及獲得元素及其屬性值。這將為學習其它 DOM API 打下堅實的基礎。

資源

XML 語法分析器及 DOM 實現
假如您想用 DOM API 編寫 Java 代碼,就需要一個 DOM 的實現,也就是一個語法分析器。幸運的是,現在已經可以找到一些了。這里有一些相關的資源: 

Apache Xerces XML Parser 
IBM's XML Parser for Java 
Oracle (要訪問 Oracle Technology Network,您必須成為其會員。注冊是免費的。) 
Sun's Java Project X 
Xbeans
Xbeans 是一個開放源代碼的 Java Beans 知識庫,使用最一般的方法來處理 DOM 文檔。通過構造 Xbeans,可以創建分布式應用程序來處理 XML。這里是通用DOM 代碼的極佳來源。 
jGuru XML FAQ 
國際出版通訊委員會 (International Press Telecommunications Council)是一個對數據交流中的 DTD 進行統一的標準化組織。 
XML 規范 
DOM 規范 
CORBA IDL 
關于作者
BrUCe Martin 是分布式對象計算領域的一位帶頭人。90 年代初期,他在惠普實驗室設計并實現了一種接口定義語言,它后來成為惠普最初的 CORBA 子項目的基礎。在 Sun 微系統公司,他是 Sun 的 CORBA 體系結構設計者之一,同時還是五項 OMG 的 CORBA 服務規范的制定者。在 Inprise 公司,Bruce 是該公司第一個以 CORBA 為基礎的 Java 應用服務器的設計者和開發者。Bruce 具有關于 Java、XML 和 DOM 的淵博的實踐經驗。

現在,Bruce 已經成為 jGuru 的軟件領袖。他正在致力于維護 xbeans.org(一個開放源代碼計劃),以創建一個用來處理 XML 并且能夠很輕易地融入分布式應用的 Java Beans 的知識庫。

Bruce 在加利福尼亞大學圣地亞哥分校獲得了計算機科學碩士和博士學位,此前他在位于加利福尼亞大學伯克利分校獲得了計算機科學學士學位。

http://www-900.ibm.com/developerWorks/cn/xml/jguru-dom/index.sHtml

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广东省| 福州市| 余庆县| 巴里| 朔州市| 德清县| 保靖县| 万载县| 新闻| 梁平县| 九寨沟县| 城口县| 洛浦县| 永康市| 会理县| 渭南市| 丰原市| 香港 | 临邑县| 泸定县| 图们市| 广南县| 达日县| 罗定市| 屯昌县| 海晏县| 岳池县| 若羌县| 城步| 泾川县| 湾仔区| 白银市| 阿克陶县| 庆阳市| 邵阳市| 克什克腾旗| 锡林郭勒盟| 正镶白旗| 丹江口市| 五家渠市| 吉木乃县|