Home AMX User Forum NetLinx Modules & Duet Modules

Variable to XML marshaling / unmarshaling.

Hi guys,

I have the following structure, that I want to serialize to XML and save to the file, which then can be deserialized and used as a simple variable. Here is the code:
DEFINE_TYPE

// Contains information for the specific year.
STRUCTURE _YearStruct
{
    DOUBLE	MONTHS[12]
}

DEFINE_VARIABLE
_YearStruct 	CURRENT_YEAR

// Some test data is filled.
// Year
CURRENT_YEAR.MONTHS[1]		= 31.5
CURRENT_YEAR.MONTHS[2]		= 18.7
CURRENT_YEAR.MONTHS[3]		= 23.2
CURRENT_YEAR.MONTHS[4]		= 21.2
CURRENT_YEAR.MONTHS[5]		= 27.5
CURRENT_YEAR.MONTHS[6]		= 13.5
CURRENT_YEAR.MONTHS[7]		= 19.5
CURRENT_YEAR.MONTHS[8]		= 14.1
CURRENT_YEAR.MONTHS[9]		= 26.5
CURRENT_YEAR.MONTHS[10]		= 23.5
CURRENT_YEAR.MONTHS[11]		= 11.5
CURRENT_YEAR.MONTHS[12]		= 18.5

I am using the following methods for serialization / deserialization of the variable into XML:
slReturn = VARIABLE_TO_XML(CURRENT_YEAR, dataToWrite, lPos, 0)
slReturn = XML_TO_VARIABLE(CURRENT_YEAR, dataRead, lPos, 0)

Please note that I have checked the return codes, and in all cases return value is [highlight]0 - OK[/highlight].
Note, that I have also tried with the encoding options, namely [highlight]XML_ENCODE_TYPES, XML_ENCODE_CHAR_AS_LIST, XML_ENCODE_LE[/highlight].

The encoded string is something like:
<struct><array><name>MONTHS</name><curLength>0</curLength><encoded><style>be</style><size>8</size><data>0000000000803F ...

which doesn't contain the actual data.

Can you please help me on how to serialize / deserialize the above mentioned structured, [highlight]together with it's data[/highlight].

BTW: VARIABLE_TO_STRING didn't work either.

Sincerely,

David Gevorkyan
http://www.david-gevorkyan.com/

Comments

  • Joe HebertJoe Hebert Posts: 2,159
    davidgev wrote:
    The encoded string is something like:
    <struct><array><name>MONTHS</name><curLength>0</curLength><encoded><style>be</style><size>8</size><data>0000000000803F ...
    

    which doesn't contain the actual data.
    What?s wrong with that stuff after the <data> tag?
    davidgev wrote:
    BTW: VARIABLE_TO_STRING didn't work either.
    V2S works fine also; I use it all the time. There?s a pretty decent example in the help file.

    If there is a DEV in a STRUCT I think one or more of the encoding/decoding methods has issues. I forget the exact details.
  • Joe Hebert wrote: »
    If there is a DEV in a STRUCT I think one or more of the encoding/decoding methods has issues. I forget the exact details.

    That's the XML_TO_VARIABLE to function which didn't work with structures/devices. Here's the thread: http://www.amxforums.com/showthread.php?t=4545.

    From what it looks like to me, the length of the MONTHS[ ] array is 0. Might be an issue with the way the array is being filled. Might need to do a SET_LENGTH_ARRAY and REBUILD_EVENT() after it's filled.

    --John
  • Joe HebertJoe Hebert Posts: 2,159
    After further review it looks like the DOUBLE might be causing problems and least from a decode standpoint.

    I assumed that the data posted:

    0000000000803F ...

    was the beginning of the values of MONTHS[] described in hex (which it might be), however, I can?t seem to decode it, even if I use SET_LENGTH_ARRAY.

    Let?s change the DOUBLE to an INTEGER and use the following code:
    DEFINE_DEVICE
    
    dvTP = 10001:1:0
    
    DEFINE_TYPE
    
    STRUCTURE _YearStruct
    {
        INTEGER MONTHS[12]
    }
    
    DEFINE_VARIABLE
    
    _YearStruct 	CURRENT_YEAR
    _YearStruct	ANOTHER_YEAR
    
    CHAR dataToWrite[500]
    
    DEFINE_START
    
    // Some test data is filled.
    // Year
    CURRENT_YEAR.MONTHS[1]		= 31
    CURRENT_YEAR.MONTHS[2]		= 18
    CURRENT_YEAR.MONTHS[3]		= 23
    CURRENT_YEAR.MONTHS[4]		= 21
    CURRENT_YEAR.MONTHS[5]		= 27
    CURRENT_YEAR.MONTHS[6]		= 13
    CURRENT_YEAR.MONTHS[7]		= 19
    CURRENT_YEAR.MONTHS[8]		= 14
    CURRENT_YEAR.MONTHS[9]		= 26
    CURRENT_YEAR.MONTHS[10]		= 23
    CURRENT_YEAR.MONTHS[11]		= 11
    CURRENT_YEAR.MONTHS[12]		= 18
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          
          VARIABLE_TO_XML(CURRENT_YEAR, dataToWrite, 1, 0)   
          XML_TO_VARIABLE(ANOTHER_YEAR,dataToWrite, 1, 0)
       }
       
       
    }
    

    If you put CURRENT_YEAR, ANOTHER_YEAR, and dataToWrite into the debugger and then press button 1 you will see that ANOTHER_YEAR gets populated with the same data decoded from CURRENT_YEAR.

    You will also see that dataToWrite =:
    <struct><array><name>MONTHS</name><curLength>0</curLength><encoded><style>be</style><size>2</size><data>001F001200170015001B000D0013000E001A0017000B0012</data></encoded></array></struct>
    

    If you break the data into pieces you?ll see that:

    $001F = 31 for month[1]
    $0012 = 18 for month[2]
    etc.

    REBUILD_EVENT() doesn?t come into play at all since nothing has been done to the event table to warrant it.

    SET_LENGTH_ARRAY is certainly something to keep in mind but I don?t ?think? it?s needed here (at least from an encode/decode standpoint.)

    I?m more of a V2S/S2V kind of guy and I know I needed to use SET_LENGTH_ARRAY() in certain situations but I?d have to dig up so code to see where and why it was required.
  • Joe HebertJoe Hebert Posts: 2,159
    And after even further review, if you use V2S and S2V instead of the XML route you can get the decode method to work properly using a DOUBLE.
    I guess VARIABLE_TO_XML/XML_TO_VARIABLE has some additional flaws.
    DEFINE_DEVICE
    
    dvTP = 10001:1:0
    
    DEFINE_TYPE
    
    STRUCTURE _YearStruct
    {
        DOUBLE MONTHS[12]
    }
    
    DEFINE_VARIABLE
    
    _YearStruct 	CURRENT_YEAR
    _YearStruct	ANOTHER_YEAR
    
    CHAR dataToWrite[500]
    
    DEFINE_START
    
    // Some test data is filled.
    // Year
    CURRENT_YEAR.MONTHS[1]		= 31.5
    CURRENT_YEAR.MONTHS[2]		= 18.7
    CURRENT_YEAR.MONTHS[3]		= 23.2
    CURRENT_YEAR.MONTHS[4]		= 21.2
    CURRENT_YEAR.MONTHS[5]		= 27.5
    CURRENT_YEAR.MONTHS[6]		= 13.5
    CURRENT_YEAR.MONTHS[7]		= 19.5
    CURRENT_YEAR.MONTHS[8]		= 14.1
    CURRENT_YEAR.MONTHS[9]		= 26.5
    CURRENT_YEAR.MONTHS[10]		= 23.5
    CURRENT_YEAR.MONTHS[11]		= 11.5
    CURRENT_YEAR.MONTHS[12]		= 18.5
    
    [b]SET_LENGTH_ARRAY(CURRENT_YEAR.MONTHS,12)[/b]
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          
          [b]VARIABLE_TO_STRING[/b](CURRENT_YEAR, dataToWrite, 1)   
          [b]STRING_TO_VARIABLE[/b](ANOTHER_YEAR,dataToWrite, 1)
    
       }
       
       
    }
    
    

    After pressing button 1, ANOTHER_YEAR gets populated with the same data decoded from CURRENT_YEAR.

    You will need to do a SET_LENGTH_ARRAY() as John noted earlier if you use VARIABLE_TO_STRING.
  • Joe HebertJoe Hebert Posts: 2,159
    Yes it’s me again, for the last time if you’re all lucky.

    If you are using VARIABLE_TO_XML so that you can write it to file and then read/edit it be aware that:

    A) You will not get a true XML file. The data is just one big-a*s string formatted with tags.

    B) If you absolutely need to use DOUBLEs in your code, I think the only way to do that is to store strings and convert back to DOUBLEs later.

    The following code will give you the look I think you want for you XML output:
    DEFINE_DEVICE
    
    dvTP = 10001:1:0
    
    DEFINE_TYPE
    
    STRUCTURE _YearStruct
    {
        CHAR MONTHS[12][4]
    }
    
    DEFINE_VARIABLE
    
    _YearStruct 	CURRENT_YEAR
    _YearStruct	ANOTHER_YEAR
    
    CHAR dataToWrite[1500]
    
    DEFINE_START
    
    // Some test data is filled.
    // Year
    CURRENT_YEAR.MONTHS[1]		= '31.5'
    CURRENT_YEAR.MONTHS[2]		= '18.7'
    CURRENT_YEAR.MONTHS[3]		= '23.2'
    CURRENT_YEAR.MONTHS[4]		= '21.2'
    CURRENT_YEAR.MONTHS[5]		= '27.5'
    CURRENT_YEAR.MONTHS[6]		= '13.5'
    CURRENT_YEAR.MONTHS[7]		= '19.5'
    CURRENT_YEAR.MONTHS[8]		= '14.1'
    CURRENT_YEAR.MONTHS[9]		= '26.5'
    CURRENT_YEAR.MONTHS[10]		= '23.5'
    CURRENT_YEAR.MONTHS[11]		= '11.5'
    CURRENT_YEAR.MONTHS[12]		= '18.5'
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          
          VARIABLE_TO_XML(CURRENT_YEAR, dataToWrite, 1,0)   
          XML_TO_VARIABLE(ANOTHER_YEAR,dataToWrite, 1,0)
    
       }
       
       
    }
    
    

    After pressing button 1 you will also see that dataToWrite =:
    <struct><array><name>MONTHS</name><curLength>0</curLength><array><index>1</index><curLength>4</curLength><string>31.5</string></array><array><index>2</index><curLength>4</curLength><string>18.7</string></array><array><index>3</index><curLength>4</curLength><string>23.2</string></array><array><index>4</index><curLength>4</curLength><string>21.2</string></array><array><index>5</index><curLength>4</curLength><string>27.5</string></array><array><index>6</index><curLength>4</curLength><string>13.5</string></array><array><index>7</index><curLength>4</curLength><string>19.5</string></array><array><index>8</index><curLength>4</curLength><string>14.1</string></array><array><index>9</index><curLength>4</curLength><string>26.5</string></array><array><index>10</index><curLength>4</curLength><string>23.5</string></array><array><index>11</index><curLength>4</curLength><string>11.5</string></array><array><index>12</index><curLength>4</curLength><string>18.5</string></array></array></struct>
    

    Hope some of this helps.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Just to add my two cents, I gave up on using both methods. I ran across flaws in both methods and have since been reluctant to use either. I have taken to writing my own code to create a pseudo xml file (I think I follow all of the XML standards, but haven't verified it) and parsing the file when needed.

    This may seem a like a waste of time, but the time I spent doing this is nowhere near the time I wasted tracking down the flaws in the built-in methods and the troubleshooting I went through figuring out the the problem was with an internal function, not my code.

    Jeff
  • Joe HebertJoe Hebert Posts: 2,159
    Spire_Jeff wrote: »
    Just to add my two cents, I gave up on using both methods. I ran across flaws in both methods and have since been reluctant to use either. I have taken to writing my own code to create a pseudo xml file (I think I follow all of the XML standards, but haven't verified it) and parsing the file when needed.

    This may seem a like a waste of time, but the time I spent doing this is nowhere near the time I wasted tracking down the flaws in the built-in methods and the troubleshooting I went through figuring out the the problem was with an internal function, not my code.
    I agree to the extent of rolling your own when writing data to a file. I don?t use any of those functions either. I normally write any data I need to store as comma delimited text (a flat file database) that can be edited in Excel if need be.

    That said though, I?d be lost without V2S/S2V. I use it extensively for passing structures into and out of modules. If you can deal with the additional memory overhead involved V2S and S2V are awesome.
  • Nice job getting that to work Joe!

    Wierd, I must not have hit the post button correctly yesterday... one of my posts is missing. The reason I was thinking the month array was 0 was because the Netlinx marshalling protocol for arrays is supposed to include all of those index tags which were missing from the original xml file the OP posted. You got them to appear in your last iteration.

    In the thread I linked earlier, rgelling mentioned that firmware 3.41.422 fixed some of the issues with xml_to_variable. Were you or davidgev using the latest firmware? Having those guys watching the forums give me more confidence that those issues can get taken care of quickly. I'm with you guys on this though, xml_to_variable makes me nervous given it's history. V2S and S2V seems to work better.

    --John
  • Joe HebertJoe Hebert Posts: 2,159
    Were you or davidgev using the latest firmware?
    Not here. My test box is still a step behind and is using .414 firmware.
  • It finally worked!

    Hi guys,

    Thanks a lot for your help and sorry for the late reply (was busy with demo preparation).

    John, my controller is also using v3.41.414 firmware.

    I have actually made the code work, and basically the following changes were done:
      I have added [highlight]SET_LENGTH_ARRAY[/highlight] calls.
      Also have changed the array type from [highlight]DOUBLE[/highlight] to [highlight]FLOAT[/highlight].

    Please note, that I am still using the [highlight]VARIABLE_TO_XML / XML_TO_VARIABLE[/highlight] serialization / deserialization methods.

    Again, thanks for the help.

    Sincerely,

    David Gevorkyan
    http://www.david-gevorkyan.com/
  • Joe HebertJoe Hebert Posts: 2,159
    Glad to hear you got it working the way you want.
    Thanks for letting us know.
Sign In or Register to comment.