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項目頁面(單擊圖像查看大圖)
Jira的一個好處就是它能提供問題數據的不同視圖。在下圖中,請看名為Current View的標題。在屏幕快照中,目前選擇的是Browser視圖,但還有其他選項,包括一個打印視圖、一個XML視圖,甚至還有一個Excel電子表格視圖:

圖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 =
"http://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,看它是如何幫助改進開發人員的開發工作的。
參考資料
凡是有該標志的文章,都是該blog博主Caoer(草兒)原創,凡是索引、收藏
、轉載請注明來處和原文作者。非常感謝。