应用E序中?XML 文档的多数方法都把重Ҏ(gu)?XML 上:(x)?XML 的观点用文档,按照 XML 元素、属性和字符数据内容~程。如果应用程序主要关?j)文档?XML l构Q那么这U方法非常好。对于更兛_(j)文档中所含数据而非文档本n的许多应用程序而言Q?数据l定提供?jin)一U更单的使用 XML 的方法?
本系列文章的上一(请参?参考资?/font>Q所讨论的文档模型,是与数据l定最接近的替代方案。文档模型和数据l定都在内存?sh)徏立文档的表示Q都需要在内部表示和标准文?XML 之间双向转换。两者的区别在于文档模型可能保?XML l构Q而数据绑定只兛_(j)应用E序所使用的文档数据?
Z(jin)说明q一点,?1 l出?jin)一个简?XML 文档的数据模型视图。文档成分——在q个例子中只有元素和文本节点——通过反映原始 XML 文档的结构连接在一赗Ş成的节点?wi)很?gu)和原始文档联p,但要解释?wi)中表示的实际数据就不那么容易?jin)?/p>
?1. 文档的文档模型视?/b>
如果应用E序使用 XML 文档模型Ҏ(gu)Q?zhn)需要处理这U类型的?wi)。这U情况下Q?zhn)用节点之间的父子关系在?wi)的上下层之间DQ用属于同一父节点的子女之间的兄弟关pd?wi)的同一层中D。?zhn)可以非常详尽地处理?wi)l构Q当把树(wi)序列化ؓ(f)文本Ӟ生成?XML 文档反映?zhn)所做的修改Q比如插入的注释Q?/p>
现在来看看与?1 截然不同的图 2Q它表示同一文档的数据绑定视图。在q里Q{换过E几乎隐藏了(jin)原始 XML 文档的所有结构,但是因ؓ(f)只有通过两个对象Q更Ҏ(gu)看清楚真正的数据Q也更很Ҏ(gu)讉Kq些数据?/p>
?2. 文档的数据绑定视?/b>
使用q种数据l构像是一般的 Java ~程——甚x(chng)本不需要知?XMLQ(哦,q是不要走得 ?/i>q了(jin)——我们这些专安问还得活……)(j)(zhn)的目中至要有h明白Q这U数据结构和 XML 文档之间的映是如何建立的,但这仍然是向化迈出的一大步?
?仅仅是编E的化,数据l定q带来其他的好处。与文档模型Ҏ(gu)相比Q因为抽掉了(jin)许多文档l节Q数据绑定通常需要的内存更少。比如前面两个图中所C的数据l构Q文档模型方法用了(jin) 10 个单独的对象Q与此相比数据绑定只使用?jin)两个。要创徏的东西少Q构造文档的数据l定表示可能更快一些。最后,数据l定与文档模型相比,应用E序可以更快地访问数据,因ؓ(f)(zhn)可以控制如何表C和存储数据。我后面q要讲到q一炏V?
既然数据l定那么好,Zq要使用文档模型呢?以下两种情况需要用文档模型:(x)
许多应用E序使用 XML 传输数据Q但q不兛_(j)文档表示的细节。这cd用程序非帔R合使用数据l定。如果?zhn)的应用程序符合这U模式,L(fng)l读下去?/p>
![]() ![]() |
![]()
|
目前有几U不同的框架支持 Java XML 数据l定Q但q没有标准的接口。这U情冉|l会(x)得到改变QJava Community Process (JCP) ?JSR-031 正在努力定义q方面的标准Q请参阅 参考资?/font>Q。现在让我们选择一个框架ƈ学习(fn)使用它的接口?
本文选择?Castor 数据l定框架。Castor 目采用 BSD cd的证书,因此可在Mcd的应用程序(包括完整版权的项目)(j)中用?Castor 实际上仅仅有 XML 数据l定Q它q支?SQL ?LDAP l定Q尽本文中不讨些其他的Ҏ(gu)。该目?2000 q初开始发P目前处于?beta 状态(一般可以用这个版本,但是如果需要问题(sh)正,(zhn)可能需要升U到目前?CVS 版本Q。请参阅 参考资?/font>部分?Castor 站点链接Q以?jin)解更多的细节ƈ下蝲该Y件?
![]() ![]() |
![]()
|
Castor XML 数据l定很容易上手,甚至不需要定?XML 文档格式。只要?zhn)的数据用c?JavaBean 的对象表C,Castor p自动生成表示q些数据的文档格式,然后从文档重构原始数据?/p>
![]() |
|
那么“类 JavaBean”是什么意思呢Q真正的 JavaBean 是可视化lgQ可以在开发环境中配置以用?GUI 布局。一些源于真?JavaBean 的惯例已l被 Java 团体普遍接受Q特别是对于数据cR如果一个类W合以下惯例Q我q之ؓ(f)是“类 JavaBean”的Q?
getX
?setX
Ҏ(gu)讉K属性(数据Q?关于技术定义已l扯得太q了(jin)Q当提到q些c?JavaBean cLQ我不再重复说明,只是UC为“bean”类?/p>
在整文章中Q我用航U班机时刻表作ؓ(f)CZ代码。我们从一个简单的 bean cd始说明它的工作原理,q个c表CZ个特定的航班Q包括四个信息项Q?/p>
下面的清?1 l出?jin)处理航班信息的代码?/p>
清单 1. 航班信息 bean
public class FlightBean { private String m_carrier; private int m_number; private String m_departure; private String m_arrival; public FlightBean() {} public void setCarrier(String carrier) { m_carrier = carrier; } public String getCarrier() { return m_carrier; } public void setNumber(int number) { m_number = number; } public int getNumber() { return m_number; } public void setDepartureTime(String time) { m_departure = time; } public String getDepartureTime() { return m_departure; } public void setArrivalTime(String time) { m_arrival = time; } public String getArrivalTime() { return m_arrival; } } |
(zhn)可以看刎ͼq个 bean 本n没有什么意思,因此我想增加一个类q在默认?XML l定中用它Q如清单 2 所C?/p>
清单 2. 试默认的数据绑?/b>
import java.io.*; import org.exolab.castor.xml.*; public class Test { public static void main(String[] argv) { // build a test bean FlightBean bean = new FlightBean(); bean.setCarrier("AR"); bean.setNumber(426); bean.setDepartureTime("6:23a"); bean.setArrivalTime("8:42a"); try { // write it out as XML File file = new File("test.xml"); Writer writer = new FileWriter(file); Marshaller.marshal(bean, writer); // now restore the value and list what we get Reader reader = new FileReader(file); FlightBean read = (FlightBean) Unmarshaller.unmarshal(FlightBean.class, reader); System.out.println("Flight " + read.getCarrier() + read.getNumber() + " departing at " + read.getDepartureTime() + " and arriving at " + read.getArrivalTime()); } catch (IOException ex) { ex.printStackTrace(System.err); } catch (MarshalException ex) { ex.printStackTrace(System.err); } catch (ValidationException ex) { ex.printStackTrace(System.err); } } } |
![]() |
|
q段代码首先构造了(jin)一?FlightBean
beanQƈ使用一些固定的数据初始化它。然后用?bean 默认?Castor XML 映射其写入一个输出文件。最后又d生成?XMLQ?同样使用默认映射重构 beanQ然后打印重构的 bean 中的信息。结果如下:(x)
Flight AR426 departing at 6:23a and arriving at 8:42a
q个输出l果表明(zhn)已l成功地来回转换?jin)航班信息(不算太糟Q只有两ơ方法调用)(j)。现在我q(sh)满于简单控制台输出Q准备再往深处挖一挖?/p>
Z(jin)更清楚地?jin)解q个例子中发生了(jin)什么,看一?Marshaller.marshal()
调用生成?XML。文档如下:(x)
<?xml version="1.0"?> <flight-bean number="426"> <arrival-time>8:42a</arrival-time> <departure-time>6:23a</departure-time> <carrier>AR</carrier> </flight-bean> |
Castor 使用 Java 内部(g)查机制检?Marshaller.marshal()
调用传递的对象。在本例中,它发C(jin)定义的四个属性倹{Castor 在输出的 XML 中创Z个元素(文档的根元素Q表C整个对象。元素名从对象的cd中衍生出来,在这里是 flight-bean
。然后Castor 用以下两U方法中的一个,把该对象的属性值包括进来:(x)
number
属性通过 getNumber()
Ҏ(gu)公开?int
|(j)?
l果是上面所C的 XML 文档?/p>
![]() ![]() |
![]()
|
如果不喜?Castor 的默认映格式,(zhn)可以方便地改变映射。在我们的航班信息例子中Q比方说Q假定我们需要更紧凑的数据表C。用属性代替子元素有助于实现这个目标,我们也许q希望用比默认的名字更短一些的名字。如下所C的文档可以很好地满我们的需要:(x)
<?xml version="1.0"?> <flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/> |
Z(jin)?Castor 使用q种格式而非默认的格式,首先需要定义描q这U格式的映射。映描q本w(非常意外的)(j)是一?XML 文档。清?3 l出?jin)?bean ~组成上q格式的映射?/p>
清单 3. 紧凑格式的映?/b>
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd"> <mapping> <description>Basic mapping example</description> <class name="FlightBean" auto-complete="true"> <map-to xml="flight"/> <field name="carrier"> <bind-xml name="carrier" node="attribute"/> </field> <field name="departureTime"> <bind-xml name="depart" node="attribute"/> </field> <field name="arrivalTime"> <bind-xml name="arrive" node="attribute"/> </field> </class> </mapping> |
class
元素定义?jin)一个命名类 FlightBean
的映。通过在该元素中加?auto-complete
属性ƈ把D?true
Q?zhn)可以告?Castor 对于该类的Q何属性,只要没有在这个元素中专门列出Q就使用默认映射。这样非常简便,因ؓ(f) number
属性已l按照希望的方式处理?jin)?
子元?map-to
告诉 CastorQ要?FlightBean
cȝ实例映射?XML 文档中的 flight
元素。如果?zhn)l箋(hu)使用默认的元素名 flight-bean
Q参?q后节中默认映输出的例子Q,可以不用该元素?
最后,对于每个希望以非默认方式处理的属性,可以引入一?field
子元素。这些子元素都按照相同的模式Q?name
属性给出映的属性名Q?bind-xml
子元素告?Castor 如何映射那个属性。这里要求把每个属性映成l定名称的属性?
现在已经定义?jin)一个映,(zhn)需要告?Castor 框架在编l和解组数据时用那个映。清?4 说明?jin)要实现q一点,需要对前面的代码做哪些修改?/p>
清单 4. 使用映射~组和解l?/b>
... // write it out as XML (if not already present) Mapping map = new Mapping(); map.loadMapping("mapping.xml"); File file = new File("test.xml"); Writer writer = new FileWriter(file); Marshaller marshaller = new Marshaller(writer); marshaller.setMapping(map); marshaller.marshal(bean); // now restore the value and list what we get Reader reader = new FileReader(file); Unmarshaller unmarshaller = new Unmarshaller(map); FlightBean read = (FlightBean)unmarshaller.unmarshal(reader); ... } catch (MappingException ex) { ex.printStackTrace(System.err); ... |
与前?清单 2默认映射所用的代码相比Q这D代码稍微复杂一炏V在执行M其他操作之前Q首先要创徏一?Mapping
对象载入(zhn)的映射定义。真正的~组和解l也有区别。ؓ(f)?jin)用这个映,?zhn)需要创?Marshaller
?Unmarshaller
对象Q用定义的映配|它们,调用q些对象的方法,而不是像W一个例子那样用静(rn)态方法。最后,(zhn)必L供对映射错误产生的另一个异常类型的处理?
完成q些修改后,(zhn)可以尝试再ơ运行程序。控制台输出与第一个例子相同(?清单 2所C)(j)Q但是现在的 XML 文档看v来符合我们的需要:(x)
<?xml version="1.0"?> <flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/> |
![]() ![]() |
![]()
|
现在单个航班数据已经有了(jin)我们喜欢的Ş式,(zhn)可以定义一个更高的结构:(x)航线数据。这个结构包括v降机场的标识W以?qing)在该航U上飞行的一l航班。清?5 l出?jin)一个包含这些信息的 bean cȝ例子?/p>
清单 5. 航线信息 bean
import java.util.ArrayList; public class RouteBean { private String m_from; private String m_to; private ArrayList m_flights; public RouteBean() { m_flights = new ArrayList(); } public void setFrom(String from) { m_from = from; } public String getFrom() { return m_from; } public void setTo(String to) { m_to = to; } public String getTo() { return m_to; } public ArrayList getFlights() { return m_flights; } public void addFlight(FlightBean flight) { m_flights.add(flight); } } |
在这D代码中Q我定义?jin)一?addFlight()
Ҏ(gu)Q用于每ơ增加一个属于这条航U的航班。这是在试E序中徏立这U数据结构非常简便的办法Q但是可能和(zhn)预料的相反Q?Castor 在解l时q不使用U方法向航线中增加航班。相反,它?getFlights()
Ҏ(gu)讉K一l航班,然后直接d到集合中?
在映中处理航班集合只需要稍微改变(sh)一个例子(?清单 3所C)(j)中的 field
元素。清?6 昄?jin)修改后的映文件?
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd"> <mapping> <description>Collection mapping example</description> <class name="RouteBean"> <map-to xml="route"/> <field name="from"> <bind-xml name="from" node="attribute"/> </field> <field name="to"> <bind-xml name="to" node="attribute"/> </field> <field name="flights" collection="collection" type="FlightBean"> <bind-xml name="flight"/> </field> </class> <class name="FlightBean" auto-complete="true"> <field name="carrier"> <bind-xml name="carrier" node="attribute"/> </field> <field name="departureTime"> <bind-xml name="depart" node="attribute"/> </field> <field name="arrivalTime"> <bind-xml name="arrive" node="attribute"/> </field> </class> </mapping> |
一切都和上一个映(?清单 3所C)(j)完全相同Q只不过?field
元素定义?jin)一?RouteBean
?flights
属性。这个映用C(jin)两个原来不需要的属性?collection
属性的?collection
把该属性定义成一?java.util.Collection Q其他值分别定义数l,java.util.Vectors {等Q?type
属性定义包含在集合中的对象cdQ值是完整的限定类名。这里的值是 FlightBean
Q因为对q些cL没有使用包?
另一个区别在 FlightBean
cd素中Q不再需要?map-to
子元素定义绑定的元素名。定?RouteBean
?flights
属性的 field
元素Q通过它的 bind-xml
子元素定义了(jin)q一炏V因为编l或解组 FlightBean
对象只能通过该属性,它们永q用这?bind-xml
元素讑֮的名U?
我不再详l列?gu)个例子的试E序Q因为数据绑定部分和上一个例子相同。以下是用一些示例数据生成的 XML 文档Q?/p>
<?xml version="1.0"?> <route from="SEA" to="LAX"> <flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/> <flight carrier="CA" depart="8:10a" arrive="10:52a" number="833"/> <flight carrier="AR" depart="9:00a" arrive="11:36a" number="433"/> </route> |
![]() ![]() |
![]()
|
现在可以为处理完整的航班时刻表做最后的准备?jin)。?zhn)q需要增加三?beanQ?
AirportBean
用于用于机场信息
CarrierBean
用于航线信息
TimeTableBean
把一切组合v?Z(jin)保持味性,除了(jin)上一个例子(参阅 处理集合Q中用到?RouteBean
?FlightBean
之间的从属关p,(zhn)还要在 bean 之间增加一些联pR?
要增加的W一个联pL修改 FlightBean
Q让它直接引用班Z息,而不再仅仅用代码标识班机。以下是?FlightBean
的修改:(x)
public class FlightBean { private CarrierBean m_carrier; ... public void setCarrier(CarrierBean carrier) { m_carrier = carrier; } public CarrierBean getCarrier() { return m_carrier; } ... } |
然后?RouteBean
做同L(fng)修改Q让它引用机Z息:(x)
public class RouteBean { private AirportBean m_from; private AirportBean m_to; ... public void setFrom(AirportBean from) { m_from = from; } public AirportBean getFrom() { return m_from; } public void setTo(AirportBean to) { m_to = to; } public AirportBean getTo() { return m_to; } ... } |
我没有给出新?bean 自n的代码,因ؓ(f)和前面的代码相比没有什么新鲜的东西。?zhn)可以从下载文?code.jar 中找到完整的CZ代码Q请参阅 参考资?/font>Q?
(zhn)可能需要映文档的其他一些特性,以支持编l和解组的对象之间的引用。清?7 l出?jin)一个完整的映射Q?/p>
清单 7. 完整的时刻表映射
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd"> <mapping> <description>Reference mapping example</description> <class name="TimeTableBean"> <map-to xml="timetable"/> <field name="carriers" type="CarrierBean" collection="collection"> <bind-xml name="carrier"/> </field> <field name="airports" type="AirportBean" collection="collection"> <bind-xml name="airport"/> </field> <field name="routes" type="RouteBean" collection="collection"> <bind-xml name="route"/> </field> </class> <class name="CarrierBean" identity="ident" auto-complete="true"> <field name="ident"> <bind-xml name="ident" node="attribute"/> </field> </class> <class name="AirportBean" identity="ident" auto-complete="true"> <field name="ident"> <bind-xml name="ident" node="attribute"/> </field> </class> <class name="RouteBean"> <field name="from" type="AirportBean"> <bind-xml name="from" node="attribute" reference="true"/> </field> <field name="to" type="AirportBean"> <bind-xml name="to" node="attribute" reference="true"/> </field> <field name="flights" type="FlightBean" collection="collection"> <bind-xml name="flight"/> </field> </class> <class name="FlightBean" auto-complete="true"> <field name="carrier"> <bind-xml name="carrier" node="attribute" reference="true"/> </field> <field name="departureTime"> <bind-xml name="depart" node="attribute"/> </field> <field name="arrivalTime"> <bind-xml name="arrive" node="attribute"/> </field> </class> </mapping> |
除了(jin)新增?bean 之外Q这里有一个重要的变化Q就是增加了(jin) identity
?reference
属性?class
元素?identity
属性,通知 Castor q个命名属性是该类实例的唯一标识W。在q里Q我?CarrierBean
?AirportBean
?ident
属性定义成它们的标识符?
bind-xml
元素?reference
属性,提供?jin)对于该映?Castor 所需要的另一部分链接信息?reference
设ؓ(f) true
的映告?Castor ~组和解l引用对象的标识W,而不是对象本w的副本。从 RouteBean
链接 AirportBean
Q表CU的h点)(j)的引用,?FlightBean
链接 CarrierBean
的引用,都用了(jin)q种Ҏ(gu)?
?Castor 使用q种cd的映解l数据时Q它自动把对象标识符转化为对实际对象的引用。?zhn)需要保证标识符的值确实是唯一的,甚至不同cd的对象之间也要保证这U唯一性。对于本例中的数据,q一点不成问题:(x)飞机的标识符是两个字W,而机场的标识W是三个字符Q永q不?x)冲H。如?实有潜在冲H的可能性,只要在所代表的对象类型的每个标识W加上唯一的前~Q就可以很容易地避免q种问题?
q个例子的测试代码没有新东西Q只是增加了(jin)一些示例数据。清?8 l出?jin)编lŞ成的 XML 文档Q?/p>
清单 8. ~组的时刻表
<?xml version="1.0"?> <timetable> <carrier ident="AR" rating="9"> <URL>http://www.arcticairlines.com</URL> <name>Arctic Airlines</name> </carrier> <carrier ident="CA" rating="7"> <URL>http://www.combinedlines.com</URL> <name>Combined Airlines</name> </carrier> <airport ident="SEA"> <location>Seattle, WA</location> <name>Seattle-Tacoma International Airport</name> </airport> <airport ident="LAX"> <location>Los Angeles, CA</location> <name>Los Angeles International Airport</name> </airport> <route from="SEA" to="LAX"> <flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/> <flight carrier="CA" depart="8:10a" arrive="10:52a" number="833"/> <flight carrier="AR" depart="9:00a" arrive="11:36a" number="433"/> </route> <route from="LAX" to="SEA"> <flight carrier="CA" depart="7:45a" arrive="10:20a" number="311"/> <flight carrier="AR" depart="9:27a" arrive="12:04p" number="593"/> <flight carrier="AR" depart="12:30p" arrive="3:07p" number="102"/> </route> </timetable> |
![]() ![]() |
![]()
|
现在Q时刻表中的所有数据都最l完成了(jin)Q简单地看一看如何在E序中处理它们。用数据绑定,(zhn)已l徏立了(jin)时刻表的数据l构Q它由几U类型的 bean l成。处理数据的应用E序代码可以直接使用q些 bean?/p>
比方_(d)假设(zhn)要查看在西雅图和洛杉矶之间有哪些航班可供选择Qƈ且要求班具备指定的最低品质评L(fng)别。清?9 l出?jin)用数据绑?bean l构获取q些信息的基本代码(完整的细节请参阅?参考资?/font>下蝲的源文gQ?
private static void listFlights(TimeTableBean top, String from, String to, int rating) { // find the routes for outbound and inbound flights Iterator r_iter = top.getRoutes().iterator(); RouteBean in = null; RouteBean out = null; while (r_iter.hasNext()) { RouteBean route = (RouteBean)r_iter.next(); if (route.getFrom().getIdent().equals(from) && route.getTo().getIdent().equals(to)) { out = route; } else if (route.getFrom().getIdent().equals(to) && route.getTo().getIdent().equals(from)) { in = route; } } // make sure we found the routes if (in != null && out != null) { // find outbound flights meeting carrier rating requirement Iterator o_iter = out.getFlights().iterator(); while (o_iter.hasNext()) { FlightBean o_flight = (FlightBean)o_iter.next(); if (o_flight.getCarrier().getRating() >= rating) { // find inbound flights meeting carrier rating // requirement, and leaving after outbound arrives int time = timeToMinute(o_flight.getArrivalTime()); Iterator i_iter = in.getFlights().iterator(); while (i_iter.hasNext()) { FlightBean i_flight = (FlightBean)i_iter.next(); if (i_flight.getCarrier().getRating() >= rating && timeToMinute(i_flight.getDepartureTime()) > time) { // list the flight combination printFlights(o_flight, i_flight, from, to); } } } } } } |
(zhn)可以尝试用前?清单 8中的数据。如果?zhn)询问从西雅图QSEAQ到z杉ӞLAXQ、别大于或{于 8 的班机,׃(x)得到如下的结果:(x)
Leave SEA on Arctic Airlines 426 at 6:23a return from LAX on Arctic Airlines 593 at 9:27a Leave SEA on Arctic Airlines 426 at 6:23a return from LAX on Arctic Airlines 102 at 12:30p Leave SEA on Arctic Airlines 433 at 9:00a return from LAX on Arctic Airlines 102 at 12:30p |
q里我不准备全面讨论使用 XML 文档模型的等价代码,那太复杂?jin),以单独成章。解册个问题最单的方式Q可能是首先解析 carrier
元素Q创建每个标识符代码到相应对象之间的映射链接。然后用和 清单 9中示例代码类似的逻辑。和使用 bean 的例子相比,每一步都更加复杂Q因Z码用的?XML 成分而不是真正的数据倹{性能可能更糟——只Ҏ(gu)据进行少量的操作q(sh)是问题Q但是如果数据处理是应用E序的核?j),q就?x)成Z个主要的焦点?
如果?bean ?XML 的映中使用更多的数据类型{换,差别?x)更大(无论从代码的复杂性还是从性能的角度看Q。比方说Q假设?zhn)使用很多的航班时_(d)可能希望把文本时间{化成一U更好的国际化表C(如一天内的分钟数Q参?清单 9Q。?zhn)可以选择为文本和国际化格式定义可以替换的 get
?set
Ҏ(gu)Q让映射仅仅使用文本形式Q,也可以定义一个定制的 org.exolab.castor.mapping.FieldHandler
实现?Castor 使用q些倹{保留时间值的内部形式Q可以避免匹配清?9 中的航班时进行{换,也许q能加快处理速度?
除了(jin)本文中所q的之外—?FieldHandler
只是一个例子,Castor q有许多qh的特性。但愿这些例子和讨论使?zhn)能够初步领略q个框架的强大功能和灉|性?我相信,(zhn)将和我一样发?Castor 非常有用也非常有?
![]() ![]() |
![]()
|
对于使用 XML 交换数据的应用程序,数据l定是文档模型很好的替代品。它化了(jin)~程Q因为?zhn)不必再按?XML 的方式思考。相反,(zhn)可以直接用代表应用程序所用数据含义的对象。与文档模型相比Q它q潜在地提供?jin)更好的内存和处理器使用效率?/p>
本文中,我?Castor 框架展示?jin)一些越来越复杂的数据绑定的例子。所有这些例子都使用所谓的 直接数据l定Q开发h员根据数据定义类Q然后把数据映射?XML 文档l构。下一文章中Q我探讨另一U方法:(x) 模式数据l定Q利用模式(?DTD、XML 模式或者其他的cdQ生成和那个模式对应的代码?
Castor 同时支持模式Ҏ(gu)和本文中介绍的直接绑定,(zhn)将在以后看到更多的 Castor 应用。我q关注着 JSR-031 Java 数据l定标准的进展,q对q些Ҏ(gu)的性能q行比较。更多了(jin)?Java 中的 XML 数据l定q个领域Q请速来讉KL最q的 IBM developerWorks?
![]() |
||
|
![]() |
Dennis Sosnoski 是西雅图地区 Java 咨询公司 Sosnoski Software Solutions, Inc.的创始h和首席顾问,他是 J2EE、XML ?Web 服务支持斚w的专家。他已经?30 多年专业软g开发经验,最q几q他集中研究服务器端?Java 技术。Dennis l常在全国性的?x)议上?XML ?Java 技术发表演Ԍ(zhn)可以通过 dms@sosnoski.com?Dennis 联系?/p> |