MG: accelerated xmlread and xmlwrite

git-svn-id: trunk@1797 -
This commit is contained in:
lazarus 2002-07-30 14:36:28 +00:00
parent 77fcbcd0dc
commit d395762f08
4 changed files with 236 additions and 109 deletions

View File

@ -72,8 +72,10 @@ type
{$IFDEF ver1_0} {$IFDEF ver1_0}
DOMString = String; DOMString = String;
DOMPChar = PChar;
{$ELSE} {$ELSE}
DOMString = WideString; DOMString = WideString;
DOMPChar = PWideChar;
{$ENDIF} {$ENDIF}
@ -749,16 +751,33 @@ end;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function CompareDOMStrings(const s1, s2: DOMPChar; l1, l2: integer): integer;
var i: integer;
begin
Result:=l1-l2;
i:=1;
while (i<=l1) and (Result=0) do begin
Result:=ord(s1[i])-ord(s2[i]);
inc(i);
end;
end;
function CompareDOMNodeWithDOMNode(Data1, Data2: Pointer): integer; function CompareDOMNodeWithDOMNode(Data1, Data2: Pointer): integer;
begin begin
Result:=AnsiCompareStr(TDOMNode(Data1).NodeName, Result:=CompareDOMStrings(DOMPChar(TDOMNode(Data1).NodeName),
TDOMNode(Data2).NodeName); DOMPChar(TDOMNode(Data2).NodeName),
length(TDOMNode(Data1).NodeName),
length(TDOMNode(Data2).NodeName)
);
end; end;
function CompareDOMStringWithDOMNode(Data1, Data2: Pointer): integer; function CompareDOMStringWithDOMNode(Data1, Data2: Pointer): integer;
begin begin
Result:=AnsiCompareStr(DOMString(Data1), Result:=CompareDOMStrings(DOMPChar(Data1),
TDOMNode(Data2).NodeName); DOMPChar(TDOMNode(Data2).NodeName),
length(DOMString(Data1)),
length(TDOMNode(Data2).NodeName)
);
end; end;
@ -1596,6 +1615,9 @@ end.
{ {
$Log$ $Log$
Revision 1.2 2002/07/30 14:36:27 lazarus
MG: accelerated xmlread and xmlwrite
Revision 1.1 2002/07/30 06:24:05 lazarus Revision 1.1 2002/07/30 06:24:05 lazarus
MG: added a faster version of TXMLConfig MG: added a faster version of TXMLConfig

View File

@ -89,18 +89,10 @@ begin
end; end;
procedure TXMLConfig.Flush; procedure TXMLConfig.Flush;
var
f: Text;
begin begin
if Modified then if Modified then
begin begin
AssignFile(f, Filename); WriteXMLFile(doc, Filename);
Rewrite(f);
try
WriteXMLFile(doc, f);
finally
CloseFile(f);
end;
FModified := False; FModified := False;
end; end;
end; end;
@ -111,14 +103,14 @@ var
i: Integer; i: Integer;
NodePath: String; NodePath: String;
begin begin
Node := doc.DocumentElement; // MAT: check this Node := doc.DocumentElement;
NodePath := APath; NodePath := APath;
while True do while True do
begin begin
i := Pos('/', NodePath); i := Pos('/', NodePath);
if i = 0 then if i = 0 then
break; break;
Child := Node.FindNode(Copy(NodePath, 1, i - 1)); // MAT: check this Child := Node.FindNode(Copy(NodePath, 1, i - 1));
NodePath := Copy(NodePath, i + 1, Length(NodePath)); NodePath := Copy(NodePath, i + 1, Length(NodePath));
if not Assigned(Child) then if not Assigned(Child) then
begin begin
@ -127,7 +119,7 @@ begin
end; end;
Node := Child; Node := Child;
end; end;
Attr := Node.Attributes.GetNamedItem(NodePath); // MAT: check this Attr := Node.Attributes.GetNamedItem(NodePath);
if Assigned(Attr) then if Assigned(Attr) then
Result := Attr.NodeValue Result := Attr.NodeValue
else else
@ -251,6 +243,9 @@ end;
end. end.
{ {
$Log$ $Log$
Revision 1.2 2002/07/30 14:36:28 lazarus
MG: accelerated xmlread and xmlwrite
Revision 1.1 2002/07/30 06:24:06 lazarus Revision 1.1 2002/07/30 06:24:06 lazarus
MG: added a faster version of TXMLConfig MG: added a faster version of TXMLConfig

View File

@ -88,7 +88,9 @@ type
procedure ExpectWhitespace; procedure ExpectWhitespace;
procedure ExpectString(s: String); procedure ExpectString(s: String);
function CheckFor(s: PChar): Boolean; function CheckFor(s: PChar): Boolean;
procedure SkipString(ValidChars: TSetOfChar);
function GetString(ValidChars: TSetOfChar): String; function GetString(ValidChars: TSetOfChar): String;
function GetString(BufPos: PChar; Len: integer): String;
function GetName(var s: String): Boolean; function GetName(var s: String): Boolean;
function ExpectName: String; // [5] function ExpectName: String; // [5]
@ -200,15 +202,40 @@ begin
Result := False; Result := False;
end; end;
function TXMLReader.GetString(ValidChars: TSetOfChar): String; procedure TXMLReader.SkipString(ValidChars: TSetOfChar);
begin begin
SetLength(Result, 0);
while buf[0] in ValidChars do begin while buf[0] in ValidChars do begin
Result := Result + buf[0];
Inc(buf); Inc(buf);
end; end;
end; end;
function TXMLReader.GetString(ValidChars: TSetOfChar): String;
var
OldBuf: PChar;
i, len: integer;
begin
OldBuf:=Buf;
while buf[0] in ValidChars do begin
Inc(buf);
end;
len:=buf-OldBuf;
SetLength(Result, Len);
for i:=1 to len do begin
Result[i]:=OldBuf[0];
inc(OldBuf);
end;
end;
function TXMLReader.GetString(BufPos: PChar; Len: integer): string;
var i: integer;
begin
SetLength(Result,Len);
for i:=1 to Len do begin
Result[i]:=BufPos[0];
inc(BufPos);
end;
end;
procedure TXMLReader.ProcessXML(ABuf: PChar; AFilename: String); // [1] procedure TXMLReader.ProcessXML(ABuf: PChar; AFilename: String); // [1]
//var //var
// LastNodeBeforeDoc: TDOMNode; // LastNodeBeforeDoc: TDOMNode;
@ -237,6 +264,7 @@ end;
function TXMLReader.GetName(var s: String): Boolean; // [5] function TXMLReader.GetName(var s: String): Boolean; // [5]
var OldBuf: PChar;
begin begin
SetLength(s, 0); SetLength(s, 0);
if not (buf[0] in (Letter + ['_', ':'])) then begin if not (buf[0] in (Letter + ['_', ':'])) then begin
@ -244,28 +272,36 @@ begin
exit; exit;
end; end;
s := buf[0]; OldBuf := buf;
Inc(buf); Inc(buf);
s := s + GetString(Letter + ['0'..'9', '.', '-', '_', ':']); SkipString(Letter + ['0'..'9', '.', '-', '_', ':']);
s := GetString(OldBuf,buf-OldBuf);
Result := True; Result := True;
end; end;
function TXMLReader.ExpectName: String; // [5] function TXMLReader.ExpectName: String; // [5]
var OldBuf: PChar;
begin begin
if not (buf[0] in (Letter + ['_', ':'])) then if not (buf[0] in (Letter + ['_', ':'])) then
RaiseExc('Expected letter, "_" or ":" for name, found "' + buf[0] + '"'); RaiseExc('Expected letter, "_" or ":" for name, found "' + buf[0] + '"');
Result := buf[0]; OldBuf := buf;
Inc(buf); Inc(buf);
Result := Result + GetString(Letter + ['0'..'9', '.', '-', '_', ':']); SkipString(Letter + ['0'..'9', '.', '-', '_', ':']);
Result:=GetString(OldBuf,buf-OldBuf);
end; end;
procedure TXMLReader.ExpectAttValue(attr: TDOMAttr); // [10] procedure TXMLReader.ExpectAttValue(attr: TDOMAttr); // [10]
var var
s: String; s: String;
OldBuf: PChar;
procedure FlushStringBuffer; procedure FlushStringBuffer;
begin begin
if OldBuf<>buf then begin
s := s + GetString(OldBuf,buf-OldBuf);
OldBuf := buf;
end;
if Length(s) > 0 then if Length(s) > 0 then
begin begin
attr.AppendChild(doc.CreateTextNode(s)); attr.AppendChild(doc.CreateTextNode(s));
@ -282,6 +318,7 @@ begin
StrDel[1] := #0; StrDel[1] := #0;
Inc(buf); Inc(buf);
SetLength(s, 0); SetLength(s, 0);
OldBuf := buf;
while not CheckFor(StrDel) do while not CheckFor(StrDel) do
if buf[0] = '&' then if buf[0] = '&' then
begin begin
@ -289,10 +326,11 @@ begin
ParseReference(attr); ParseReference(attr);
end else end else
begin begin
s := s + buf[0];
Inc(buf); Inc(buf);
end; end;
dec(buf);
FlushStringBuffer; FlushStringBuffer;
inc(buf);
ResolveEntities(Attr); ResolveEntities(Attr);
end; end;
@ -300,10 +338,10 @@ function TXMLReader.ExpectPubidLiteral: String;
begin begin
SetLength(Result, 0); SetLength(Result, 0);
if CheckFor('''') then begin if CheckFor('''') then begin
GetString(PubidChars - ['''']); SkipString(PubidChars - ['''']);
ExpectString(''''); ExpectString('''');
end else if CheckFor('"') then begin end else if CheckFor('"') then begin
GetString(PubidChars - ['"']); SkipString(PubidChars - ['"']);
ExpectString('"'); ExpectString('"');
end else end else
RaiseExc('Expected quotation marks'); RaiseExc('Expected quotation marks');
@ -312,14 +350,16 @@ end;
function TXMLReader.ParseComment(AOwner: TDOMNode): Boolean; // [15] function TXMLReader.ParseComment(AOwner: TDOMNode): Boolean; // [15]
var var
comment: String; comment: String;
OldBuf: PChar;
begin begin
if CheckFor('<!--') then begin if CheckFor('<!--') then begin
SetLength(comment, 0); SetLength(comment, 0);
OldBuf := buf;
while (buf[0] <> #0) and (buf[1] <> #0) and while (buf[0] <> #0) and (buf[1] <> #0) and
((buf[0] <> '-') or (buf[1] <> '-')) do begin ((buf[0] <> '-') or (buf[1] <> '-')) do begin
comment := comment + buf[0];
Inc(buf); Inc(buf);
end; end;
comment:=GetString(OldBuf,buf-OldBuf);
AOwner.AppendChild(doc.CreateComment(comment)); AOwner.AppendChild(doc.CreateComment(comment));
ExpectString('-->'); ExpectString('-->');
Result := True; Result := True;
@ -435,7 +475,7 @@ begin
if CheckFor('[') then if CheckFor('[') then
begin begin
ParseDoctypeDecls; ParseDoctypeDecls;
SkipWhitespace; SkipWhitespace;
end; end;
ExpectString('>'); ExpectString('>');
end; end;
@ -589,12 +629,12 @@ function TXMLReader.ParseMarkupDecl: Boolean; // [29]
end; end;
end else if CheckFor('(') then begin // [59] end else if CheckFor('(') then begin // [59]
SkipWhitespace; SkipWhitespace;
GetString(Nmtoken); SkipString(Nmtoken);
SkipWhitespace; SkipWhitespace;
while not CheckFor(')') do begin while not CheckFor(')') do begin
ExpectString('|'); ExpectString('|');
SkipWhitespace; SkipWhitespace;
GetString(Nmtoken); SkipString(Nmtoken);
SkipWhitespace; SkipWhitespace;
end; end;
end else end else
@ -728,13 +768,15 @@ var
var var
s: String; s: String;
i: Integer; i: Integer;
OldBuf: PChar;
begin begin
SetLength(s, 0); SetLength(s, 0);
OldBuf := buf;
while not (buf[0] in [#0, '<', '&']) do while not (buf[0] in [#0, '<', '&']) do
begin begin
s := s + buf[0];
Inc(buf); Inc(buf);
end; end;
s:=GetString(OldBuf,buf-OldBuf);
if Length(s) > 0 then if Length(s) > 0 then
begin begin
// Check if s has non-whitespace content // Check if s has non-whitespace content
@ -742,7 +784,7 @@ var
while (i > 0) and (s[i] in WhitespaceChars) do while (i > 0) and (s[i] in WhitespaceChars) do
Dec(i); Dec(i);
if i > 0 then if i > 0 then
NewElem.AppendChild(doc.CreateTextNode(s)); NewElem.AppendChild(doc.CreateTextNode(s));
Result := True; Result := True;
end else end else
Result := False; Result := False;
@ -751,15 +793,17 @@ var
function ParseCDSect: Boolean; // [18] function ParseCDSect: Boolean; // [18]
var var
cdata: String; cdata: String;
OldBuf: PChar;
begin begin
if CheckFor('<![CDATA[') then if CheckFor('<![CDATA[') then
begin begin
SetLength(cdata, 0); SetLength(cdata, 0);
OldBuf := buf;
while not CheckFor(']]>') do while not CheckFor(']]>') do
begin begin
cdata := cdata + buf[0];
Inc(buf); Inc(buf);
end; end;
cdata := GetString(OldBuf,buf-OldBuf);
NewElem.AppendChild(doc.CreateCDATASection(cdata)); NewElem.AppendChild(doc.CreateCDATASection(cdata));
Result := True; Result := True;
end else end else
@ -879,21 +923,25 @@ end;
function TXMLReader.ParseExternalID: Boolean; // [75] function TXMLReader.ParseExternalID: Boolean; // [75]
function GetSystemLiteral: String; function GetSystemLiteral: String;
var
OldBuf: PChar;
begin begin
SetLength(Result, 0); SetLength(Result, 0);
if buf[0] = '''' then begin if buf[0] = '''' then begin
Inc(buf); Inc(buf);
OldBuf := buf;
while (buf[0] <> '''') and (buf[0] <> #0) do begin while (buf[0] <> '''') and (buf[0] <> #0) do begin
Result := Result + buf[0];
Inc(buf); Inc(buf);
end; end;
Result := GetString(OldBuf,buf-OldBuf);
ExpectString(''''); ExpectString('''');
end else if buf[0] = '"' then begin end else if buf[0] = '"' then begin
Inc(buf); Inc(buf);
OldBuf := buf;
while (buf[0] <> '"') and (buf[0] <> #0) do begin while (buf[0] <> '"') and (buf[0] <> #0) do begin
Result := Result + buf[0];
Inc(buf); Inc(buf);
end; end;
Result := GetString(OldBuf,buf-OldBuf);
ExpectString('"'); ExpectString('"');
end; end;
end; end;
@ -922,12 +970,14 @@ end;
function TXMLReader.ParseEncodingDecl: String; // [80] function TXMLReader.ParseEncodingDecl: String; // [80]
function ParseEncName: String; function ParseEncName: String;
var OldBuf: PChar;
begin begin
if not (buf[0] in ['A'..'Z', 'a'..'z']) then if not (buf[0] in ['A'..'Z', 'a'..'z']) then
RaiseExc('Expected character (A-Z, a-z)'); RaiseExc('Expected character (A-Z, a-z)');
Result := buf[0]; OldBuf := buf;
Inc(buf); Inc(buf);
Result := Result + GetString(['A'..'Z', 'a'..'z', '0'..'9', '.', '_', '-']); SkipString(['A'..'Z', 'a'..'z', '0'..'9', '.', '_', '-']);
Result := GetString(OldBuf,buf-OldBuf);
end; end;
begin begin
@ -966,14 +1016,14 @@ procedure TXMLReader.ResolveEntities(RootNode: TDOMNode);
if Assigned(NextSibling) and (NextSibling.NodeType = TEXT_NODE) then if Assigned(NextSibling) and (NextSibling.NodeType = TEXT_NODE) then
begin begin
TDOMCharacterData(PrevSibling).AppendData( TDOMCharacterData(PrevSibling).AppendData(
TDOMCharacterData(NextSibling).Data); TDOMCharacterData(NextSibling).Data);
RootNode.RemoveChild(NextSibling); RootNode.RemoveChild(NextSibling);
end end
end else end else
if Assigned(NextSibling) and (NextSibling.NodeType = TEXT_NODE) then if Assigned(NextSibling) and (NextSibling.NodeType = TEXT_NODE) then
begin begin
TDOMCharacterData(NextSibling).InsertData(0, Replacement); TDOMCharacterData(NextSibling).InsertData(0, Replacement);
RootNode.RemoveChild(EntityNode); RootNode.RemoveChild(EntityNode);
end else end else
RootNode.ReplaceChild(Doc.CreateTextNode(Replacement), EntityNode); RootNode.ReplaceChild(Doc.CreateTextNode(Replacement), EntityNode);
end; end;
@ -987,15 +1037,15 @@ begin
NextSibling := Node.NextSibling; NextSibling := Node.NextSibling;
if Node.NodeType = ENTITY_REFERENCE_NODE then if Node.NodeType = ENTITY_REFERENCE_NODE then
if Node.NodeName = 'amp' then if Node.NodeName = 'amp' then
ReplaceEntityRef(Node, '&') ReplaceEntityRef(Node, '&')
else if Node.NodeName = 'apos' then else if Node.NodeName = 'apos' then
ReplaceEntityRef(Node, '''') ReplaceEntityRef(Node, '''')
else if Node.NodeName = 'gt' then else if Node.NodeName = 'gt' then
ReplaceEntityRef(Node, '>') ReplaceEntityRef(Node, '>')
else if Node.NodeName = 'lt' then else if Node.NodeName = 'lt' then
ReplaceEntityRef(Node, '<') ReplaceEntityRef(Node, '<')
else if Node.NodeName = 'quot' then else if Node.NodeName = 'quot' then
ReplaceEntityRef(Node, '"'); ReplaceEntityRef(Node, '"');
Node := NextSibling; Node := NextSibling;
end; end;
end; end;
@ -1123,6 +1173,9 @@ end.
{ {
$Log$ $Log$
Revision 1.2 2002/07/30 14:36:28 lazarus
MG: accelerated xmlread and xmlwrite
Revision 1.1 2002/07/30 06:24:06 lazarus Revision 1.1 2002/07/30 06:24:06 lazarus
MG: added a faster version of TXMLConfig MG: added a faster version of TXMLConfig

View File

@ -83,7 +83,7 @@ end;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
type type
TOutputProc = procedure(s: String); TOutputProc = procedure(const Buffer; Count: Longint);
var var
f: ^Text; f: ^Text;
@ -91,30 +91,56 @@ var
wrt, wrtln: TOutputProc; wrt, wrtln: TOutputProc;
InsideTextNode: Boolean; InsideTextNode: Boolean;
procedure Text_Write(const Buffer; Count: Longint);
procedure Text_Write(s: String); var s: string;
begin begin
Write(f^, s); if Count>0 then begin
SetLength(s,Count);
System.Move(Buffer,s[1],Count);
Write(f^, s);
end;
end; end;
procedure Text_WriteLn(s: String); procedure Text_WriteLn(const Buffer; Count: Longint);
var s: string;
begin begin
WriteLn(f^, s); if Count>0 then begin
SetLength(s,Count);
System.Move(Buffer,s[1],Count);
WriteLn(f^, s);
end;
end; end;
procedure Stream_Write(s: String); procedure Stream_Write(const Buffer; Count: Longint);
begin begin
if Length(s) > 0 then if Count > 0 then
stream.Write(s[1], Length(s)); stream.Write(Buffer, Count);
end; end;
procedure Stream_WriteLn(s: String); procedure Stream_WriteLn(const Buffer; Count: Longint);
begin begin
if Length(s) > 0 then if Count > 0 then
stream.Write(s[1], Length(s)); stream.Write(Buffer, Count);
stream.WriteByte(10); stream.WriteByte(10);
end; end;
procedure wrtStr(s: string);
begin
if s<>'' then
wrt(s[1],length(s));
end;
procedure wrtStrLn(s: string);
begin
if s<>'' then
wrtln(s[1],length(s));
end;
procedure wrtChr(c: char);
begin
wrt(c,1);
end;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Indent handling // Indent handling
@ -160,36 +186,43 @@ begin
begin begin
if s[EndPos] in SpecialChars then if s[EndPos] in SpecialChars then
begin begin
wrt(Copy(s, StartPos, EndPos - StartPos)); wrt(s[StartPos],EndPos - StartPos);
SpecialCharCallback(s[EndPos]); SpecialCharCallback(s[EndPos]);
StartPos := EndPos + 1; StartPos := EndPos + 1;
end; end;
Inc(EndPos); Inc(EndPos);
end; end;
if EndPos > StartPos then if EndPos > StartPos then
wrt(Copy(s, StartPos, EndPos - StartPos)); wrt(s[StartPos], EndPos - StartPos);
end; end;
procedure AttrSpecialCharCallback(c: Char); procedure AttrSpecialCharCallback(c: Char);
const
QuotStr = '&quot;';
AmpStr = '&amp;';
begin begin
if c = '"' then if c = '"' then
wrt('&quot;') wrt(QuotStr, length(QuotStr))
else if c = '&' then else if c = '&' then
wrt('&amp;') wrt(AmpStr, length(AmpStr))
else else
wrt(c); wrt(c,1);
end; end;
procedure TextnodeSpecialCharCallback(c: Char); procedure TextnodeSpecialCharCallback(c: Char);
const
ltStr = '&lt;';
gtStr = '&gt;';
AmpStr = '&amp;';
begin begin
if c = '<' then if c = '<' then
wrt('&lt;') wrt(ltStr, length(ltStr))
else if c = '>' then else if c = '>' then
wrt('&gt;') wrt(gtStr, length(gtStr))
else if c = '&' then else if c = '&' then
wrt('&amp;') wrt(AmpStr, length(AmpStr))
else else
wrt(c); wrt(c,1);
end; end;
@ -205,31 +238,35 @@ var
s: String; s: String;
begin begin
if not InsideTextNode then if not InsideTextNode then
wrt(Indent); wrtStr(Indent);
wrt('<' + node.NodeName); wrtChr('<');
wrtStr(node.NodeName);
for i := 0 to node.Attributes.Length - 1 do for i := 0 to node.Attributes.Length - 1 do
begin begin
attr := node.Attributes.Item[i]; attr := node.Attributes.Item[i];
wrt(' ' + attr.NodeName + '='); wrtChr(' ');
wrtStr(attr.NodeName);
wrtChr('=');
s := attr.NodeValue; s := attr.NodeValue;
// !!!: Replace special characters in "s" such as '&', '<', '>' // !!!: Replace special characters in "s" such as '&', '<', '>'
wrt('"'); wrtChr('"');
ConvWrite(s, AttrSpecialChars, @AttrSpecialCharCallback); ConvWrite(s, AttrSpecialChars, @AttrSpecialCharCallback);
wrt('"'); wrtChr('"');
end; end;
Child := node.FirstChild; Child := node.FirstChild;
if Child = nil then if Child = nil then begin
if InsideTextNode then if InsideTextNode then begin
wrt('/>') wrtChr('/'); wrtChr('>');
else end else begin
wrtln('/>') wrtChr('/'); wrtln('>',1);
else end;
end else
begin begin
SavedInsideTextNode := InsideTextNode; SavedInsideTextNode := InsideTextNode;
if InsideTextNode or Child.InheritsFrom(TDOMText) then if InsideTextNode or Child.InheritsFrom(TDOMText) then
wrt('>') wrtChr('>')
else else
wrtln('>'); wrtln('>',1);
IncIndent; IncIndent;
repeat repeat
if Child.InheritsFrom(TDOMText) then if Child.InheritsFrom(TDOMText) then
@ -239,13 +276,15 @@ begin
until child = nil; until child = nil;
DecIndent; DecIndent;
if not InsideTextNode then if not InsideTextNode then
wrt(Indent); wrtStr(Indent);
InsideTextNode := SavedInsideTextNode; InsideTextNode := SavedInsideTextNode;
s := '</' + node.NodeName + '>'; wrtChr('<');
wrtChr('/');
wrtStr(node.NodeName);
if InsideTextNode then if InsideTextNode then
wrt(s) wrtChr('>')
else else
wrtln(s); wrtln('>',1);
end; end;
end; end;
@ -264,14 +303,16 @@ end;
procedure WriteCDATA(node: TDOMNode); procedure WriteCDATA(node: TDOMNode);
begin begin
if InsideTextNode then if InsideTextNode then
wrt('<![CDATA[' + node.NodeValue + ']]>') wrtStr('<![CDATA[' + node.NodeValue + ']]>')
else else
wrtln(Indent + '<![CDATA[' + node.NodeValue + ']]>') wrtStrln(Indent + '<![CDATA[' + node.NodeValue + ']]>')
end; end;
procedure WriteEntityRef(node: TDOMNode); procedure WriteEntityRef(node: TDOMNode);
begin begin
wrt('&' + node.NodeName + ';'); wrtChr('&');
wrtStr(node.NodeName);
wrtChr(';');
end; end;
procedure WriteEntity(node: TDOMNode); procedure WriteEntity(node: TDOMNode);
@ -281,23 +322,23 @@ begin
end; end;
procedure WritePI(node: TDOMNode); procedure WritePI(node: TDOMNode);
var
s: String;
begin begin
s := '<!' + TDOMProcessingInstruction(node).Target + ' ' + wrtChr('<'); wrtChr('!');
TDOMProcessingInstruction(node).Data + '>'; wrtStr(TDOMProcessingInstruction(node).Target);
if InsideTextNode then wrtChr(' ');
wrt(s) wrtStr(TDOMProcessingInstruction(node).Data);
else wrtChr('>');
wrtln(Indent + s); if not InsideTextNode then
wrtStrln('');
end; end;
procedure WriteComment(node: TDOMNode); procedure WriteComment(node: TDOMNode);
begin begin
if InsideTextNode then wrtStr('<!--');
wrt('<!--' + node.NodeValue + '-->') wrtStr(node.NodeValue);
else wrtStr('-->');
wrtln(Indent + '<!--' + node.NodeValue + '-->') if not InsideTextNode then
wrtStrln('');
end; end;
procedure WriteDocument(node: TDOMNode); procedure WriteDocument(node: TDOMNode);
@ -335,19 +376,19 @@ var
Child: TDOMNode; Child: TDOMNode;
begin begin
InitWriter; InitWriter;
wrt('<?xml version="'); wrtStr('<?xml version="');
if Length(doc.XMLVersion) > 0 then if Length(doc.XMLVersion) > 0 then
wrt(doc.XMLVersion) wrtStr(doc.XMLVersion)
else else
wrt('1.0'); wrtStr('1.0');
wrt('"'); wrtChr('"');
if Length(doc.Encoding) > 0 then if Length(doc.Encoding) > 0 then
wrt(' encoding="' + doc.Encoding + '"'); wrtStr(' encoding="' + doc.Encoding + '"');
wrtln('?>'); wrtStrln('?>');
if Length(doc.StylesheetType) > 0 then if Length(doc.StylesheetType) > 0 then
// !!!: Can't handle with HRefs which contain special chars (" and so on) // !!!: Can't handle with HRefs which contain special chars (" and so on)
wrtln(Format('<?xml-stylesheet type="%s" href="%s"?>', wrtStrln(Format('<?xml-stylesheet type="%s" href="%s"?>',
[doc.StylesheetType, doc.StylesheetHRef])); [doc.StylesheetType, doc.StylesheetHRef]));
indent := ''; indent := '';
@ -361,17 +402,30 @@ begin
end; end;
procedure WriteXMLMemStream(doc: TXMLDocument);
// internally used by the WriteXMLFile procedures
begin
Stream:=TMemoryStream.Create;
WriteXMLFile(doc,Stream);
Stream.Position:=0;
end;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Interface implementation // Interface implementation
// ------------------------------------------------------------------- // -------------------------------------------------------------------
procedure WriteXMLFile(doc: TXMLDocument; const AFileName: String); procedure WriteXMLFile(doc: TXMLDocument; const AFileName: String);
var fs: TFileStream;
begin begin
Stream := TFileStream.Create(AFileName, fmCreate); // write first to memory buffer and then as one whole block to file
wrt := @Stream_Write; WriteXMLMemStream(doc);
wrtln := @Stream_WriteLn; try
RootWriter(doc); fs := TFileStream.Create(AFileName, fmCreate);
Stream.Free; fs.CopyFrom(Stream,Stream.Size);
fs.Free;
finally
Stream.Free;
end;
end; end;
procedure WriteXMLFile(doc: TXMLDocument; var AFile: Text); procedure WriteXMLFile(doc: TXMLDocument; var AFile: Text);
@ -425,6 +479,9 @@ end.
{ {
$Log$ $Log$
Revision 1.2 2002/07/30 14:36:28 lazarus
MG: accelerated xmlread and xmlwrite
Revision 1.1 2002/07/30 06:24:06 lazarus Revision 1.1 2002/07/30 06:24:06 lazarus
MG: added a faster version of TXMLConfig MG: added a faster version of TXMLConfig