jinfeng_wang

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

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


XMLBEANS 2.0 —— 一位JAVA开发人员的视点

时间:2006-07-13
作者:Jacob DannerRaj Alagumalai
浏览次数: 4546
本文关键字:XMLBeansApacheXmlCursorXPathXQueryOpen SourceDev ToolboxXMLJacob Danner开源
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章

摘要

  随着面向服务架构的出现,大部分用户不得不在应用程序中使用XML。在开发过程中,用户可能已经注意到存在多种可以分析和处理XML的模型,包括开源和专有的。所有这些模型都存在一定的优缺点。选择不适合业务需求的模型可能会导致开发时间延长并浪费资源。Apache XMLBeans是一个非常有价值的工具,它提供一种在Java中使用XML的简便方法。在本文中,我们将介绍XMLBeans以及XMLBeans 2.0中的一些有用特性。

XMLBeans简介

  W3C XML Schema是一个XML文档,该文档定义一组其他XML文档必须遵守才合法的规则。与早期XML模式语言如文档类型定义(document type definition,DTD)或简单对象XML(simple object XML,SOX)相比,W3C XML Schema具有许多优点,它还提供了可供用户以多种方式使用的丰富特性集。

  XMLBeans是完全与模式兼容的XML-Java绑定工具,使用这个工具可以以对Java友好的方式访问XML的全部特性。XMLBean解决方案是独一无二的,因为它提供XML数据的双重视图。XMLBeans维护一个信息和结构均未更改的原始XML文档,并提供一个基于Java的XML数据视图。

  现在我们通过显示一些代码示例来演示XMLBeans 2.0中的一些特性。在每个示例中,我们都会提供模式以及一些操纵模式的XMLBean表示的Java代码。模式和Java示例都可供下载。

  下面我们来看下面的模式片断:

   

  1 <xs:element name="order">
2 <xs:complexType>
3 <xs:sequence>
4 <xs:element name="orderNo" type="xs:string"/>
5 <xs:element name="item" nillable="true"
6 maxOccurs="unbounded" type="tns:itemType"/>
7 <xs:element name="address" type="tns:addressType"/>
8 <xs:element name="quantity" type="tns:quantityType"/>
10 </xs:sequence>
11 </xs:complexType>
12 </xs:element>

  要生成XMLBeans类,需要对模式进行编译。使用scomp实用工具可以很轻松地完成这个任务,因为它可以为所有简单和复杂的类型生成接口。所有类和接口的包名均派生自模式中指定的targetNamespace值。详细情况请阅读Hetal Shah的Configuring XMLBeans(中文版,Dev2Dev,2005年3月)。

  现在我们看看如何生成实例文档,如何针对模式检查文档的有效性,以及如何将实例保存到文件系统。

  下面所生成的OrderDocument接口是一个XMLBeans为任意全局元素或类型创建的特殊“文档”类型示例。

  AddressType和ItemType是为全局复杂类型addressType和sizeType创建的接口:

   

   1 OrderDocument orderDoc = OrderDocument.Factory.newInstance();
2 Order order = orderDoc.addNewOrder();
3 order.setOrderNo("ORD1234");
4 order.setQuantity(4);
5
6 AddressType aType = order.addNewAddress();
7 aType.setCity("Kirkland");
8
9 ItemType iType = order.addNewItem();
10 iType.setId("ITEM003");
11
12 boolean isValid = orderDoc.validate(xopt);
13
14 orderDoc.save(new File("sample.xml"),xopt);

  运行此示例会导致构建一个实例文档,该文档将被验证并以“sample. xml”为名保存在本地文件系统中。该程序还会将此实例文档的内容以及验证测试的结果显示到命令提示符或Unix shell中:

   

   1 <sam:order xmlns:sam="http://temp.openuri.org/Sample">
2 <sam:orderNo>ORD1234</sam:orderNo>
3 <sam:item>
4 <sam:id>ITEM003</sam:id>
5 <sam:description>Latest Item</sam:description>
6 <sam:size>Large</sam:size>
7 </sam:item>
8 <sam:address>
9 <sam:Name>BEA Systems, Inc</sam:Name>
10 <sam:Street>10230 NE Points Drive, Ste 300</sam:Street>
11 <sam:City>Kirkland</sam:City>
12 <sam:Zip>98033</sam:Zip>
13 <sam:State>WA</sam:State>
14 <sam:Country>USA</sam:Country>
15 </sam:address>
16 <sam:quantity>4</sam:quantity>
17 </sam:order>

  这是一个有效的实例文档。在编译一个模式时,从模式生成的API会与表示底层XML模式的XMLBeans类型系统相集成。对模型相关信息的访问权限可通过使用模式类型系统API获取。

  在下一个示例中,我们将展示如何使用getEnumerationValues()方法编程式地访问特定模式类型的多个枚举值。我们使用的模式类型是sizeType,它是带有三个可能值的枚举类型。该模式片断如下所示:

   

   1 <xs:simpleType name="sizeType">
2 <xs:restriction base="xs:token">
3 <xs:enumeration value="Small"/>
4 <xs:enumeration value="Medium"/>
5 <xs:enumeration value="Large"/>
6 </xs:restriction>
7 </xs:simpleType>

  SizeType是SchemaType类,它包含关于simpleType模式类型的信息:

  SchemaType schType = null;
XmlAnySimpleType [] xmlarray = null;
SizeType sType = SizeType.Factory.newInstance();
schType = sType.schemaType();
xmlarray = schType.getEnumerationValues();

  运行此代码示例(EnumerationSample.java)将导致编程式地获取枚举值并将其重定向到System.out:

  Enumeration values for ItemType :
Small
Medium
Large

  XmlCursor是XMLBeans中的一个有趣特性;它们提供一种操作或导航XML实例文档的直观方法。XmlCursor还提供了一种执行XQuery表达式的方法。一旦加载了XML文档,就可以创建一个游标来表示XML中的特定位置。因为用户可以使用具有或不具有对应于XML的模式的游标,因此游标是处理XML的理想方法。

  下一个示例演示如何使用游标操作XMLBean实例。此示例分析在第一个示例中创建的sample.xml。一旦将该文件保存到内存中,就会使用XmlCursor API导航到quantity元素并将值更改为104:

  orderDoc = OrderDocument.Factory.parse(new File("sample.xml"));
XmlCursor xcursor = orderDoc.newCursor();
xcursor.toFirstChild();
xcursor.toChild(3);
xcursor.toEndToken();
xcursor.toPrevChar(1);
xcursor.insertChars("10");
xcursor.disp ose();

  运行此示例会生成下面的输出,它显示修改后的XMLBean文档为什么会无效:

  Message: decimal
value (104) is greater than maxInclusive facet (5) for
quantityType in namespace http://temp.openuri.org/Sample
Location of invalid XML:
<xml-fragment xmlns:sam="http://temp.openuri.org/Sample"/>

  到目前为止,我们已经简要介绍了XMLBeans,现在介绍一下2.0版本中的新特性。

XMLBeans 2.0中的新特性

  通常,通过观察产品的实际运行来了解其中的新特性是比较简便的方法。我们将通过介绍一个利用了XMLBeans的某些重要特性的项目来介绍这些新特性。众所周知,XMLBeans是一个Apache项目,所以它使用Atlassian的Jira问题跟踪和项目管理应用程序来跟踪bug、特性和其他问题。BEA对XMLBeans项目进行了投资,并拥有一个提供高质量软件的标准。这意味着BEA很关注XMLBeans之类项目的质量。由于XMLBeans是开源项目,并且它使用Apache的常见工具如Jira,所以问题就在于BEA如何跟踪XMLBeans的质量指标。

  用于揭示XMLBeans 2.0中的一些新特性的计划就是对这个问题的回答:如何方便地从Jira收集质量指标?

  下面的屏幕快照显示了XMLBeans的项目主页面。请看图片的右边,在Project Summary区域下可以看到一些与我们关心的质量指标问题相关的选项。

图1:XMLBeans Jira项目页面
图1:XMLBeans Jira项目页面(单击图像查看大图)

  Jira的一个好处就是它能提供问题数据的不同视图。在下图中,请看名为Current View的标题。在屏幕快照中,目前选择的是Browser视图,但还有其他选项,包括一个打印视图、一个XML视图,甚至还有一个Excel电子表格视图:

图2:XMLBeans Jira Issue Navigator
图2:XMLBeans Jira Issue Navigator(单击图像查看大图)

  熟悉Jira以及XMLBeans跟踪质量指标的方式后,我们可以通过多种方式收集质量指标。我们的选项包括屏幕抓取HTML、分析电子表格以及从URL获取XML。我们认为最合理的是从URL(通过从Issue Navigator页面单击XML链接而提供)使用XML视图。该URL的内容看起来与下面的XML文档类似:

  <?xml version="1.0" encoding="utf-8" ?>
<!-- RSS generated by JIRA 98 at Sun Dec 04 18:08:34 CET 2005
-->
<rss version="0.92">
<channel>
<title>ASF JIRA</title>
<link>http://issues.apache.org/jira</link>
<description>This file is an XML representation of some
issues</description>
<language>en</language>
<item>
<title>[XMLBEANS-232] Fast Xml Infoset</title>
<link>http://issues.apache.org/jira/browse/x</link>
<description>
<!-- left out for brevity -->
</description>
<environment><![CDATA[]]></environment>
<key id="12326193">XMLBEANS-232</key>
<summary>Fast Xml Infoset</summary>
<type id="4">Improvement</type>
<priority id="3">Major</priority>
<status id="1">Open</status>
<resolution>Unresolved</resolution>
<assignee>Unassigned</assignee>
<reporter username="rrusin">Rafal
Rusin</reporter>
<created>Wed, 30 Nov 2005 13:29:44 +0100
(CET)</created>
<updated>Sat, 3 Dec 2005 18:15:10 +0100
(CET)</updated>
<version>unspecified</version>
<fixVersion>unspecified</fixVersion>
<component>XmlObject</component>
<due></due>
<votes>0</votes>
<comments>
<comment author="dandiep" created="Sat, 3 Dec 2005
18:15:10 +0100 (CET)" level="">
<!-- ... -->
</comment>
</comments>
<customfields>
</customfields>
</item>
<item>
<!-- left out for brevity -->
</item>
</channel>
</rss>

  如果从上面的XML feed查看片断,会发现它被定义为RSS feed。我们的第一步是找到一个RSS 0.92版本的XML Schema模式,这样就可以编译模式,并通过使用XMLBeans的类似于JavaBean的简单API来使用XMLBeans分析URL。我们无法找到官方模式,但可以找到规范,并可由此开始创建模式。随后,我们发现根据规范创建的模式与从Jira获取的RSS feed不匹配。我们该怎么做呢?我们实际上惟一可以选择的就是为此RSS feed创建一个模式,但这费时且容易出错。进行了进一步的调查后,我们偶然发现了新增的inst2xsd特性。

模式到实例再到模式的过程

inst2xsd工具可作为命令行实用工具使用,但用户也可以编程式地使用API。其目的是采用一个XML实例并创建一个合法模式集。该工具也是可配置的,它提供了用于指定使用哪种设计模式的选项(包括Russian Doll、Salami Slice、Venetian Blind;详细信息请参见模式设计指导原则)。

  该工具还能够将枚举映射到重复值,并能够根据数据类型的最小公分母创建类型。

  我们使用lcd:val这个值作为创建最小公分母类型的示例。该文本可由多个内置XML Schema数据类型表示,例如字符串派生的类型(xsd:string、xsd:normalizedString、xsd:token,等等)以及QName类型。在本例中,inst2xsd特性确定类型的方式是查找前缀为lcd的命名空间声明。如果找到该前缀,该类型将是QName,而不是某个可能基于字符串的类型。

  现在看一下我们从Jira接收的RSS feed的结果是什么。如果我们已经将feed保存到名为jiraRssFeed.xml的实例中并已将XMLBEANS_HOME\bin放在我们的路径中,工作流将如下:

  /home/user>inst2xsd
Generates XMLSchema from instance xml documents.
Usage: inst2xsd [opts] [instance.xml]*
Options include:
-design [rd|ss|vb] - XMLSchema design type
rd - Russian Doll Design - local elements and local types
ss - Salami Slice Design - global elements and local
types
vb - Venetian Blind Design (default) - local elements and
global complex types
-simple-content-types [smart|string] - Simple content types
detection (leaf text). Smart is the default
-enumerations [never|NUMBER] - Use enumerations. Default
value is 10.
-outDir [dir] - Directory for output files. Default is '.'
-outPrefix [file_name_prefix] - Prefix for output file names.
Default is 'schema'
-validate - Validates input instances against generated
schemas.
-verbose - print more informational messages
-license - print license information
-help - help information

/home/user>inst2xsd jiraRssFeed.xml -enumerations never
-design rd -verbose -validate
# this generates a schema named schema0.xsd

  这将生成名为schema0.xsd的(可配置)文件,并且模式将与下面的片断类似:

   1 <?xml version="1.0" encoding="UTF-8"?>
2 <xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
3 <xs:element name="rss">
4 <xs:annotation>
5 <xs:documentation>RSS generated by JIRA 98...
</xs:documentation>
6 </xs:annotation>
7 <xs:complexType>
8 <xs:sequence>
9 <xs:element name="channel">
10 <xs:complexType>
11 <xs:sequence>
12 <xs:element type="xs:string" name="title"/>
13 <xs:element type="xs:anyURI" name="link"/>
14 <xs:element type="xs:string" name="description"/>
15 <xs:element type="xs:string" name="language"/>
15 <xs:element name="item" maxOccurs="unbounded"
minOccurs="0">

  从这个片断中我们发现Jira RSS feed所需的所有元素均已定义。

  如果用户想要通过其他方式工作,例如从XML Schema开始,XMLBeans的最新版本就提供了这种功能。xsd2inst工具就为用户提供了从模式和全局元素创建示例文档的方式;该实例将包含简单类型的值。上述两种工具的使用使得使用XML实例和模式变得非常简单。

  在项目的这个阶段,我们就拥有了一个模式,使用这个模式可以通过scomp实用工具创建一个XMLBeans类型jar,并可开始处理业务逻辑以及先前尝试收集的质量指标。

  通过查看Jira RSS feed实例,我们发现我们关注的bug详细信息放在名为item的元素中,而且生成的模式将item元素作为数组。这意味着,如果我们想要获得可能出现在所有项中的信息,就需要迭代所有项。现在我们看看如何通过一些代码实现这个目标。在下面的代码中,我们会遇到名字被指定为方法参数的用户导致的所有问题:

   1 public Vector getItemsFromReporter(String reporter) {
2
3 // Get the Jira RSS feed instance from a URL
4 URL jiraFeedUrl; = new URL("");
5
6 // Get instance objects
7 RssDocument rssDoc = RssDocument.Factory.parse(jiraFeedUrl);
8 RssDocument.Rss rss = rssDoc.getRss();
9 RssDocument.Rss.Channel channel = rss.getChannel();
10
11 // We will use this object to get most of our data
12 RssDocument.Rss.Channel.Item[] items = channel.getItemArray();
13
14 //We will store all of the valid results in a vector
15 Vector results = new Vector();
16
17 for (int i = 0; i < items.length; i++) {
18 RssDocument.Rss.Channel.Item item = items[i];
19
20 //Add item to results vector when reporter == username
21 if(item.getReporter().getUsername().compareTo(reporter) == 0)
22 results.add(item);
23 }
24 }
25
26 return results;
27 }

  可以看出,这是非常整洁的Java代码。但是,当项数变大时,使用此代码也会影响性能。在最新的XMLBeans版本中,新增了两个新特性来帮助解决这些问题。第一个特性是对JDK 5.0泛型的支持,第二个特性是对XPath和Xquery的支持。我们来看看如何将泛型用于XMLBeans。

将泛型用于XMLBeans

  很明显,JDK 5.0泛型可帮助创建参数化的类和方法。Collections API是XMLBeans中首批使用泛型的API之一。在XML Schema中,当元素包含的maxOccurs属性的值大于1时,默认情况下XMLBeans将针对这些类型创建一个Java数组。为了启用泛型,需要将一个附加参数添加到scomp,并需要使用一个兼容JDK 5.0的虚拟机。

  默认情况下,用于从channel获取item元素的API包含如下方法:

 
RssDocument.Rss.Channel.Item getItemArray(int i)
获取item元素
RssDocument.Rss.Channel.Item[] getItemArray()
获取所有item元素的数组
void setItemArray(int i,RssDocument.Rss.Channel.Item item)
设置item元素
void setItemArray(RssDocument.Rss.Channel.Item[] itemArray)
设置所有item元素的数组

  但是,执行了启用泛型的编译步骤后,API会有所变化:

  /home/user>scomp
Compiles a schema into XML Bean classes and metadata.
Usage: scomp [opts] [dirs]* [schema.xsd]* [service.wsdl]*
[config.xsdconfig]*
Options include:
...
-javasource [version] - generate java source compatible for a
Java version (1.4 or 1.5)
...

#This is all it takes to enable Generics in your use of XMLBeans
/home/user>scomp -javasource 1.5 schema0.xsd

  使用上面的示例,可用的新方法将如下所示:

java.util.List<RssDocument.Rss.Channel.Item> getItemList
获取item元素的列表

  现在我们来看看泛型的使用如何能够简化用于实现获取单个用户报告的所有项的方法的代码:

   1 public List getItemsFromReporter(String reporter) {
2
3 // We already loaded the data as above
4 // ...
5 RssDocument.Rss.Channel channel = rss.getChannel();
6
7 // We will use this object to get most of our data
8 List<RssDocument.Rss.Channel.Item> items =
channel.getItemList();
9
10 for (int i = 0; i < items.size(); i++) {
11 RssDocument.Rss.Channel.Item item = items.get(i);
12
13 //Remove results from list
14 if (item.getReporter().getUsername().compareTo(reporter)
!= 0)
15 items.remove(i);
16 }
17 }
18
19 return items;
20 }

  这种方法非常不错,但还有一种更加简单的获取每个用户的项信息的方法——当您了解XPath和/或XQuery之后。

XQuery和XPath

  XMLBeans与XQuery和XPath的集成在2.0版本中有了变化。版本1中使用了Jaxen(一种XPath实现),但与XMLBeans的集成不支持命名空间和前缀。最新版本构建于Saxon 8.1.1版本所提供的XQuery实现的基础之上。由于XQuery在Xpath之上构建,所以Saxon还为XMLBeans提供了XPath实现。为了使用XQuery和XPath的特性,XmlObject类(所有XMLBeans类型都派生自它)提供了两个执行实例的查询和语句的方法。XmlObject API的execQuery()和selectPath()方法返回一个匹配组件的数组。这些方法在XmlCursor对象上也存在,但返回对象是使用匹配值列表填充的另一个XmlCursor对象:

   1 String xq = "for $e in //employee 
where $e/name='Bob' return $e ";
2
3 // Input is a valid xml instance
4 XmlObject o = XmlObject.Factory.parse(input);
5
6 XmlObject[] xObjres = o.execQuery(xq);
7 XmlCursor xCurres = o.newCursor.selectPath(xq);

  从上面的代码片断中可以看出API相当易用,而且您可以采取最方便的方式处理生成的数据。我们在第4行中构建了自己的查询语句,并在第6和第7行中使用不同的API运行该查询。XQuery是一个强大的工具,从下面的代码中可以看出获取项数据变得多么简单:

   1 public XmlObject[] getItemsFromReporter(String reporter) {
2
3 //Load Jira RSS feed data
4 URL jiraFeedUrl; = new URL("");
5
6 //This is the only object we need
7 RssDocument rssDoc = RssDocument.Factory.parse(jiraFeedUrl);
8
9 //Build the statement for the xpath engine
10 String xpathStatement =
"//item[reporter/@username='"+reporter+"']";
11
12 //Execute the statement on the instance
13 //We could cast this to an Item[] if we wanted
14 XmlObject[] queryResult = rssDoc.selectPath(xpathStatement);
15
16 return queryResult;
17 }

  将XQuery与XMLBeans同时使用将使其如虎添翼,使对XML的处理变得简单得多。如果要获取更多有关XQuery的信息,有无数的资源可供参考。我们建议从Apache XMLBeans Web站点上的XMLBeans示例开始。

  到此时,由于XMLBeans提供的最新特性,XMLBeans的质量指标跟踪问题解决方案实现起来已经非常容易了。我们使用inst2xsd实用工具为实例创建模式,而不用从头编写,从而节省了时间。我们可以看到泛型的启用如何通过使业务逻辑变得容易编写而提高了生产力。最后,我们看到新增的XQuery集成如何提供操纵和查询XML的丰富特性。

  这些仅仅是最新版本的XMLBeans中的基本新特性。一些其他特性使得XMLBeans成为可满足处理XML时的所有开发需要的理想工具。而下一个特性提供有关使用XML和XML Schema时可能接收到的错误的更详细信息,从而帮助开发人员提高生产力。

错误代码

  错误代码是2.0版本中提供的另一个伟大特性。人们已创建了许多种方法,以便将这个新特性与scomp之类的工具集成,并允许编程式地访问以便(比如说)在IDE中使用。XML Schema规范的附录C定义了一个错误代码集,它定义了非法模式条款。在分析、验证和编译过程中,可使用错误监听程序编程式地访问错误代码。以前,错误消息的详细信息和模式一致性是越小越好。此外,还添加了有关错误所在位置以及模式规范中的相关内容的详细信息。错误代码本身以“cvc-complex-type.2.2”的形式定义,可参见http://www.w3c.org/TR/xmlschema-1/#cvc-complex-type条款2.2中的解释。下面我们来看看它的工作方式。我们从一个XML Schema开始,并针对它验证一个实例。然后我们将查看旧的错误,并与接收到的最新版本进行比较。

   1 <!-- errorcode.xsd -->
2 <xs:schema
3 xmlns:xs="http://www.w3.org/2001/XMLSchema"
4 targetNamespace="http://xmlbeans.rocks.com/"
5 xmlns:tns="http://xmlbeans.rocks.com/" >
6 <xs:element name="address" type="tns:address"/>
7 <xs:complexType name="address">
8 <xs:sequence>
9 <xs:element name="number" type="xs:unsignedInt"/>
10 <xs:element name="street" type="xs:string"/>
11 <xs:choice>
12 <xs:sequence>
13 <xs:element name="city" type="xs:string"/>
14 <xs:element name="state" type="xs:string"/>
15 </xs:sequence>
16 <xs:element name="zipcode" type="xs:int"/>
17 </xs:choice>
18 <xs:element name="country" type="xs:string"/>
19 </xs:sequence>
20 </xs:complexType>
21 </xs:schema>

  这个模式相当简单。注意xs:choice模型组的用法,因为下面的示例正是在对其进行定义时出错的。我们将要介绍一些错误代码,您很快就可以发现问题所在:

   1 <!-- errorcode.xml -->
2 <t:address
3 xmlns:t="http://xmlbeans.rocks.com/" >
4 <number>72</number>
5 <street>156th NE</street>
6 <country>USA</country>
7 </t:address>

  除了可从命令行使用的scomp实用工具,还存在一个可针对模式验证实例的实用工具。

  /home/user>validate
Validates the specified instance against the specified schema.
Contrast with the svalidate tool, which validates using a stream.
Usage: validate [-dl] [-nopvr] [-noupa] [-license]
schema.xsd instance.xml
Options:
-dl - permit network downloads for imports and
includes (default is off)
-noupa - do not enforce the unique particle attribution rule
-nopvr - do not enforce the particle valid (restriction) rule
-partial - allow partial schema type system
-license - print license information

  如果使用XMLBeans的1.0版本运行validate实用工具,结果将如下所示:

  /home/user>validate errorcode.xsd errorcode.xml
errorcode.xml:0: error: Expected elements
city zipcode at the end of the content in element
address@http://xmlbeans.rocks.com/

  上面的错误文本提到了实例的名称,并告诉我们地址的末尾缺少一些应有的元素。在这个小示例中,这是有点用处的,但没有行号很难找到起点。现在我们将这个代码文本与新版本中的新增错误代码特性进行比较:

   /home/user>validate errorcode.xsd errorcode.xml

errorcode.xml:4: error: cvc-complex-type.2.4a: Expected elements
'city state' instead of 'country' here in element
address@http://xmlbeans.beaworld.com/

errorcode.xml:4: error: cvc-complex-type.2.4c: Expected elements
'zipcode' before the end of the content in element
address@http://xmlbeans.beaworld.com/

  与XMLBeans的1.0版本中的错误文本相比,新的错误文本有很大的改进。两个错误文本都提到了实例,但新错误代码还提供了行号、问题严重程度、附录C模式参考以及更清楚的错误消息。而且,使用新的错误代码,我们发现错误代码cvc-complex-type.2.4a和cvc-complex-type.2.4c还提及更多造成故障的问题。同样,这些错误代码也分别对应于模式规范中一个可使用URL访问的位置。

  刚刚我们介绍了如何通过命令行获取详细的错误文本,现在介绍如何以编程方式获取错误信息:

   1 // Create the error listener and XmlOptions 
2 LinkedList list = new LinkedList();
3 XmlOptions opts = new XmlOptions().setErrorListener(list);
4
5 // Load the instance
6 File instance = new File("<SOME_PATH>\errorcodes.xml");
7 AddressDocument ad = AddressDocument.Factory.parse(instance);
8
9 // If there are errors, making a method call like this will
10 // populate the error listener
11 ad.validate(opts);
12
13 // Since we know there are errors, let's
14 // look at how to get at the data
15 for(int i=0; i < errors.size(); i++) {
16
17 // Cast list object to an XmlError
// type XmlError e = (XmlError)
18 errors.get(i);
19
20 // Now, let's get at all the information about the error
21 // This will be the location of the error in the instance
22 System.out.println("["+e.getLine()+","+e.getColumn()+"]-" +
e.getSeverity())
23 // Information about the error
24 System.out.println(e.getErrorCode() + ": " +e.getMessage());
25 }

  请看此代码片断,以编程方式访问错误信息并不比从命令行获取类似信息困难多少。

性能提升

  用户可能不会注意到以前的特性,但一定会注意到它对开发工作的影响。如果新版本无法带来性能提升,那它还有什么好处呢?

  与在XMLBeans 1.0中一样,性能对于2.0版本极为重要。在大多数情况下,与1.0相比,2.0版本性能有了10%到60%的提升。导致性能提升的原因有许多,其中最重要的是完全不同的存储架构。在1.0版本中,使用了一个名为splay tree的数据结构使所有存储在XML Store中的内容与影响XML数据的操作同步。对于不熟悉它的用户,splay tree可以理解为支持O(log N)次Find、Insert和Delete操作的平衡树。这种数据结构与其他此类树的差别在于它不维持显式的平衡条件。其详细程度超出了用户在大多数情况下的需要。2.0版本使用了一个较为简单的架构,提供较少的复制和较少的对象。

  在对XML数据执行任何操作时,XMLBeans都会加载一个XML Store。XMLBeans总是加载一个XML Store,然后在Store上提供一个绑定视图。与直接解组到Java对象的其他Java/XML绑定框架相比,此绑定视图与完整的XML Infoset真实性通常导致额外的开销。这使得XMLBeans的性能一直是一个障碍,从而消弱了额外的特性与信息所带来的好处。对于运行时性能,人们主要关注的就是XML Store方面,并尽可能地使Store的性能得到提高。

  在对XML Store进行改写时,新增了一个特性,该特性使得使用XMLBeans进行编程可以有更好的性能,并且更易于使用。此特性即DOM Level II支持。DOM是Document Object Model(文档对象模型)的简写,它提供了一个用于处理XML数据的接口。Level II则指定哪些接口是可用的。它与SAX的区别在于XML信息保存在内存中。

固有的DOM II支持

  在1.0版本中,对DOM的访问由Xerces处理,因此此类调用返回一个Xerces DOM Node。在2.0中,类似调用返回XMLBeans DOM表示,因为DOM II现在是天然实现的。这意味着在XMLBeans内无需协调两种不同的数据存储即可访问DOM表示和XMLBeans表示。

  这还意味着可以通过以下三种方式中的任何一种来处理XML。第一种方式是使用XmlObject API中JavaBean风格的方法。第二种方式是通过XMLCursor API使用基于令牌的模型。而第三种方式是使用对熟悉DOM API的人来说非常熟悉的树模型。它有一个特别的好处,就是用户可以在这些方法之间来回切换,而不必担心实例的同步问题。从开发人员的角度来看,这就意味着他们可以使用最顺手的方式来处理XML。现在我们来了解一些可以在其中进行切换以便获得XML的底层视图的API:

  //To get the live DOM Node:
Node XmlObject.getDomNode()
Node XmlCursor.getDomNode()

//To get back:
XmlObject XmlBeans.nodeToObject(Node n)
XmlCursor XmlBeans.nodeToCursor(Node n)

//XMLBeans 1.0 API returns a copy:
Node XmlObject.newDomNode()

  从上面的代码中可以看出,在这些视图之间进行切换相当容易。

结束语

  本文介绍了XMLBeans 2.0中可用的一些新特性。我们了解到XMLBeans提供了一个健壮且完全保真的Java到XML的绑定框架。我们还介绍了如何使用XMLBeans 2.0的一些新特性更方便快捷地完成项目。这些新特性可以提高开发人员的生产力。性能提升也有助于提高生产力,但更重要的是,这意味着花在对应用程序进行调试和分析瓶颈上的时间将会减少。

  我们介绍的特性只是XMLBeans的最新版本所提供的一部分增强。请了解一下XMLBeans,看它是如何帮助改进开发人员的开发工作的。

参考资料

原文出处:http://dev2dev.bea.com/pub/a/2006/05/xmlbeans-2.html

 作者简介

Jacob Danner 是BEA的高级软件工程师。他自2001年BEA的WebLogic Workshop团队建立时起就一直在其中工作。他还曾参与BEA的多项开源工作。

Raj Alagumalai 是BEA Systems的WebLogic Workshop支持部门的一名高级开发人员关系工程师。

posted on 2008-03-10 17:59 jinfeng_wang 阅读(660) 评论(0)  编辑  收藏

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


网站导航: