0

我有一个包含对象层次结构的 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')

所以我们知道代码实际上是在生成一个类。现在,如果您使用 amfast 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 文件?

4

1 回答 1

0

好的,显然,这是没有人知道该怎么做的事情,所以我想出了一个解决方法。

我修改了 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] + " = 0\n"
    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 代码生成。走我。

于 2011-12-29T22:00:21.123 回答