Показать сообщение отдельно
Старый 30.06.2009, 07:25   #7  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
376 / 562 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
Цитата:
Сообщение от 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;
...

Последний раз редактировалось SRF; 30.06.2009 в 07:27.
За это сообщение автора поблагодарили: gl00mie (7).