我正在研究的项目将从Web服务器中提取XML并从中构建数据存储。数据将具有某些核心字段,但需要可扩展...例如,我有一个,后来可能想要添加额外的字段。
在Flex应用程序中,我不希望中央数据存储处理XML对象或只是将属性放入对象。我希望有强类型,例如Person类,它是从XML创建/填充的。
如何以灵活的方式完成?如果属性名称匹配,或者我是否需要为等编写转换功能,Flex是否能够从XML自动构建Person?
答案 0 :(得分:3)
我不认为这可以自动完成。我通常创建一个类来镜像我拥有的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(xmlParam.@bar1, xmlParam.@bar2, xmlParam.bar3[0], xmlParam.bar4[0]);
}
}
}
答案 1 :(得分:1)
如果您不依赖于XML(例如,您有应用服务器而不是文件服务器),则可以考虑使用AMF(Action Message Format)来传输数据。有一些项目将AMF暴露给服务器,包括Adobe自己的Blaze DS和社区开源变体,如OpenAMF,AMFPHP,PyAMF等。这将使您能够将自定义对象从服务器传输到Flex,自动解析数据类型和类型安全。看看this comparison of data transfer options,了解相对优点。
话虽这么说,XML对于应用程序配置数据以及那些没有运行应用程序服务器的实例非常有用。我同意另一张海报,我会立即用手将xml解析成适当的结构。我通常使用post-fix VO(对于Value Object)存储它们,并将成员保留为public。我经常分层次地这样做。
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 = xml.@title;
}
}
}
我见过过去将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));
}
}
}
}
}
答案 2 :(得分:0)
答案 3 :(得分:0)
不久前,我开始研究一个Flex库,它将帮助将Action Script对象序列化和反序列化为XML。您所要做的就是创建模型对象,在字段上添加一些注释,让序列化器知道您希望如何序列化字段(元素,属性,名称等)以及调用(反)序列化过程。
我认为这符合您的需求。
如果需要,可以在http://code.google.com/p/flexxb/查看。
希望这会有所帮助。
答案 4 :(得分:0)
创建强大的数据类型有几个优点,代码完成和编译时语法检查是最重要的。手动映射可以完成,但应该生成(毕竟不再是手动),以避免迟早不同步。
基于内省的通用转换库功能多样,易于使用,并且应该足以满足大多数用例。
JAXB是Java的标准。 ASXB为Actionscript世界提供了这个想法的轻量级实现。它使用带有注释的显式AS对象来(un)编组来自XML的对象。
如果您被迫在线上使用XML,我建议您仔细查看ASXB。如果您可以自由选择格式并拥有支持服务器端,Adobes自己的AMF格式应该是您的选择,因为它在语言中直接支持并且在传输过程中具有更低的开销。
在我们当前的项目中,我们编写了一些小代码生成器,它们接受Java端的外部API(源内省,也复制Javadoc)并在构建过程中从中生成AS类。因此,当外部要求迫使我们这样做时,很容易从AMF切换到XML。
PS:记得将编译器参数添加到flex配置文件中以保留注释
答案 5 :(得分:0)
AsBeanGen可以做到这一点。它为DTD驱动的XML文件生成值对象。