Цитата:
Сообщение от
AndyD
...По-этому, либо надо будет парсить xml для опраделения таблицы до передачи в метод, либо надо будет знать заранее, какая таблица там будет
X++:
static void xml2record(Args args)
{
InventTable InventTable;
Common common;
xmlDocument xmlDocument = new xmlDocument();
XMLNode xmlNode;
;
select InventTable;
if (xmlDocument.loadXML(InventTable.xml()))
{
xmlNode = xmlDocument.documentElement();
if (xmlNode.nodeName() == "Table:Record")
{
common = new DictTable(tableName2Id(xmlNode.attributes().getNamedItem("name").nodeValue())).makeRecord();
global::recordFromXMLNode(xmlDocument.documentElement(), common);
}
else
common = global::recordFromXMLNode(xmlDocument.documentElement());
}
}
Либо для AX 3.0 можно внести изменение в метод
recordFromXMLNode (так же можно навсякий случай учитывать и атрибут
'table')
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;
// If we don't have an incoming buffer, one is created
if (prmIsDefault(c))
{
// Create a buffer of the correct type
//srf -->
//table = tableName2Id(n.attributes().getNamedItem('table').nodeValue());
table = tableName2Id(n.attributes().getNamedItem('name').nodeValue());
//srf <--
dt = new dictTable(table);
c = dt.makeRecord();
}
else
{
table = c.TableId;
dt = new dictTable(table);
}
...
}
После этого можно пользоваться вызовом
X++:
common = global::recordFromXMLNode(xmlDocument.documentElement());
без передачи табличной переменной вторым параметром. В AX 2009 в данном методе именно так и делается(еще также учитывается атрибут
'table') :
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 tableName;
Types t;
//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
tableName = n.attributes().getNamedItem('name');
// If node does not contain name attribute, try with table attribute.
if (tableName == null)
{
tableName = n.attributes().getNamedItem('table');
}
// Check if table node can be accessed
if (tableName != null)
{
table = tablename2id(tableName.nodeValue());
dt = new DictTable(table);
c = dt.makeRecord();
}
}
else
{
table = c.TableId;
dt = new DictTable(table);
}
...
}
Есть и еще неприятные моменты и ошибки возникающие при работе с
recordFromXMLNode
Вне зависимости от версии AX (3.0, 4.0, 2009), если в таблице есть поле типа
Container - то при сериализации записи c помощью
common.xml() и обратном преобразовании с помощью
recordFromXMLNode вылетает эксепшен. Чтобы побороть данную ошибку нужно внести изменение
Global::valueFromXmlNode X++:
....
case Types::Container :
//srf -->
//retval.value(#value, Global::containerFromXMLNode(n));
retval.value(#value, Global::containerFromXMLNode(n.firstChild()));
//srf <--
break;
...
Для AX 4.0 (SP2 в том числе) не учитываются поля типа
int64, т.е. нужно как минимум в метод
Global::valueFromXmlNode добавить case по типу
int64
X++:
....
case Types::Int64 :
retval.value(#value, str2int64(getXmlNodeValue(n)));
break;
....
Для AX 2009 поле типа
int64 учитывается

, однако совсем забыт новый тип
UtcDateTime, чтобы поля данного типа заполнялись в метод
Global::valueFromXmlNode нужно добавить соотвествующий case
X++:
...
case Types::UtcDateTime :
retval.value(#value, str2datetime(getXmlNodeValue(n), -1));
break;
...