1
0
mirror of synced 2024-11-23 22:13:49 +00:00

Added: xsd:base64binary supports

This commit is contained in:
Mark van Renswoude 2008-07-20 12:07:18 +00:00
parent fd9c309309
commit 7ed849490c
5 changed files with 175 additions and 28 deletions

View File

@ -9,10 +9,14 @@ unit XMLDataBindingUtils;
interface interface
uses uses
Classes,
SysUtils,
XMLIntf; XMLIntf;
type type
EBase64Error = class(Exception);
TXMLDateTimeFormat = (xdtDateTime, xdtDate, xdtTime); TXMLDateTimeFormat = (xdtDateTime, xdtDate, xdtTime);
TXMLTimeFragment = (xtfMilliseconds, xtfTimezone); TXMLTimeFragment = (xtfMilliseconds, xtfTimezone);
TXMLTimeFragments = set of TXMLTimeFragment; TXMLTimeFragments = set of TXMLTimeFragment;
@ -32,6 +36,9 @@ const
function FloatToXML(AValue: Extended): WideString; function FloatToXML(AValue: Extended): WideString;
function XMLToFloat(const AValue: WideString): Extended; function XMLToFloat(const AValue: WideString): Extended;
function Base64Encode(AValue: String): String;
function Base64Decode(AValue: String): String;
function GetNodeIsNil(ANode: IXMLNode): Boolean; function GetNodeIsNil(ANode: IXMLNode): Boolean;
procedure SetNodeIsNil(ANode: IXMLNode; ASetNil: Boolean); procedure SetNodeIsNil(ANode: IXMLNode; ASetNil: Boolean);
@ -61,11 +68,16 @@ const
XMLIsNilAttribute = 'nil'; XMLIsNilAttribute = 'nil';
Base64ValidChars = ['A'..'Z', 'a'..'z', '0'..'9', '+', '/'];
Base64LookupTable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
'abcdefghijklmnopqrstuvwxyz' +
'0123456789+/';
Base64Padding = '=';
implementation implementation
uses uses
DateUtils, DateUtils,
SysUtils,
Windows; Windows;
@ -262,6 +274,132 @@ begin
end; end;
function Base64Encode(AValue: String): String;
var
pos: Integer;
lookupIndex: array[0..3] of Byte;
padCount: Integer;
begin
Result := '';
if Length(AValue) = 0 then
exit;
padCount := 0;
{ At least 3 input bytes are required, and the input must be a multiple of 3 }
if Length(AValue) < 3 then
padCount := 3 - Length(AValue)
else if Length(AValue) mod 3 <> 0 then
padCount := 3 - (Length(AValue) mod 3);
if padCount > 0 then
AValue := AValue + StringOfChar(#0, padCount);
pos := 1;
{ Process in 3-byte blocks }
while pos <= Length(AValue) - 2 do
begin
{ Each 3 input bytes are converted into 4 index values
in the range of 0..63, by taking 6 bits each step.
6 high bytes of first char }
lookupIndex[0] := (Ord(AValue[pos]) shr 2) and $3F;
{ 2 low bytes of first char + 4 high bytes of second char }
lookupIndex[1] := ((Ord(AValue[pos]) shl 4) and $3F) or
(Ord(AValue[pos + 1]) shr 4);
{ 4 low bytes of second char + 2 high bytes of third char }
lookupIndex[2] :=((Ord(AValue[pos + 1]) shl 2) and $3F) or
(Ord(AValue[pos + 2]) shr 6);
{ 6 low bytes of third char }
lookupIndex[3] := Ord(AValue[pos + 2]) and $3F;
Result := Result + Base64LookupTable[lookupIndex[0] + 1] +
Base64LookupTable[lookupIndex[1] + 1] +
Base64LookupTable[lookupIndex[2] + 1] +
Base64LookupTable[lookupIndex[3] + 1];
Inc(pos, 3);
end;
{ Replace padding }
if padCount > 0 then
begin
for pos := Length(Result) downto Length(Result) - Pred(padCount) do
Result[pos] := Base64Padding;
end;
end;
function Base64LookupIndex(AChar: Char): Byte;
var
lookupIndex: Integer;
begin
Result := Ord(Base64Padding);
for lookupIndex := 1 to Length(Base64LookupTable) do
if Base64LookupTable[lookupIndex] = AChar then
begin
Result := Pred(lookupIndex);
break;
end;
end;
function Base64Decode(AValue: String): String;
var
pos: Integer;
padCount: Integer;
value: Byte;
begin
Result := '';
if Length(AValue) = 0 then
exit;
if Length(AValue) mod 4 <> 0 then
raise EBase64Error.Create('Value length must be a multiple of 4');
padCount := 0;
pos := Length(AValue);
{ Count padding chars }
while (pos > 0) and (AValue[pos] = Base64Padding) do
begin
Inc(padCount);
Dec(pos);
end;
Result := '';
pos := 1;
while pos <= Length(AValue) - 3 do
begin
value := (Base64LookupIndex(AValue[pos]) shl 2) or
(Base64LookupIndex(AValue[pos + 1]) shr 4);
Result := Result + Chr(value);
value := (Base64LookupIndex(AValue[pos + 1]) shl 4) or
(Base64LookupIndex(AValue[pos + 2]) shr 2);
Result := Result + Chr(value);
value := (Base64LookupIndex(AValue[pos + 2]) shl 6) or
(Base64LookupIndex(AValue[pos + 3]));
Result := Result + Chr(value);
Inc(pos, 4);
end;
{ Delete padding }
if padCount > 0 then
SetLength(Result, Length(Result) - padCount);
end;
function GetNodeIsNil(ANode: IXMLNode): Boolean; function GetNodeIsNil(ANode: IXMLNode): Boolean;
begin begin
Result := ANode.HasAttribute(XMLIsNilAttribute, XMLSchemaInstanceURI) and Result := ANode.HasAttribute(XMLIsNilAttribute, XMLSchemaInstanceURI) and

View File

@ -1,5 +1,6 @@
program X2XMLDataBindingTests; program X2XMLDataBindingTests;
{$APPTYPE CONSOLE}
uses uses
ActiveX, ActiveX,
GUITestRunner, GUITestRunner,

View File

@ -181,7 +181,8 @@ type
tcDateTime, tcDateTime,
tcDate, tcDate,
tcTime, tcTime,
tcString); tcString,
tcBase64);
TTypeConversions = set of TTypeConversion; TTypeConversions = set of TTypeConversion;
@ -193,7 +194,7 @@ type
const const
SimpleTypeMapping: array[0..9] of TTypeMapping = SimpleTypeMapping: array[0..10] of TTypeMapping =
( (
(SchemaName: 'int'; DelphiName: 'Integer'; Conversion: tcNone), (SchemaName: 'int'; DelphiName: 'Integer'; Conversion: tcNone),
(SchemaName: 'integer'; DelphiName: 'Integer'; Conversion: tcNone), (SchemaName: 'integer'; DelphiName: 'Integer'; Conversion: tcNone),
@ -204,7 +205,8 @@ const
(SchemaName: 'float'; DelphiName: 'Double'; Conversion: tcFloat), (SchemaName: 'float'; DelphiName: 'Double'; Conversion: tcFloat),
(SchemaName: 'double'; DelphiName: 'Double'; Conversion: tcFloat), (SchemaName: 'double'; DelphiName: 'Double'; Conversion: tcFloat),
(SchemaName: 'boolean'; DelphiName: 'Boolean'; Conversion: tcBoolean), (SchemaName: 'boolean'; DelphiName: 'Boolean'; Conversion: tcBoolean),
(SchemaName: 'string'; DelphiName: 'WideString'; Conversion: tcString) (SchemaName: 'string'; DelphiName: 'WideString'; Conversion: tcString),
(SchemaName: 'base64Binary'; DelphiName: 'WideString'; Conversion: tcBase64)
); );
@ -216,7 +218,8 @@ const
{ tcDateTime } True, { tcDateTime } True,
{ tcDate } True, { tcDate } True,
{ tcTime } True, { tcTime } True,
{ tcString } False { tcString } False,
{ tcBase64 } True
); );
TypeConversionNone: array[TDelphiAccessor, TDelphiNodeType] of String = TypeConversionNone: array[TDelphiAccessor, TDelphiNodeType] of String =
@ -248,7 +251,8 @@ const
{ tcDateTime } ' %<Destination>:s := XMLToDateTime(ChildNodes[''%<Source>:s''].NodeValue, xdtDateTime);', { tcDateTime } ' %<Destination>:s := XMLToDateTime(ChildNodes[''%<Source>:s''].NodeValue, xdtDateTime);',
{ tcDate } ' %<Destination>:s := XMLToDateTime(ChildNodes[''%<Source>:s''].NodeValue, xdtDate);', { tcDate } ' %<Destination>:s := XMLToDateTime(ChildNodes[''%<Source>:s''].NodeValue, xdtDate);',
{ tcTime } ' %<Destination>:s := XMLToDateTime(ChildNodes[''%<Source>:s''].NodeValue, xdtTime);', { tcTime } ' %<Destination>:s := XMLToDateTime(ChildNodes[''%<Source>:s''].NodeValue, xdtTime);',
{ tcString } ' %<Destination>:s := ChildNodes[''%<Source>:s''].Text;' { tcString } ' %<Destination>:s := ChildNodes[''%<Source>:s''].Text;',
{ tcBas64 } ' %<Destination>:s := Base64Decode(Trim(ChildNodes[''%<Source>:s''].Text));'
), ),
{ dntAttribute } { dntAttribute }
( (
@ -258,7 +262,8 @@ const
{ tcDateTime } ' %<Destination>:s := XMLToDateTime(AttributeNodes[''%<Source>:s''].NodeValue, xdtDateTime);', { tcDateTime } ' %<Destination>:s := XMLToDateTime(AttributeNodes[''%<Source>:s''].NodeValue, xdtDateTime);',
{ tcDate } ' %<Destination>:s := XMLToDateTime(AttributeNodes[''%<Source>:s''].NodeValue, xdtDate);', { tcDate } ' %<Destination>:s := XMLToDateTime(AttributeNodes[''%<Source>:s''].NodeValue, xdtDate);',
{ tcTime } ' %<Destination>:s := XMLToDateTime(AttributeNodes[''%<Source>:s''].NodeValue, xdtTime);', { tcTime } ' %<Destination>:s := XMLToDateTime(AttributeNodes[''%<Source>:s''].NodeValue, xdtTime);',
{ tcString } ' %<Destination>:s := AttributeNodes[''%<Source>:s''].Text;' { tcString } ' %<Destination>:s := AttributeNodes[''%<Source>:s''].Text;',
{ tcBase64 } ' %<Destination>:s := Base64Decode(Trim(AttributeNodes[''%<Source>:s''].Text));'
), ),
{ dntCustom} { dntCustom}
( (
@ -268,7 +273,8 @@ const
{ tcDateTime } ' %<Destination>:s := XMLToDateTime(%<Source>:s, xdtDateTime);', { tcDateTime } ' %<Destination>:s := XMLToDateTime(%<Source>:s, xdtDateTime);',
{ tcDate } ' %<Destination>:s := XMLToDateTime(%<Source>:s, xdtDate);', { tcDate } ' %<Destination>:s := XMLToDateTime(%<Source>:s, xdtDate);',
{ tcTime } ' %<Destination>:s := XMLToDateTime(%<Source>:s, xdtTime);', { tcTime } ' %<Destination>:s := XMLToDateTime(%<Source>:s, xdtTime);',
{ tcString } '' { tcString } '',
{ tcBase64 } ' %<Destination>:s := Base64Decode(Trim(%<Source>:s));'
) )
), ),
{ daSet } { daSet }
@ -281,7 +287,8 @@ const
{ tcDateTime } ' ChildNodes[''%<Destination>:s''].NodeValue := DateTimeToXML(%<Source>:s, xdtDateTime);', { tcDateTime } ' ChildNodes[''%<Destination>:s''].NodeValue := DateTimeToXML(%<Source>:s, xdtDateTime);',
{ tcDate } ' ChildNodes[''%<Destination>:s''].NodeValue := DateTimeToXML(%<Source>:s, xdtDate);', { tcDate } ' ChildNodes[''%<Destination>:s''].NodeValue := DateTimeToXML(%<Source>:s, xdtDate);',
{ tcTime } ' ChildNodes[''%<Destination>:s''].NodeValue := DateTimeToXML(%<Source>:s, xdtTime);', { tcTime } ' ChildNodes[''%<Destination>:s''].NodeValue := DateTimeToXML(%<Source>:s, xdtTime);',
{ tcString } '' { tcString } '',
{ tcBase64 } ' ChildNodes[''%<Destination>:s''].NodeValue := Base64Encode(%<Source>:s);'
), ),
{ dntAttribute } { dntAttribute }
( (
@ -291,7 +298,8 @@ const
{ tcDateTime } ' SetAttribute(''%<Destination>:s'', DateTimeToXML(%<Source>:s, xdtDateTime));', { tcDateTime } ' SetAttribute(''%<Destination>:s'', DateTimeToXML(%<Source>:s, xdtDateTime));',
{ tcDate } ' SetAttribute(''%<Destination>:s'', DateTimeToXML(%<Source>:s, xdtDate));', { tcDate } ' SetAttribute(''%<Destination>:s'', DateTimeToXML(%<Source>:s, xdtDate));',
{ tcTime } ' SetAttribute(''%<Destination>:s'', DateTimeToXML(%<Source>:s, xdtTime));', { tcTime } ' SetAttribute(''%<Destination>:s'', DateTimeToXML(%<Source>:s, xdtTime));',
{ tcString } '' { tcString } '',
{ tcBase64 } ' SetAttribute(''%<Destination>:s'', Base64Encode(%<Source>:s));'
), ),
{ dntCustom} { dntCustom}
( (
@ -301,7 +309,8 @@ const
{ tcDateTime } ' %<Destination>:s := DateTimeToXML(%<Source>:s, xdtDateTime);', { tcDateTime } ' %<Destination>:s := DateTimeToXML(%<Source>:s, xdtDateTime);',
{ tcDate } ' %<Destination>:s := DateTimeToXML(%<Source>:s, xdtDate);', { tcDate } ' %<Destination>:s := DateTimeToXML(%<Source>:s, xdtDate);',
{ tcTime } ' %<Destination>:s := DateTimeToXML(%<Source>:s, xdtTime);', { tcTime } ' %<Destination>:s := DateTimeToXML(%<Source>:s, xdtTime);',
{ tcString } '' { tcString } '',
{ tcBase64 } ' %<Destination>:s := Base64Encode(%<Source>:s);'
) )
) )
); );

View File

@ -130,7 +130,7 @@
<Directories Name="UsePackages">False</Directories> <Directories Name="UsePackages">False</Directories>
</Directories> </Directories>
<Parameters> <Parameters>
<Parameters Name="RunParams">"F:\Archive\2007\XMLDataBinding\Tests\Data\02. Collection.xsd"</Parameters> <Parameters Name="RunParams">"F:\Archive\2007\XMLDataBinding\DMS_export_import_formaat.xsd"</Parameters>
<Parameters Name="HostApplication"></Parameters> <Parameters Name="HostApplication"></Parameters>
<Parameters Name="Launcher"></Parameters> <Parameters Name="Launcher"></Parameters>
<Parameters Name="UseLauncher">False</Parameters> <Parameters Name="UseLauncher">False</Parameters>

View File

@ -1,6 +1,6 @@
-$A8 -$A8
-$B- -$B-
-$C- -$C+
-$D+ -$D+
-$E- -$E-
-$F- -$F-
@ -12,7 +12,7 @@
-$L+ -$L+
-$M- -$M-
-$N+ -$N+
-$O- -$O+
-$P+ -$P+
-$Q- -$Q-
-$R- -$R-
@ -22,7 +22,7 @@
-$V+ -$V+
-$W- -$W-
-$X+ -$X+
-$Y+ -$YD
-$Z1 -$Z1
-GD -GD
-cg -cg
@ -32,9 +32,8 @@
-M -M
-$M16384,1048576 -$M16384,1048576
-K$00400000 -K$00400000
-N"lib" -LE"C:\Documents and Settings\PsychoMark\My Documents\Borland Studio Projects\Bpl"
-LE"c:\program files\borland\delphi7\Projects\Bpl" -LN"C:\Documents and Settings\PsychoMark\My Documents\Borland Studio Projects\Bpl"
-LN"c:\program files\borland\delphi7\Projects\Bpl"
-w-UNSAFE_TYPE -w-UNSAFE_TYPE
-w-UNSAFE_CODE -w-UNSAFE_CODE
-w-UNSAFE_CAST -w-UNSAFE_CAST