jinfeng_wang

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

BlogJava 首页 新随笔 联系 聚合 管理
  400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
http://dev2dev.bea.com.cn/techdoc/2007/08/java-XMLBeans.html


使用XMLBeans绑定XML-java数据


时间:2007-08-16
作者:Hetal C. Shah
浏览次数: 1202
本文关键字:XMLBeansxmlxml schemaxsdschema apache模式 xml-java绑定 java绑定 数据绑定
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章

  XMLBeans提供了底层XML数据的对象视图,同时还能访问原始的XML信息集合。通过递增的解除封送xml数据和高效的访问XML 模式内置数据类型的方法,XMLBeans交付了较好的性能。下面两种特性几乎百分之百的支持XML模式,并在操作数据期间定时验证XML数据 ,从而使XMLBeans非常适用于XML-Java 数据绑定。

  XMLBeans目前处于 Apache 项目的孵化过程中,并且证明对于Java开发人员进行XML-Java数据绑定是非常有用的。

  本文后面的资源部分提供了本文示例代码和其他文件的下载。所有示例代码均在Apache XMLBeans 1.02、Java 1.4.2_02和Microsoft Windows 2000的环境下进行了测试。

创建一个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 -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类

  下面将详细讨论XMLBeans类。 XMLBeans提供了46种java类型,反映了XML 模式规范中定义的46种内置类型。例如,W3C定义了一个xsd:string类型,XMLBeans就提供了一个XmlString数据类型与之对应。

  在weather_latlong.xsd 模式创建的Weather接口为xsd:float类型的局部元素Visibility声明了如下的两种方法:

float getVisibility();

  和

org.apache.xmlbeans.XmlFloat xgetVisibility();

  对于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());

  输出的结果是:

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

模式声明多个全局元素时如何解除封送

  在上面的例子中,我们假设输入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  + " : \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文档的内容,我们先检查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 : "
  + "\n\n\n " + 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数据转换引擎等实现,都用到了该数据绑定技术。

资源

 作者简介

Hetal C. Shah 是一名IT顾问,擅长与Internet相关的技术。
posted on 2008-03-10 17:32 jinfeng_wang 阅读(802) 评论(0)  编辑  收藏 所属分类: javaZZ

只有注册用户登录后才能发表评论。


网站导航: