Как оказалось, это еще не все неприятности, связанные с
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;
}