Показать сообщение отдельно
Старый 09.07.2009, 06:30   #8  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
365 / 543 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
Как оказалось, это еще не все неприятности, связанные с recordFromXMLNode. Недавно коллега обнаружил еще пару интересных моментов.

Независимо от версии AX 3.0, AX 4.0 или AX2009 через метод recordFromXMLNode не загружаются поля-массивы записей, поскольку атрибут offset (формируемый при помощи common.xml()) никак не учитывается.

А коде функции valueFromXMLNode (используется в recordFromXMLNode)
X++:
boolean enum; // Any enumeration type will do...
 
...
 
case Types::Enum :
    enum = str2int(getXmlNodeValue(n));
    retval.value(#value, enum);
    break;


Т.е. для enum-ов можно увидеть преобразование int -> boolean, как следствие, некорректная загрузка значений enum'ов, данная ошибка наблюдается только в версиях младше AX 2009, там починили следующим образом
X++:
...
t = df.baseType();
 
if (t == Types::Enum)
    t = Types::Integer;
 
content = valueFromXmlNode(t, fieldNode);
...
После всех этих ошибок, в голову пришли вопросы
Цитата:
А вообще common.xml() и global::recordFromXMLNode это обратные функции или нет? Может есть другие обратные для ниx?
Буду рад услышать комментарии по данным вопросам.

Пока для себя решил, что это обратные функции(то, как они используются в AX, говорит как раз об этом), и те ошибки, которые допущены в реализации recordFromXMLNode и valueFromXMLNode, в последующих версиях должны, как мне кажется, быть устранены

А пока ниже приведен код метода recordFromXMLNode для AX 4.0, устраняющий обе эти ошибки
X++:
// Input is <Record table="name"> <Field:field1> value </Field:field1> ... </Record>
static Common recordFromXMLNode(XmlNode n, Common c = null)
{
    tableId table;
    fieldId field;
    DictTable dt;
    DictField df;
    XmlNode fieldNode;
    str fieldName;
    Struct content;
    // -->
    XmlNode     fieldArrayNode;
    int         fieldArray;
    // <--
    //validate arguments before using them
    if (n == null)
        return null;
    // If we don't have an incoming buffer, one is created
    if (prmisdefault(c))
    {
        // Create a buffer of the correct type
        table = tablename2id(n.attributes().getNamedItem('table').nodeValue());
        dt = new DictTable(table);
        c = dt.makeRecord();
    }
    else
    {
        table = c.TableId;
        dt = new DictTable(table);
    }
    fieldNode = n.firstChild();
    while (fieldNode)
    {
        fieldName = fieldNode.attributes().getNamedItem('name').text();
        field = dt.fieldName2Id(fieldName);
        df = new DictField(table, field);
        // -->
        fieldArrayNode = fieldNode.attributes().getNamedItem('offset');
        if (fieldArrayNode)
        {
            fieldArray = str2int(fieldArrayNode.text());
            if (fieldArray)
            {
                field = fieldId2Ext(field, fieldArray);
            }
        }
        if (df.baseType() == Types::Enum)
        {
            content = valueFromXMLNode (Types::Integer, fieldNode);
        }
        else
        // <--
        content = valueFromXMLNode (df.baseType(), fieldNode);
        c.(field) = content.value('value');
        fieldNode = fieldNode.nextSibling();
    }
    return c;
}
За это сообщение автора поблагодарили: AlGol (3).