I would like to be able to take XML data and write/read it to a Progress database without saving to an OS file. I believe I understand how to get the XML to a stream, but I'm not quite sure how to get it from the stream into a CLOB/Longchar or from the CLOB/Longchar back to the stream.
I have a couple of different XML files that are used for saving settings within the application. For example, I use the SaveAsXML method for an UltraExplorerBar to write the current settings when the app is closing, and then LoadFromXML to read them when restarting. There are also some settings that are not object specific that are managed via a dataset, and those I write out using the dataset's WRITE-XML method and read back using READ-XML. In both cases, the XML is just a file on the OS. These now need to be stored in the database and I would prefer to not use an intermediate OS file.
Can anyone provide some sample code for converting the stream to a CLOB/Longchar and back. It would really be appreciated.
Thanks,
Jim
I would like to be able to take XML data and write/read it to a Progress database without saving to an OS file. I believe I understand how to get the XML to a stream, but I'm not quite sure how to get it from the stream into a CLOB/Longchar or from the CLOB/Longchar back to the stream.
What kind of stream are you working with? An ABL STREAM, or a .NET Stream object?
If the former, then you have the XML in a non-OS file-based form (ie the ProDataSet or buffer object).
-- peter
Oops, I should have been more clear.
This would be a .Net object...
DEFINE VARIABLE myMemoryStream AS System.IO.MemoryStream NO-UNDO.
ASSIGN
myMemoryStream = NEW System.IO.MemoryStream()
.
ultraExplorerBar1:SaveAsXml(myMemoryStream).
/* Now assign a Clob or LongChar variable or database field. */
And then of course, back again.
Thanks,
Jim
DEFINE VARIABLE myMemoryStream AS System.IO.MemoryStream NO-UNDO.
ASSIGN
myMemoryStream = NEW System.IO.MemoryStream()
.
ultraExplorerBar1:SaveAsXml(myMemoryStream).
/* Now assign a Clob or LongChar variable or database field. */
Thanks to something Patrick Tallman said over at
http://communities.progress.com/pcom/message/54023#54023
I came up with the following:
def var obj1 as System.Text.UTF8Encoding.
def var longc as longchar.
obj1 = new System.Text.UTF8Encoding().
longc = obj1:GetString(myMemoryStream:ToArray()).
A question I have is whether this performs better than using a file-based operation such as the untested code below (I'm assuming that performance is the reason why you don't want to write to disk).
ultraExplorerBar1:SaveAsXml('c:\temp\my.xml').
copy-lob from 'c:/temp/my.xml' to longc.
And then of course, back again.
... left as an exercise for the reader
-- peter
Peter,
Thanks for the example...
I will be testing performance between the stream and OS file methods. Our app is going to be able to be run on a Term Server, so I was trying to limit the number of OS files as much as possible. If performance is noticeably better writing to the OS, I may elect to go that route.
Given that, I'm still not quite sure of the reverse method from what you posted. I need to take XML from a Longchar and assign it to a stream and then load into the object. I found an example on the Infragistics site but I'm not sure of the syntax in Progress, particularly the first two lines. The example there is using a grid, but the methods should be similar...
byte[ bt = System.Text.Encoding.UTF8.GetBytes(layout.xmlGridSettings);
MemoryStream stream = new MemoryStream(bt, 0, bt.Length);
gridDocuments.DisplayLayout.LoadFromXml(stream, PropertyCategories.All);
Thanks,
Jim
I will be testing performance between the stream and OS file methods. Our app is going to be able to be run on a Term Server, so I was trying to limit the number of OS files as much as possible. If performance is noticeably better writing to the OS, I may elect to go that route.
That makes sense.
Given that, I'm still not quite sure of the reverse method from what you posted. I need to take XML from a Longchar and assign it to a stream and then load into the object. I found an example on the Infragistics site but I'm not sure of the syntax in Progress, particularly the first two lines. The example there is using a grid, but the methods should be similar...
byte[ bt = System.Text.Encoding.UTF8.GetBytes(layout.xmlGridSettings);
MemoryStream stream = new MemoryStream(bt, 0, bt.Length);gridDocuments.DisplayLayout.LoadFromXml(stream, PropertyCategories.All);
Thanks,
Jim
Based on the IG example, the ABL should look something like the below. The xmlGridSettings LONGCHAR can be populated from the TT.
def var myEnc as System.Text.UTF8Encoding.
def var myStream as System.IO.MemoryStream.
def var xmlGridSettings as longchar.
myEnc = new System.Text.UTF8Encoding().
myStream = new MemoryStream(
myEnc:GetBytes(xmlGridSettings),
0,
myEnc:GetByteCount(xmlGridSettings) ).
/* this also looks to be supported.
myStream = new MemoryStream( myEnc:GetBytes(xmlGridSettings)).
*/
gridDocuments:DisplayLayout:LoadFromXml(myStream, PropertyCategories.All);
hth,
Peter
Excellent, Peter.
Thank you!
Sorry if I'm being dense...
I'm attempting to take the longchar variable which now contains my encoded xml and write it to a database Clob field. I'm using the COPY-LOB statement as so:
COPY-LOB xmlString to myTable.myClobField.
This throws the following error:
Could not update large object segment during copy. (11322)
I haven't found much information about this error. I did verify that the xmlString variable contains a valid XML file by using COPY-LOB to write to a text file. I did have to use NO-CONVERT when I did this however.
Any ideas?
Thanks,
Jim
I'm attempting to take the longchar variable which now contains my encoded xml and write it to a database Clob field. I'm using the COPY-LOB statement as so:
COPY-LOB xmlString to myTable.myClobField.
This throws the following error:
Could not update large object segment during copy. (11322)
I haven't found much information about this error. I did verify that the xmlString variable contains a valid XML file by using COPY-LOB to write to a text file. I did have to use NO-CONVERT when I did this however.
Any ideas?
My first (and only, unfortunately) thought is that this has to do with codepage conversions (maybe try COLUMN-CODEPAGE UTF-8 on the TT def?). I'd contact TS and see if they can help you further.
-- peter
Unfortunately I haven't had to deal with much code page stuff. Maybe for the time being, I'll write to a file and see if I can get that to work.
I still think writing through a memory stream should be possible.
Thanks.
Jim