>>>ÿØÿà>>
>PROTECTED PROCEDURE xml_dbf2str > LPARAMETERS tcTable, tnNumRecs, tcNoHeader > LOCAL lcTableName, lcDTD, laFieldInfo, lnFieldCount, lni > LOCAL lcData, lcCRLF, llNoHeader, lcRetVal > > THIS.write_log('Entering method...', PROGRAM(), '1') > > IF VARTYPE(tcTable)<>'C' > lcRetVal='100-Parameters Error: Table Name C8, #Records (optional, -1 = all)' > THIS.write_log('Returning: '+lcRetVal, PROGRAM(), '2') > RETURN lcRetVal > ENDIF > IF PCOUNT()<3 > llNoHeader=.T. > IF PCOUNT()<2 &&default is to fill resulting object with data > tnNumRecs=1 > ENDIF > ELSE > llNoHeader=INLIST(UPPER(tcNoHeader),'T','Y') > ENDIF > > SELECT (tcTable) &&make sure you're on the right table > IF !UPPER(ALIAS())==UPPER(ALLTRIM(tcTable)) > lcRetVal='202- Table Not Open - '+tcTable > THIS.write_log('Returning: '+lcRetVal, PROGRAM(), '2') > RETURN lcRetVal > ENDIF > IF tnNumRecs<0 &&want entire table? > tnNumRecs=RECCOUNT() > GO TOP > ENDIF > lcCRLF=CRLF > lcTableName=ALIAS()+'_Table' > &&put field info into array for creating DTD and each record > DIMENSION laFieldInfo[1] > lnFieldCount=AFIELDS(laFieldInfo) > > &&can be sent as a parameter or turned on globally via .ini setting > IF llNoHeader AND !this.lXMLDTD > lcDTD='' > ELSE > &&standard DTD (Document Type Definition) for tables converted to xml > lcDTD='<?xml version="1.0" encoding="ISO-8859-1"?>'+lcCRLF+lcCRLF+; > '<!DOCTYPE '+lcTableName+' ['+lcCRLF+; > ' <!ELEMENT '+lcTableName+' (Record+)>'+lcCRLF+; > ' <!ATTLIST '+lcTableName+lcCRLF+; > ' RecCount i4 #REQUIRED>'+lcCRLF+; > ' <!ELEMENT Record (#PCDATA)>'+lcCRLF+; > ' <!ATTLIST Record'+lcCRLF > &&add field list to DTD (Document Type Definition) > FOR lni=1 TO lnFieldCount > lcFoxType=laFieldInfo[lnI,2] > DO CASE > CASE lcFoxType = "C" > lcType = "string" > CASE lcFoxType = "M" > lcType = "bin.hex" > CASE lcFoxType $ "NFY" > lcType = "number" > CASE lcFoxType = "L" > lcType = "boolean" > CASE lcFoxType = "O" > lcType = "object" > CASE lcFoxType = "I" > lcType = "i4" > CASE lcFoxType = "D" > lcType = "date.iso8601" > CASE lcFoxType = "T" > lcType = "datetime.iso8601" > OTHERWISE > lcType = lcFoxType > ENDCASE > > lcDTD=lcDTD+; > ' name='+ PADR(laFieldInfo[lnI,1],10)+; > ' type='+ PADR(lcType,16)+; > ' size='+ PADR(TRANSFORM(laFieldInfo[lnI,3]),5)+; > ' precision='+PADR(TRANSFORM(laFieldInfo[lnI,4]),5)+; > ' #REQUIRED'+lcCRLF > ENDFOR > lcDTD=lcDTD+'>'+lcCRLF+']>'+lcCRLF+lcCRLF > ENDIF > > &&standard table into starts this way > lcData='<XML>'+lcCRLF+; > ' <'+lcTableName+'>'+lcCRLF+; > ' <RecCount>'+TRANSFORM(MIN(tnNumRecs,RECCOUNT()))+'</RecCount>'+lcCRLF > IF tnNumRecs > 0 > scan next tnNumRecs > lcData = lcData + lcCRLF + ' <Record>' + lcCRLF > for lni = 1 TO lnFieldCount > if laFieldInfo[lnI,2] = 'G' > && do nothing - can't process > else > lFieldValue = evaluate(laFieldInfo[lnI,1]) > do case > case laFieldInfo[lnI, 2] $ 'CM' && character, memo > lcStr = rtrim(nvl(lFieldValue, '')) > case laFieldInfo[lnI, 2] $ 'NFB' && numeric, float, double > lcStr = alltrim(str(nvl(lFieldValue, 0), 20, 5)) > case laFieldInfo[lnI, 2] = 'I' && integer > lcStr = transform(nvl(lFieldValue, 0)) > case laFieldInfo[lnI, 2] = 'Y' && currency > lcStr = alltrim(str(mton(nvl(lFieldValue, ntom(0))), 20, 4)) > case laFieldInfo[lnI, 2] = 'D' && date > lcStr = dtoc(nvl(lFieldValue, {})) > case laFieldInfo[lnI, 2] = 'T' && date/time > lcStr = ttoc(nvl(lFieldValue, {})) > case laFieldInfo[lnI, 2] = 'L' && logical > lcStr = iif(nvl(lFieldValue, .f.),'.T.', '.F.') > case laFieldInfo[lnI, 2] $ 'QW' && Blob/VarBinary > lcStr = nvl(lFieldValue, '') > otherwise > lcStr = '' > endcase > lcData = lcData + ' <' + laFieldInfo[lnI, 1] + '>' + ; > lcStr + '</' + laFieldInfo[lnI, 1] + '>' + lcCRLF > endif > endfor > lcData = lcData+' </Record>' + lcCRLF > endscan > endif > > lcData = lcData+' </'+lcTableName+'>'+lcCRLF+ '</XML>'+lcCRLF > this.write_log('Returning: '+lcDTD+lcData, program(), '2') > return lcDTD+lcData > endproc > > protected procedure xm2_dbf2str > lparameters tcTable, tnNumRecs > local lcTableName, lcDTD, laFieldInfo, lnFieldCount, lni, lnF, lnR, lcF, lcR > local lcData, llNoHeader, lcRetVal, lnPlaces > > this.write_log('Entering method...', program(), '1') > > if vartype(tcTable)<>'C' > lcRetVal='100-Parameters Error: Table Name C8, #Records (optional, -1 = all)' > this.write_log('Returning: ' + lcRetVal, program(), '2') > return lcRetVal > endif > if vartype(tnNumRecs) <> 'N' && default is to fill resulting object with data > tnNumRecs = 1 > endif > > select (tcTable) && make sure you're on the right table > if !upper(alias()) == upper(alltrim(tcTable)) > lcRetVal = '202- Table Not Open - ' + tcTable > this.write_log('Returning: ' + lcRetVal, program(), '2') > return lcRetVal > endif > if tnNumRecs < 0 && want entire table? > tnNumRecs = reccount() > go top > endif > > lcTableName = alias() + '_Table' > && put field info into array for creating DTD and each record > dimension laFieldInfo[1] > lnFieldCount = afields(laFieldInfo) > > && standard table into starts this way > lcData = '<XM2><' + lcTableName + '><Fields>' > lnF = 0 > for lni = 1 TO lnFieldCount > if laFieldInfo[lnI, 2] <> 'G' > lnF = lnF + 1 > lcF = transform(lnF) > lcData = lcData + '<' + lcF + '>' + laFieldInfo[lnI,1] + '</' + lcF + '>' > endif > endfor > lcData = lcData + '</Fields>' > if tnNumRecs > 0 > lnR = 0 > scan next tnNumRecs > lnR = lnR + 1 > lcR = transform(lnR) > lcData = lcData + '<R' + lcR + '>' > lnF = 0 > for lni = 1 to lnFieldCount > if laFieldInfo[lnI, 2] = 'G' > && can't process - skip > else > lnF = lnF + 1 > if !empty(nvl(evaluate(laFieldInfo[lnI, 1]), '')) > lFieldValue = evaluate(laFieldInfo[lnI, 1]) > * This.write_log('Working on field ' + transform(lnI) + ': ' + laFieldInfo[lnI, 1] + ; > * ", type: " + laFieldInfo[lnI, 2], program(), '5') > do case > case laFieldInfo[lnI, 2] $ 'CM' && character, memo > lcStr = rtrim(lFieldValue) > case laFieldInfo[lnI, 2] $ 'NFB' && numeric, float, double > lnPlaces = iif(lFieldValue % 1 = 0, 0, 5) > lcStr = alltrim(str(lFieldValue, 20, lnPlaces)) > case laFieldInfo[lnI, 2] = 'I' && integer > lcStr = transform(lFieldValue) > case laFieldInfo[lnI, 2] = 'Y' && currency > lcStr = alltrim(str(mton(lFieldValue), 20, 4)) > case laFieldInfo[lnI, 2] = 'D' && date > lcStr = dtoc(lFieldValue) > case laFieldInfo[lnI, 2] = 'T' && date/time > lcStr = ttoc(lFieldValue) > case laFieldInfo[lnI, 2] = 'L' && logical > lcStr = iif(lFieldValue,'.T.', '.F.') > case laFieldInfo[lnI, 2] $ 'QW' && Blob/VarBinary > lcStr = lFieldValue > otherwise > lcStr = "" > endcase > if len(lcStr) > 0 > lcF = transform(lnF) > lcData = lcData + '<' + lcF + ; > iif(.lXM2IncludeLength, ' L=' + transform(len(lcStr)), '') + ; > '>' + lcStr + '</' + lcF + '>' > endif > endif > endif > endfor > lcData = lcData+'</R' + lcR + '>' > endscan > endif > > lcData = lcData + '</' + lcTableName + '></XM2>' > this.write_log('Returning: ' + lcData, program(), '2') > return lcData > endproc >I believe this is exactly the problem I was facing, because it tries to interpret the binary value from the memo field, and that will produce this short piece of character codes:
CREATE CURSOR cutest (image M) APPEND BLANK REPLACE image WITH FILETOSTR(GETFILE("JPG")) MESSAGEBOX(image) lcString = rtrim(nvl(Image, '')) MESSAGEBOX(lcstring)If you compare that with the output of CursorToXML it looks like this:
CURSORTOXML("cuTest","test.xml",1,8+512)and the image part is inside a ![CDATA[ block in the xml file.