2011-12-19 1 views
0

У меня есть XML-фрагмент, который содержит иерархию объектов:с использованием динамического определения класса Python и amfast отображения динамического класса и генерации коды для генерации класса ActionScript

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>""" 

я использую XML-представление ElementTree для разбора 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) 

Использование дамп, функция нашла в другом месте на 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, который фактически содержит правильное определение класса?

ответ

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 генерации кода в обычном режиме. Иди меня.