DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 使用SDO跟蹤XML數據的變化
使用SDO跟蹤XML數據的變化
編輯:XML詳解     

本文給出了一個使用apache SDO處理XML數據的例子。由於SDO現在還不是處理XML的標准的解決方案,因此,本文還討論了SDO中的基本的操作XML數據的方法。

跟蹤數據的變化在很多軟件、應用程序和商業場景中是一個基本的要求。如果要嚴格地實現這個需求是非常困難的,這主要是因為對文件的不同變化建模,並監視這些變化一般很難做到。從另一方面講,在所有的程序中反復地實現這種功能要比將一個單獨的模塊應用到不同的應用程序中更經濟實用。而服務數據對象(SDO),這個由BEA和IBM定義的異構數據訪問解決方案,為開發人員提供了更容易實現的機制來從系統層跟蹤數據的變化。

一、處理XML數據的三個階段

在本文給出的處理XML的例子分為三個不同的階段,這些階段如下:

1、建立

2、處理

3、浏覽

XML數據可以通過一個文件系統在這三個階段之間進行傳輸。在本例的中心場景如下:第二步需要記錄XML文件在第一階段被建立的記錄,當第三步浏覽XML數據時,人們總希望知道這個文件有哪些變化。如果我們使用Word的跟蹤特性,我們將會立即獲得這些變化的值。

許多應用程序都有這些需求,包括實現並發控制、離線應用程序的同步,商業進程管理(BPM)系統。這部分將演示SDO如何幫助我們更容易地實現這些需求。

本文提供的XML數據是一個訂購數據,代碼如下:

http://www.w3.org/2001/XMLSchema"
XMLns="
http://www.example.com/PO"
targetNamespace="
http://www.example.com/PO">

CreatePO.Java類完成了建立XML的工作。代碼如下:

package com.company.sdo.po;
import commonj.sdo.DataObject;
import commonj.sdo.helper.DataFactory;
public class CreatePO {
public static void main(String[] args) throws Exception {
//1.  使用XSD定義類型和屬性
Util.definePOTypes();
//2.  建立根DataObject
DataObject purchaSEOrder =
DataFactory.INSTANCE.create(Constants.PO_NAMESPACE, "PurchaSEOrderType");
//3.  設置根DataObject的數據類型屬性
purchaSEOrder.setString("orderDate", "1999-10-20");
//4.  建立子DataObject
DataObject shipTo = purchaSEOrder.createDataObject("shipTo");
//5.  設置子DataObject的數據類型屬性
shipTo.set("country", "US");
shipTo.set("name", "Alice Smith");
shipTo.set("street", "123 Maple Street");
shipTo.set("city", "Mill Valley");
shipTo.set("state", "CA");
shipTo.setString("zip", "90952");
DataObject billTo = purchaSEOrder.createDataObject("billTo");
billTo.set("country", "US");
billTo.set("name", "Robert Smith");
billTo.set("street", "8 Oak Avenue");
billTo.set("city", "Mill Valley");
billTo.set("state", "PA");
billTo.setString("zip", "95819");
purchaSEOrder.set("comment", "Hurry, my lawn is going wild!");
DataObject items = purchaSEOrder.createDataObject("items");
//6.  為子DataObject “item”建立一個子DataObject
DataObject item1 = items.createDataObject("item");
item1.set("partNum", "872-AA");
item1.set("productName", "Lawnmower");
item1.setInt("quantity", 1);
item1.setString("price", "148.95");
item1.set("comment", "Confirm this is electric");
DataObject item2 = items.createDataObject("item");
item2.set("partNum", "926-AA");
item2.set("productName", "Baby Monitor");
item2.setInt("quantity", 1);
item2.setString("price", "39.98");
item2.setString("shipDate", "2007-11-21");
DataObject item3 = items.createDataObject("item");
item3.set("partNum", "998-AA");
item3.set("productName", "Carpet");
item3.setInt("quantity", 1);
item3.setString("price", "439.98");
item3.setString("shipDate", "2007-12-01");
//7.  將XML數據保存在一個XML文件中
Util.storeXML(purchaseOrder,"purchaSEOrder", Constants.PO_XML);
}
}

1、使用XSD定義類型和屬性;由於我們的數據是基於XML格式的,因此,我們首先需要在運行時定義SDO類型的屬性。這個功能由Util類的definePOTypes()方法完成。在definePOTypes方法內部調用了XSDHelper類。definePOTypes()方法的代碼如下:

public static void definePOTypes() throws Exception {
FileInputStream fis = new FileInputStream(PO_MODEL_ORIGINAL);
XSDHelper.INSTANCE.define(fis, null);
fis.close();
}

 

2、建立根數據對象:SDO的動態API可以通過數據對象的層次和屬性或是一個DataGraph(包含了數據對象元數據的一個圖)來描述結構化數據。SDO提供了用於建立一個未連接的數據對象的DataFactory接口。

3、設置根數據對象的數據類型屬性:訂購單在SDO中是一個類型,並且根據schema,它有一個叫orderDate的數據類型屬性,這是一個日期類型。

4、建立子數據對象:數據對象訂購單有一些子數據對象。例如,上面代碼中的注釋4在purchaseOrder中建立shipTo子結點。除了這種方法,我們還可以使用DataFactory來建立一個未連接的shipTo數據對象,並使用setDataObject方法將他設置成purchaSEOrder的一個子結點。代碼如下:

DataObject shipTo = DataFactory.INSTANCE.create(CONSTANTS.PO_NAMESPACE, "USAddress");
......
PurchaSEOrder.setDataObject("shipTo", shipTo);

5、設置子對象結點的數據類型屬性:基於USAddress類型的定義,shipTo數據對象有不同的數據類型屬性。上面注釋5建立了這些屬性。

6、為子數據對象“item”建立一個子數據對象:這部分顯示了建立XML時SDO數據模型。

在下一部分將討論如何使用SDO的動態API,我們可以編輯訂購單,並且在同時跟蹤他們的變化。

三、記錄處理XML數據的變化

我們可以利用在SDO中定義的ChangeSummary機制來跟蹤訂購單的變化。為了實現我們的第二個目的,我們先來編輯一個這個XML的schema文件po_orginal.xsd。代碼如下:

XMLns="http://www.example.com/PO"
XMLns:sdo="commonj.sdo"
xmlns:sdoxml="commonj.sdo/XML"
targetNamespace="
http://www.example.com/PO">

schemaLocation="C:\\eclipse\\workspace\\SDO\\src\\main\\resources\\sdo.xsd" />


這個被導入的sdo.xsd定義了ChangeSummaryType。我們在PurchaSEOrderType中加一個ChangeSummaryType的元素。我們可以將這個元素命名為任何東西,當然,除了使用“changes”。

為了使用新的schema,我們需要使用Util類的definePOTypes()方法來裝載它。我們將要保存被CreatePO.Java產生的XML文件為po.xml。這個文件和po_original.xml比較得知,po.XML在: 中有一個新的子元素。ProcessPO.Java類處理訂購單。當運行時,程序保存了這個處理過程,並在po_processed.xml中產生了一條變化記錄。po_processed.XML的代碼如下:

http://www.example.com/PO" orderDate="1999-10-20">

Alice Smith
123 Maple Street
Mill Valley
CA
90952


Alice Smith
8 Oak Avenue
Mill Valley
PA
95819

Hurry, my lawn is going wild!


Lawnmower
148.95
1
Confirm this is electric


Baby Monitor
39.98
2
2007-11-21


Armed Chair
299.95
1
Make sure the cover is leather.




Robert Smith


1




Carpet439.9812007-12-01


上面的代碼顯示了XML文件的變化記錄,但是我們更感興趣的是元素,這個元素現在變得更復雜了。這個元素捕捉了訂購單的所有的變化。基本這些變化,應用程序可以恢復以前的未變化的數據。

現在讓我我們看一下ProcessPO.Java類,並分析一個SDO如何允許我們獲得這樣詳細的變化數據。

1、注釋1中在運行時轉載了po.XML。

2、注釋2建立了和purchaSEOrder數據對象相關的ChangeSummary對象。

3、為了跟蹤變化,注釋3打開了ChangeSummary對象的日志功能。

4、在注釋4中,日志是關閉的,purchaSEOrder的所有變化和它的子數據對象在ChangeSummary對象中被捕捉。

5、在注釋5中輸出了結果,我們可以看看Util類中的printChangeSummary方法,代碼如下:

public static void printChangeSummary(ChangeSummary chngSum) {
if (chngSum == null) {
System.out.println("ChangeSummary is not in existence!");
return;
}
for (Iterator it = chngSum.getChangedDataObjects().iterator(); it.hasNext();) {
DataObject changedObject = (DataObject) it.next();
System.out.println();
if (chngSum.isCreated(changedObject)) {//is the changed object newly created
System.out.println("Created: " + changedObject);
if (changedObject.getContainer()!=null){
System.out.println("\t--- to be contained in : "
+ changedObject.getContainer().getType().getName()
+ " ---");
}else{
System.out.println("\t--- created object has no container --- ");
}
printAnnotatedDataObject("newly created",changedObject, 2);
} else if (chngSum.isDeleted(changedObject)) {
System.out.println("Deleted: " + changedObject);
if (chngSum.getOldContainer(changedObject) != null){
System.out.println("\t--- originally contained in : "

+ chngSum.getOldContainer(changedObject)

.getType().getName() + " ---");
}else{
System.out.println("\t--- deleted object has no container ---");
}
// a potential bug in Tuscany SDO, this shows nothing in ProcessPO.Java
printAnnotatedDataObject("deleted",changedObject, 2);
// drill down to deleted property
System.out.println("\t--- deleted property information --- ");
// a potential bug in Tuscany SDO, this section shows nothing in RevIEwPO.Java
for (Iterator settingIt = chngSum.getOldValues(changedObject).iterator();

settingIt.hasNext();) {
printDeletedProperty((ChangeSummary.Setting) settingIt.next());
}
System.out.println("\t--- deleted property information --- ");
} else if (chngSum.isModifIEd(changedObject)) {
System.out.println("Updated:  " + changedObject);
// print out the updated object
printAnnotatedDataObject("after update", changedObject, 2);
// drill down to changed property
System.out.println("\t--- property update information --- ");
for (Iterator settingIt = chngSum.getOldValues(changedObject).iterator();

settingIt.hasNext();) {
ChangeSummary.Setting changeSetting = (ChangeSummary.Setting) settingIt.next();
printUpdatedProperty(changeSetting, changedObject,chngSum);
}
System.out.println("\t--- property update information --- ");
} else
System.out.println("Should never come here!");
}
}

 

在這個方法中,我們首先使用了getChangedDataObjects()來獲得所有變化了的數據對象,然後按著他們的種類處理,即建立、刪除或編輯。如果數據對象是新建的,我們會打印對象的信息和所有的屬性。

在下一部分,我們來浏覽被編輯的訂購單。

四、通過一個不同的實體浏覽數據的變化

XML數據處理的第三部分需要完成兩個任務:

1、程序需要按著編輯順序打印出主要的信息。

2、顯示處理階段所有的修改記錄。

當我們可以更進一步根據著一個記錄變化階段編輯訂購單時,這部分顯示了如何使用ReviewPO.java調用所有的編輯記錄。RevIEwPO.Java的代碼如下:

package com.company.sdo.po;
import Java.io.FileInputStream;
import Java.util.List;
import commonj.sdo.ChangeSummary;
import commonj.sdo.DataObject;
import commonj.sdo.helper.XMLDocument;
import commonj.sdo.helper.XMLHelper;
public class RevIEwPO {
public static void main(String[] args) throws Exception {
Util.definePOTypes();
FileInputStream fis = new FileInputStream(Constants.PO_PROCESSED_XML);
//1. 裝載要處理的訂購單
XMLDocument xmlDoc = XMLHelper.INSTANCE.load(fis);
DataObject purchaSEOrder = XMLDoc.getRootObject();
//2.  顯示被編輯的訂購單的信息
System.out.println();
System.out.println("---received purchase order information---");
System.out.println("Order date: " + purchaSEOrder.get("orderDate"));
System.out.println("Order comment: " + purchaSEOrder.get("comment"));
DataObject shipTo = purchaSEOrder.getDataObject("shipTo");
System.out.println("Ship to name: ");
Util.printDataObject(shipTo,1);
DataObject billTo = purchaSEOrder.getDataObject("billTo");
System.out.println("Bill to name: ");
Util.printDataObject(billTo,1);
DataObject items = purchaSEOrder.getDataObject("items");
List itemList = items.getList("item");
System.out.println("Ordered items: ");
for (int i = 0; i < itemList.size(); i++) {
DataObject item = (DataObject) itemList.get(i);
System.out.println("\tItem " + (i+1) + " :" );
Util.printDataObject(item,2);
}
//3.  顯示了第二階段的數據變化
System.out.println();
System.out.println("---revIEw changes in purchase order ---");
ChangeSummary chngSum = purchaSEOrder.getChangeSummary();
Util.printChangeSummary(chngSum);
//4.  取消第二階段的所有變化
System.out.println();
System.out.println("---action taken after revIEwing the changes---");
System.out.println("\t###undo all changes###");
chngSum.undoChanges();
//5. 編輯訂購單的原始版本
System.out.println();
System.out.println("---changes made in purchase order revIEw---");
chngSum.beginLogging();
billTo.set("name", "Alice Smith");
chngSum.endLogging();
//6.  將新的變化輸出到系統控制台
Util.printChangeSummary(chngSum);
//7.  將改變記錄保存到一個XML文件中
Util.storeXML(purchaseOrder,"purchaSEOrder", Constants.PO_REVIEWED_XML);
}
}


要注意的是第二個任務不同於在前一部分打印ChangeSummary,在這裡printout是直接基於ChangeSummary的。變化細節在運行時被重新裝載。我們可以通過比較這兩個printout來分辨它們的不同。在上一部分,printDataObject()在刪除項時什麼都沒產生,而是調用了printDeletedProperty()來列出它們的屬性和它們的值。在當前的printout中,恰恰相反。

在程序的其他部分,注釋4通過調用undoChanges方法取消了在第二階段的所有的變化,注釋5對訂購單做了一些小的變化。我們可以看看保存變化記錄的文件(po_revIEwed.XML)來驗證這些操作結果。

 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved