使用动态python类定义和快速动态类映射和代码生成来生成ActionScript类



我有一个包含对象层次结构的xml片段:

doc = """
<RootObj val1="ValueOne" stat1="Stat1" stat2="Stat2">
  <internalarray type="array">
    <InternalObject val1="12" val2="12" />
    <InternalObject val1="13" val2="13" />
    <InternalObject val1="14" val2="14" />
    <InternalObject val1="15" val2="15" />
  </internalarray>
</RootObj>"""

我使用ElementTree xml表示来解析xml:

from xml.etree import ElementTree as ET
...
xml_doc = ET.XML(doc)

我递归地遍历xml_doc元素,边使用"namedtuple"边构建类定义:

from collections import namedtuple
...
def buildClass(name, node):
  symbol_table = {}
  args = []
  varnames = ""
  for subnode in node:
    args.append(buildClass(subnode.tag, subnode))
    if (subnode.tag not in symbol_table):
      symbol_table[subnode.tag] = 1
      varnames += subnode.tag + " "
  print 'Building class for:', name
  for (key, value) in node.items():
    args.append(value)
    varnames += key + " "
  varnames = varnames.strip()
  if (not name[0] == name[0].upper()):
    #this is an array, do not create a class, just return an array
    #pop the last element, "array"
    args.pop()
    return args
  globals()[name] = namedtuple(name, varnames)
  obj = globals()[name](*args)
  return obj

这样调用:

  rootObj = build_class(xml_doc.tag, xml_doc)

使用dump,一个在StackOverflow中可以找到的函数:

def dump(obj):
  '''return a printable representation of an object for debugging'''
  newobj=obj
  if '__dict__' in dir(obj):
    newobj=obj.__dict__
    if ' object at ' in str(obj) and not newobj.has_key('__type__'):
      newobj['__type__']=str(obj)
    for attr in newobj:
      newobj[attr]=dump(newobj[attr])
  return newobj

您可以调用:

print dump(rootObj)

和看到(我手动格式化空格):

RootObj(
  internalarray=[
    InternalObject(val2='12', val1='12'), 
    InternalObject(val2='13', val1='13'), 
    InternalObject(val2='14', val1='14'), 
    InternalObject(val2='15', val1='15')
  ], 
  val1='ValueOne', stat2='Stat2', stat1='Stat1')

所以我们知道代码实际上在生成一个类。现在,如果您使用快速DynamicClassMapper和代码生成器:

import amfast
from amfast import class_def
from amfast.class_def.code_generator import CodeGenerator   
...
class_mapper = class_def.ClassDefMapper()
mapped_class = class_def.DynamicClassDef(RootObj, 'RootObj', ())
#OR
#mapped_class = class_def.DynamicClassDef(globals()[xml_doc.tag],xml_doc.tag, ())
#I tried both and received the same output
coder = CodeGenerator()
coder.generateFilesFromMapper(class_mapper, use_accessors=False,
  packaged=True, constructor=True, bindable=True, extends='Object')

得到一个文件RootObj.as:

package
{
  [Bindable]
  [RemoteClass(alias='RootObj')]
  public dynamic class RootObj extends Object
  {
    public function RootObj():void
    {
      super();
    }
  }
}

显然缺少所有的属性之类的东西。是否有一种方法利用这种编码方法来输出ActionScript文件,实际上包含正确的类定义?

好的,显然,这是没有人知道如何做的事情,所以我想出了一个解决方案。

我修改buildClass()函数如下:

def buildClass(name, node):
  global _classes
  symbol_table = {}
  args = []
  varnames = ""
  varnameswithtypes = ""
  for subnode in node:
    args.append(buildClass(subnode.tag, subnode))
    if (subnode.tag not in symbol_table):
      symbol_table[subnode.tag] = 1
      varnames += subnode.tag + " "
      if (not subnode.tag[0] == subnode.tag[0].upper()):
        varnameswithtypes += subnode.tag + ":array "
      else:
        varnameswithtypes += subnode.tag + ":object "
  print 'Building class for:', name
  for (key, value) in node.items():
    args.append(value)
    varnames += key + " "
    if (key == "variable_name"):
      varnameswithtypes+= key + ":" + value + " "
    elif (is_numeric(value)):
      varnameswithtypes+= key + ":numeric" + " "
    else:
      varnameswithtypes+= key + ":text" + " "
  varnames = varnames.strip()
  varnameswithtypes = varnameswithtypes.strip()
  if (_classes.has_key(name)):
    if (len(_classes[name]) < len(varnameswithtypes)):
      _classes[name] = varnameswithtypes
  else:
    _classes[name] = varnameswithtypes
  if (not name[0] == name[0].upper()):
    #this is an array, do not create a class, just return an array
    return args
  #print varnames, args
  globals()[name] = namedtuple(name, varnames)
  obj = globals()[name](*args)
  #print dump(obj)
  return obj

然后补充说:

_classdefs = {}
def getClassDef(name):
  global _classdefs, _classes
  _classdefs[name] = "class " + name + "(object):n   def __init__(self):n"    
  classvars = _classes[name].split(" ")
  for x in classvars:
    vals = x.split(":")
    if (vals[1] == "array"):
      c = _classes[vals[0]].split(":")[0]
      if (not _classdefs.has_key(c)):
        getClassDef(c)
      _classdefs[name] += "    self." + vals[0] + " = []n"
    elif (vals[1] == "text"):
      _classdefs[name] += "    self." + vals[0] + " = ""n"
    elif (vals[1] == "numeric"):
      _classdefs[name] += "    self." + vals[0] + " = 0n"
    elif (vals[1] == "object"):
      if (not _classdefs.has_key(vals[0])):
        getClassDef(vals[0])
      subclassvars = _classes[vals[0]].split(" ")
      for z in subclassvars:
        if (z.split(":")[0] == "variable_name"):
          _classdefs[name] += "    self." + z.split(":")[1] + " = " + vals[0] + "()n"

可以这样调用:

getClassDef("RootObj")
for x in _classdefs.keys():
  print _classdefs[x]
使用xml:

<RootObj val1="ValueOne" stat1="Stat1" stat2="Stat2">
  <internalarray>
    <InternalObject val1="12" val2="12" />
    <InternalObject val1="13" val2="13" />
    <InternalObject val1="14" val2="14" />
    <InternalObject val1="15" val2="15" />
  </internalarray>
  <InternalObject2 val1="12" val2="13" variable_name="intObj2" />
</RootObj>

代码将输出:

class RootObj(object):
   def __init__(self):
    self.internalarray = []
    self.intObj2 = InternalObject2()
    self.val1 = ""
    self.stat2 = ""
    self.stat1 = ""
class InternalObject2(object):
   def __init__(self):
    self.val2 = 0
    self.val1 = 0
class InternalObject(object):
   def __init__(self):
    self.val2 = 0
    self.val1 = 0

你可以把它保存到一个.py文件中,然后像平常一样导入到amfast ActionScript代码生成中。去我。

相关内容

  • 没有找到相关文章

最新更新