程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用XMLBeans綁定XML-java數據

使用XMLBeans綁定XML-java數據

編輯:關於JAVA

創建一個XMLBean

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

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

例如,下面的weather_latlong.xsd模式列表描述了xml文檔的內容,該文檔包含了某個地理位置的天氣、經緯度信息,這些信息全部基於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-outweather.jarweather_latlong.xsd

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

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

XMLBeans類

下面將詳細討論XMLBeans類。 XMLBeans提供了46種java類型,反映了XML 模式規范中定義的46種內置類型。例如,W3C定義了一個xsd:string類型,XMLBeans就提供了一個XmlString數據類型與之對應。

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

floatgetVisibility();

org.apache.xmlbeans.XmlFloatxgetVisibility();

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

Xget形式的函數在性能上要優於get形式的函數,因為get形式的函數必須要把數據轉化成為最合適的java類型。

當模式被編譯後,模式類型的名稱將會變得符合java的命名規則。換句話說,stock-quote這樣的名稱將變為StockQuote。另外,模式名稱空間的URIs變成了模式生成的XMLBeans類型的包名。如果包含的模式沒有聲明目標名稱空間,那麼所有的java類都將放在noNamespace這個包中。當出現了類命名沖突時,生成的類名字後面將加上相應的數字——例如, timeStamp3。

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

對於在另一個元素或類型的聲明中局部聲明的命名類型,XMLBeans會在元素或類型接口中生成一個內部接口,形成嵌套結構。

考慮下面的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的接口中生成了一個內部接口Jobstatus,嵌套在了Employee接口中。

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

Employee類在這裡擴展了org.apache.xmlbeans.XmlObject,這是所有XMLBeans類型的基礎接口。所有的內置模式類型,用戶定義類型和派生的模式類型都從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();

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

要獲得Weather元素的內容,簡單調用weatherElement的相應的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());

輸出的結果是:

Weatherdetailsofzipcode92834-2345at2003-11-13T05:29:27-03:01
Temperatureis85.3
Humidityis50.0
Visibilityis5.5

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

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

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

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

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 + " :
");
  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() + " :
");
   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文檔的內容,我們先檢查XmlObject.Factory.parse()返回的對象的文檔類型,然後把返回的對象轉化為相應的文檔類型,以供稍後處理。另一段有趣的代碼是最後的else代碼塊,它將處理格式良好的XML文檔不符合weather_latlong.xsd模式的情況。

創建一個新的XML文檔

下面的一小段latlong_marshal.java代碼闡述了如何使用XMLBeans生成的類創建一個包含經緯度信息的新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()創建了一個LatlongDocument對象並且返回該對象。隨後對文檔對象調用addNewLatlong()方法創建並向文檔增加一個新的LatLong元素。

要向LatLong元素添加數據, 簡單調用latLongElement的相應的Set方法即可,它將直接映射模式中定義的的元素和屬性名稱。

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

最後的代碼段將LatLong元素的當前狀態寫到了標准的輸出流中。

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 : "
  + "
" + xmlStr );

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

輸出的結果是:

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

性能優勢

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

XMLBeans也提供高效的xget版本的函數訪問XML模式內置數據類型。

驗證

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

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

其他特性

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

結束語

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

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved