jinfeng_wang

          G-G-S,D-D-U!

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
          http://dev2dev.bea.com.cn/techdoc/2007/08/java-XMLBeans.html


          使用XMLBeans綁定XML-java數(shù)據(jù)


          時間:2007-08-16
          作者:Hetal C. Shah
          瀏覽次數(shù): 1202
          本文關(guān)鍵字:XMLBeansxmlxml schemaxsdschema apache模式 xml-java綁定 java綁定 數(shù)據(jù)綁定
          文章工具
          推薦給朋友 推薦給朋友
          打印文章 打印文章

            XMLBeans提供了底層XML數(shù)據(jù)的對象視圖,同時還能訪問原始的XML信息集合。通過遞增的解除封送xml數(shù)據(jù)和高效的訪問XML 模式內(nèi)置數(shù)據(jù)類型的方法,XMLBeans交付了較好的性能。下面兩種特性幾乎百分之百的支持XML模式,并在操作數(shù)據(jù)期間定時驗證XML數(shù)據(jù) ,從而使XMLBeans非常適用于XML-Java 數(shù)據(jù)綁定。

            XMLBeans目前處于 Apache 項目的孵化過程中,并且證明對于Java開發(fā)人員進(jìn)行XML-Java數(shù)據(jù)綁定是非常有用的。

            本文后面的資源部分提供了本文示例代碼和其他文件的下載。所有示例代碼均在Apache XMLBeans 1.02、Java 1.4.2_02和Microsoft Windows 2000的環(huán)境下進(jìn)行了測試。

          創(chuàng)建一個XMLBean

            在開始創(chuàng)建XMLBeans之前,需要下載并在系統(tǒng)中安裝Apache XMLBeans 1.02。當(dāng)從XMLBeans 的歸檔文件中提取出文件之后,將會在解壓文件中看到bin目錄和lib目錄。隨后,把bin目錄放到路徑中,把lib目錄中的xbean.jar包放到classpath路徑中。

            XML 模式文件(XSD文件)創(chuàng)建了XMLBeans類。這些XMLBeans類能夠解析所有符合XML模式的XML 實例文檔。同樣,通過使用這些XMLBeans類,也能夠創(chuàng)建出實例文檔。

            例如,下面的weather_latlong.xsd模式列表描述了xml文檔的內(nèi)容,該文檔包含了某個地理位置的天氣、經(jīng)緯度信息,這些信息全部基于zip代碼。

          <xsd:schema
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <!-- This XML Schema describes xml documents
          containing either weather details or latlong
          details of a location based on Zipcode Two Global
          elements Weather and Latlong, and one Global
          Attribute Zipcode are declared.-->
          <xsd:element name="Weather">
            <xsd:complexType>
             <xsd:sequence>
              <xsd:element name="Temperature"
                   type="xsd:float"/>
              <xsd:element name="Humidity"
                   type="xsd:float"/>
              <xsd:element name="Visibility"
                   type="xsd:float"/>
              <xsd:element name="Datetime"
                   type="xsd:dateTime"/>
             </xsd:sequence>
            <xsd:attribute ref="Zipcode"/>
          </xsd:complexType>
          </xsd:element>
          <xsd:element name="Latlong">
            <xsd:complexType>
             <xsd:sequence>
              <xsd:element name="Latitude"
                   type="xsd:string"/>
              <xsd:element name="Longitude"
                   type="xsd:string"/>
              </xsd:sequence>
             <xsd:attribute ref="Zipcode"/>
            </xsd:complexType>
          </xsd:element>
          <xsd:attribute name="Zipcode"
                   type="xsd:string"/>
          </xsd:schema>

            接下來的步驟將生成一組XMLBeans類,它們表示上面的XSD類型模式。在工作目錄(從示例歸檔文件提取文件的位置)的提示符中,輸入以下命令行:

          scomp -out weather.jar weather_latlong.xsd

            在編譯完以上的模式后,XMLBeans生成如下五個接口。WeatherDocument、WeatherDocument$Weather、LatlongDocument、LatlongDocument$Latlong和ZipcodeAttribute。

            在此,WeatherDocument接口表示文檔元素,WeatherDocument$Weather接口表示全局元素Weather。類似地,LatlongDocument和LatlongDocument$Latlong接口表示全局元素Latlong。ZipcodeAttribute接口代表了全局屬性Zipcode。

          XMLBeans類

            下面將詳細(xì)討論XMLBeans類。 XMLBeans提供了46種java類型,反映了XML 模式規(guī)范中定義的46種內(nèi)置類型。例如,W3C定義了一個xsd:string類型,XMLBeans就提供了一個XmlString數(shù)據(jù)類型與之對應(yīng)。

            在weather_latlong.xsd 模式創(chuàng)建的Weather接口為xsd:float類型的局部元素Visibility聲明了如下的兩種方法:

          float getVisibility();

            和

          org.apache.xmlbeans.XmlFloat xgetVisibility();

            對于46種java類型中的任何一種,XMLBeans 都提供了兩種訪問數(shù)據(jù)的方法。在此,一種方法為xsd:float返回了XmlFloat類型,而另一種方法為xsd:float返回了一個普通的java類型如float類型。

            Xget形式的函數(shù)在性能上要優(yōu)于get形式的函數(shù),因為get形式的函數(shù)必須要把數(shù)據(jù)轉(zhuǎn)化成為最合適的java類型。

            當(dāng)模式被編譯后,模式類型的名稱將會變得符合java的命名規(guī)則。換句話說,stock-quote這樣的名稱將變?yōu)镾tockQuote。另外,模式名稱空間的URIs變成了模式生成的XMLBeans類型的包名。如果包含的模式?jīng)]有聲明目標(biāo)名稱空間,那么所有的java類都將放在noNamespace這個包中。當(dāng)出現(xiàn)了類命名沖突時,生成的類名字后面將加上相應(yīng)的數(shù)字——例如, timeStamp3。

            對于全局元素和屬性,XMLBeans 模式編譯器將分別生成名稱以Document和Attribute結(jié)尾的接口。

            對于在另一個元素或類型的聲明中局部聲明的命名類型,XMLBeans會在元素或類型接口中生成一個內(nèi)部接口,形成嵌套結(jié)構(gòu)。

            考慮下面的employee.xsd 模式列表。

          <?xml version="1.0" encoding="UTF-8"?>
          <!-- This XML Schema describes Employee's
              Jobstatus -->
          <xsd:schema
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <xsd:complexType name="Employee">
            <xsd:sequence>
             <xsd:element name="Jobstatus">
              <xsd:simpleType>
               <xsd:restriction base="xsd:NMTOKEN">
                <xsd:enumeration value="fullTime"/>
                <xsd:enumeration value="hourly"/>
               </xsd:restriction>
              </xsd:simpleType>
             </xsd:element>
            </xsd:sequence>
          </xsd:complexType>
          </xsd:schema>

            因此,XMLBeans在元素Employee的接口中生成了一個內(nèi)部接口Jobstatus,嵌套在了Employee接口中。

          public interface Employee
            extends org.apache.xmlbeans.XmlObject
          {
          ...
          public interface Jobstatus
             extends org.apache.xmlbeans.XmlNMTOKEN
            {
            }
          }

            Employee類在這里擴展了org.apache.xmlbeans.XmlObject,這是所有XMLBeans類型的基礎(chǔ)接口。所有的內(nèi)置模式類型,用戶定義類型和派生的模式類型都從XmlObject中繼承而來。

          使用XMLBeans類解除封送XML文件

            下面的一小段weather_unmarshal.java代碼闡明了怎樣使用XMLBeans類從weatherInput.xml.文件的XML文檔中獲取天氣信息。

          String filePath = "weatherInput.xml";
          java.io.File inputXMLFile =
          new java.io.File(filePath);
          // Parse XML Document.
          WeatherDocument weatherDoc =
          WeatherDocument.Factory.parse(inputXMLFile);
          // Get object reference of root element Weather.
          WeatherDocument.Weather weatherElement =
          weatherDoc.getWeather();

            通過調(diào)用WeatherDocument.Factory.parse(File)方法來解析XML文件,該方法返回一個WeatherDocument對象。隨后對weatherDocument對象調(diào)用getWeather()方法來獲取根元素Weather的對象引用。

            要獲得Weather元素的內(nèi)容,簡單調(diào)用weatherElement的相應(yīng)的get方法,它將直接映射模式定義的元素和屬性名稱:

          // Call the appropriate 'get' methods of
          // weatherElement that
          // directly map to the element and attribute names
          // defined in the schema.
          Calendar timeStamp = weatherElement.getDatetime();
          System.out.println("Weather details of zipcode "
          + weatherElement.getZipcode() + " at "
          + timeStamp);
          System.out.println("Temperature is "
          + weatherElement.getTemperature());
          System.out.println("Humidity is "
          + weatherElement.getHumidity());
          System.out.println("Visibility is "
          + weatherElement.getVisibility());

            輸出的結(jié)果是:

          Weather details of zipcode 92834-2345 at 2003-11-13T05:29:27-03:01
          Temperature is 85.3
          Humidity is 50.0
          Visibility is 5.5

          模式聲明多個全局元素時如何解除封送

            在上面的例子中,我們假設(shè)輸入XML文檔始終包含天氣信息。然而,在實際中,由于weather_latlong.xsd文件通過聲明兩個全局元素(Weather和Latlong)同時描述了二者的詳細(xì)信息,因此輸入XML文檔中可能包含天氣信息也可能包含經(jīng)緯度信息。。

            有兩種方法可以解析一個xml文檔并將其綁定到相應(yīng)XMLBeans類型的實例。在上述的例子中,我們用WeatherDocument.Factory.parse()方法解析XML文檔。另外一種方式是使用XMLBeans內(nèi)置的XmlObject類。

            下面的一小段weather_unmarshal_xmlObject.java代碼闡述了怎樣使用XmlObject類獲取xml實例文檔中包含的天氣和經(jīng)緯度信息。

          public static void main(String args[]) {
          try {
          if (args.length < 1 ) {
          System.out.println("Usage : java "
          +"weather_unmarshal_xmlObject <<InputFilePath>>");
          return;
          }
          String filePath = args[0];
          java.io.File inputXMLFile
             = new java.io.File(filePath);
          XmlObject xmlObjExpected =
          XmlObject.Factory.parse(inputXMLFile);
          // Check document type of the object returned by
          // the call to XmlObject.Factory.parse() method.
          // If type of object returned is of
          //noNamespace.WeatherDocument, then input xml
          //document carries weather details of a location.
          if (xmlObjExpected instanceof
          noNamespace.WeatherDocument) {
            WeatherDocument weatherDoc =
              (noNamespace.WeatherDocument)xmlObjExpected;
            WeatherDocument.Weather weatherElement =
                  weatherDoc.getWeather();
            Calendar timeStamp =
              weatherElement.getDatetime();
            System.out.println
              ("Weather details of zipcode "
              + weatherElement.getZipcode() + " at "
              + timeStamp  + " : \n\n");
            System.out.println("Temperature is "
                  + weatherElement.getTemperature());
            System.out.println("Humidity is "
                  + weatherElement.getHumidity());
            System.out.println("Visibility is "
                  + weatherElement.getVisibility());
          // else if type of object returned is of
          // noNamespace.LatlongDocument, then input xml
          //document carries latlong details of a location.
          } else if(xmlObjExpected instanceof
              noNamespace.LatlongDocument) {
                  LatlongDocument latLongDoc =
                  (noNamespace.LatlongDocument)xmlObjExpected;
                  LatlongDocument.Latlong latLongElement =
                  latLongDoc.getLatlong();
              System.out.println
             ("Latlong details of zipcode "
                + latLongElement.getZipcode() + " : \n\n");
              System.out.println("Latitude is "
                + latLongElement.getLatitude());
              System.out.println("Longitude is "
                + latLongElement.getLongitude());
          // else input xml document is well formed , but
          // doesn't conform to weather_latlong.xsd schema
          // file.
          } else {
                  System.out.println("Input xml document "
                    + "doesn't conform to weather_latlong.xsd");
          }
          } catch (Exception e) {
              e.printStackTrace();
            }
          }
          }

            為了獲得輸入XML文檔的內(nèi)容,我們先檢查XmlObject.Factory.parse()返回的對象的文檔類型,然后把返回的對象轉(zhuǎn)化為相應(yīng)的文檔類型,以供稍后處理。另一段有趣的代碼是最后的else代碼塊,它將處理格式良好的XML文檔不符合weather_latlong.xsd模式的情況。

          創(chuàng)建一個新的XML文檔

            下面的一小段latlong_marshal.java代碼闡述了如何使用XMLBeans生成的類創(chuàng)建一個包含經(jīng)緯度信息的新xml實例文檔。

          LatlongDocument latLongDoc;
          LatlongDocument.Latlong latLongElement;
          XmlOptions xmlOptions;
          // LatlongDocument.Factory.newInstance() creates
          // and returns a LatlongDocument object.
          latLongDoc= LatlongDocument.Factory.newInstance();
          // addNewLatlong() method is called on the
          // document object to create and add a new
          // LatLong Element to document.
          latLongElement = latLongDoc.addNewLatlong();

            LatlongDocument.Factory.newInstance()創(chuàng)建了一個LatlongDocument對象并且返回該對象。隨后對文檔對象調(diào)用addNewLatlong()方法創(chuàng)建并向文檔增加一個新的LatLong元素。

            要向LatLong元素添加數(shù)據(jù), 簡單調(diào)用latLongElement的相應(yīng)的Set方法即可,它將直接映射模式中定義的的元素和屬性名稱。

          latLongElement.setZipcode("91023");
          latLongElement.setLatitude("33.8792");
          latLongElement.setLongitude("117.8974");

            最后的代碼段將LatLong元素的當(dāng)前狀態(tài)寫到了標(biāo)準(zhǔn)的輸出流中。

          xmlOptions = new XmlOptions();
           
          // Requests use of whitespace for easier reading
          xmlOptions.setSavePrettyPrint();
           
          // Requests that nested levels of the xml
          // document to be indented by multiple of 4
          // whitespace characters
          xmlOptions.setSavePrettyPrintIndent(4);
           
          String xmlStr = latLongDoc.xmlText(xmlOptions);
           
          // Writes the current state of the LatLong
          // element to a standard output stream
           
          System.out.println("XML Instance Document is : "
            + "\n\n\n " + xmlStr );

            xmlText方法用可選的xmlOptions對象控制它的行為。setSavePrettyPrint()方法要求使用空白符,以便方便閱讀,而setSavePrettyPrintIndent(4)方法要求在嵌套的XML文檔中首行縮進(jìn)四的倍數(shù)個空白符。

            輸出的結(jié)果是:

          XML Instance Document is :
           
          <Latlong Zipcode="91023">
              <Latitude>33.8792</Latitude>
              <Longitude>117.8974</Longitude>
          </Latlong>

          性能優(yōu)勢

            與DOM的不同之處是,XMLBeans沒有采用解除封送整個xml文檔和為每個xml文檔結(jié)點提供一個對象的方法。使用XMLBeans,只在需要時進(jìn)行封送和解除封送,因此對于你從來沒有查看過的代碼,它們是不會被封送和解除封送的。這提高了XMLBeans解決方案的性能。

            XMLBeans也提供高效的xget版本的函數(shù)訪問XML模式內(nèi)置數(shù)據(jù)類型。

          驗證

            分配給內(nèi)置XMLBeans java類型的值將按照其表示的模式類型的規(guī)則進(jìn)行驗證。例如,如果將一個符合條件的名稱分配給一個XmlQName數(shù)據(jù)類型時,如果該名稱的前綴不能解析為任何URI,將會拋出XmlValueOutOfRange異常。

            當(dāng)xml文檔第一次被解析時,將根據(jù)模式定義驗證其中包含的數(shù)據(jù)。更有意思的是,無論何時通過XMLBeans生成的java類處理xml文檔時,XMLBeans系統(tǒng)將確保遵守模式約束條件。

          其他特性

            XMLBeans對象是可序列化的,因而,可以通過RMI邊界傳送,也能夠很容易的從XML 字符流和字節(jié)流中提取,并保存回去。XMLBeans也具有配置功能,因而可以將XML名稱映射到Java名稱。這樣將避免在XML的名稱發(fā)生變化時重新編寫Java代碼。由于篇幅限制我們在此不做過多討論。

          結(jié)束語

            XMLBeans 提出了底層XML數(shù)據(jù)的對象視圖,同時還能訪問原始的XML信息集合。通過遞增的解除封送xml數(shù)據(jù)和高效的訪問XML模式內(nèi)置數(shù)據(jù)類型的方法,XMLBeans交付了較好的性能。下面兩種特性幾乎百分之百的支持XML 模式,并在操作數(shù)據(jù)期間定時驗證XML數(shù)據(jù),從而使XMLBeans非常適用于XML-Java 數(shù)據(jù)綁定。現(xiàn)在web services、BPEL、BPML、基于規(guī)則的XML數(shù)據(jù)轉(zhuǎn)換引擎等實現(xiàn),都用到了該數(shù)據(jù)綁定技術(shù)。

          資源

           作者簡介

          Hetal C. Shah 是一名IT顧問,擅長與Internet相關(guān)的技術(shù)。
          posted on 2008-03-10 17:32 jinfeng_wang 閱讀(903) 評論(0)  編輯  收藏 所屬分類: javaZZ
          主站蜘蛛池模板: 隆尧县| 松江区| 阳春市| 彭山县| 三河市| 拜泉县| 尤溪县| 安溪县| 舟山市| 珲春市| 南城县| 阳信县| 常熟市| 论坛| 昌吉市| 安龙县| 无棣县| 宝清县| 阿坝| 巴塘县| 兰溪市| 甘泉县| 九江市| 临洮县| 天长市| 靖远县| 长乐市| 仁寿县| 河北省| 仪陇县| 河西区| 闵行区| 岑溪市| 荃湾区| 东辽县| 安徽省| 台州市| 鹤峰县| 洪江市| 登封市| 荣成市|