我正在處理的項目將從Web服務器中提取XML並從中構建數據存儲。數據將有一定的核心領域,但需要可擴展...例如我有一個和以後可能想要添加額外的領域。將XML數據轉換爲強大的Flex類型
在Flex應用程序中,我不希望中央數據存儲正在處理XML對象,或者只是將屬性放入對象中。我想要有強類型,例如Person類,它們是從XML創建/填充的。
這是如何以靈活的方式完成的?如果屬性名稱匹配,或者是否需要爲等寫入轉換功能,Flex是否能夠自動從XML構建Person?
我正在處理的項目將從Web服務器中提取XML並從中構建數據存儲。數據將有一定的核心領域,但需要可擴展...例如我有一個和以後可能想要添加額外的領域。將XML數據轉換爲強大的Flex類型
在Flex應用程序中,我不希望中央數據存儲正在處理XML對象,或者只是將屬性放入對象中。我想要有強類型,例如Person類,它們是從XML創建/填充的。
這是如何以靈活的方式完成的?如果屬性名稱匹配,或者是否需要爲等寫入轉換功能,Flex是否能夠自動從XML構建Person?
我不認爲這可以自動完成。我通常創建一個類來鏡像我擁有的XML結構,然後創建一個靜態類方法來創建給定XML節點的對象實例。例如:
package {
public class Foo{
public function Foo(barparam1:String, barparam2:uint, barparam3:String, barparam4:Number){
this._bar1 = barparam1;
this._bar2 = barparam2;
this._bar3 = barparam3;
this._bar4 = barparam4;
}
protected var _bar1:String;
protected var _bar2:uint;
protected var _bar3:String;
protected var _bar4:Number;
public function get bar1():String{ return this._bar1; }
public function get bar2():uint { return this._bar2; }
public function get bar3():String { return this._bar3; }
public function get bar4():Number { return this._bar4; }
public function toString():String{
return "[Foo bar1:\"" + this.bar1 + "\", bar3:\"" + this.bar3 + "\", bar2:" + this.bar2 + ", bar4:" + this.bar4 + "]";
}
public static function createFromXml(xmlParam:XML):Foo{
/* XML Format:
<foo bar1="bar1value" bar2="5">
<bar3>bar3 data</bar3>
<bar4>10</bar4>
</foo>
*/
return new Foo([email protected], [email protected], xmlParam.bar3[0], xmlParam.bar4[0]);
}
}
}
如果你不依賴於XML(例如你有一個應用程序服務器,而不是一個文件服務器),你可以考慮使用AMF(Action Message Format)來傳輸數據。有幾個項目將AMF暴露給服務器,包括Adobe自己的Blaze DS和社區開源變體,如OpenAMF,AMFPHP,PyAMF等。這將使您能夠將自定義對象從服務器傳輸到Flex,自動解析數據類型和類型安全。看看this comparison of data transfer options來了解相對的優點。
這就是說,XML對於諸如應用程序配置數據之類的東西非常有用,而且在那些情況下您並未運行應用程序服務器。我同意另一張海報,我將立即用手將xml解析爲適當的結構。我通常會將這些內容與修復後的VO(對於Value Object)存儲在一起,我將這些成員公諸於衆。我經常這樣做等級。
package model.vo
{
public class ConfigVO
{
public var foo:String;
public var bar:int;
public var baz:Boolean;
public var sections:Array;
public function ConfigVO(xml:XML)
{
parseXML(xml);
}
private function parseXML(xml:XML):void
{
foo = xml.foo;
bar = xml.bar;
baz = (xml.baz == "true");
sections = [];
for each(var sectionXML:XML in xml.section)
{
sections.push(new SectionVO(sectionXML));
}
}
}
}
package model.vo
{
public class SectionVO
{
public var title:String;
public function SectionVO(xml:XML)
{
parseXML(xml);
}
private function parseXML(xml:XML):void
{
title = [email protected];
}
}
}
我見過的系統將XML元素名稱綁定到類定義。這些通常在類上使用某種內省來確定讀取xml的屬性,或者它們將具有一些將實例屬性映射到xml標記或屬性的靜態類屬性。根據我的經驗,他們比他們的價值更麻煩。它需要2秒鐘的時間來添加一個新的公共屬性和一行來從屬性或子標籤讀取數據。這是我的建議,以避免這種複雜的計劃,但我會舉一個簡單的例子來說明完整性。
package model
{
public class XMLReader
{
// maps <tagname> to a class
private static var elementClassMap:Object =
{
"section": SectionVO,
"person": PersonVO
};
public var parsedElements:Array;
public function XMLReader(xml:XML)
{
parsedElements = [];
parseXML(xml);
}
private function parseXML(xml:XML):void
{
var voClass:Class;
for each(var element:XML in xml.children())
{
voClass = elementClassMap[element.name().localname];
if(voClass)
{
parsedElements.push(new voClass(element));
}
}
}
}
}
不久之前我開始一個Flex圖書館工作,這將有助於序列化和反序列化動作腳本對象和XML。所有你需要做的就是創建你的模型對象,在這些字段上放置一些註釋,讓序列化程序知道你想如何序列化字段(元素,屬性,名稱等),並調用序列化過程。
我認爲它適合您的需求。
如果你願意,你可以在http://code.google.com/p/flexxb/查看。
希望這會證明是有幫助的。
創建強大的數據類型有幾個優點,代碼完成和編譯時語法檢查是最重要的。手動映射可以完成,但應該生成(因此不再是真正的手動),以避免遲早不同步。
基於內省的通用轉換庫功能多樣,易於使用,並且應該滿足大多數使用情況。
JAXB是Java的標準。 ASXB爲Actionscript世界提供了這個想法的輕量級實現。它使用帶有註釋的顯式AS對象(un)封送來自XML和來自XML的對象。
如果你不得不在電匯上使用XML,我建議給ASXB一下。如果你可以自由選擇你的格式,並有一個支持服務器端,Adobes自己的AMF格式應該是你的選擇,因爲它在語言中直接支持,並且在傳輸過程中具有低得多的開銷。
在我們當前的項目中,我們編寫了一些小代碼生成器,它們在構建過程中使用Java端的外部API(源內省,還複製Javadoc)並從中生成AS類。當外部需求迫使我們這樣做時,從AMF切換到XML非常容易。
PS:記得編譯器參數添加到您的Flex配置文件,以保持註釋
AsBeanGen可以做到這一點。它爲DTD驅動的XML文件生成值對象。