Hallo.
Ich habe hier ein kleines Verständnisproblem, warum folgender Code extrem langsam wird, wenn es viele (
XML) Unterelemente gibt:
Delphi-Quellcode:
function TXmlDocument.Content:
string;
const
CrLf = #13#10;
Idnt = #32#32;
{ Expand }
function Expand(
const Str, Indent:
string;
const Elements: TXmlElements):
string;
var
i: Integer;
Content:
string;
SmartEnd: Boolean;
begin
Result := Str;
for i := 0
to Elements.Count - 1
do
begin
Result := Result + Indent + '
<' + Elements[i].
Name;
Content := Trim(Elements[i].Content);
SmartEnd :=
not((Content <> '
')
or (Elements[i].Elements.Count > 0));
if not(SmartEnd)
then
Result := Result + '
>' + Content;
if Elements[i].Elements.Count > 0
then
Result := Expand(Result + CrLf, Indent + Idnt, Elements[i].Elements) + Indent;
if not(SmartEnd)
then
Result := Result + Format('
</%s>', [Elements[i].
Name])
else
Result := Result + '
/>';
Result := Result + CrLf;
end;
end;
begin
Result := '
<?xml version="1.0" encoding="utf-8" ?>' + #13#10 + Expand('
', '
', Elements);
end;
Hierbei handelt es sich um eine kleine Routine, die rekursiv alle
Xml-Elemente durchgeht und einen String
mit dem kompletten Inhalt zurückliefert. Bei einem Baum von 100 Knoten mit jeweils 50 Unterknoten braucht die
Routine auf meinem Rechner stolze 18 Sekunden.
Schritt1: String durch AnsiString ersetzen
Da ich derzeit sowie keine
Unicode Xml-Dateien unterstütze und brauche, spare ich mir die ganzen Umwandlungen
und ersetze String durch AnsiString:
Delphi-Quellcode:
function TXmlDocument.Content: AnsiString;
const
CrLf: AnsiString = #13#10;
Idnt: AnsiString = #32#32;
{ Expand }
function Expand(
const Str, Indent: AnsiString;
const Elements: TXmlElements): AnsiString;
var
i: Integer;
Content: AnsiString;
SmartEnd: Boolean;
begin
Result := Str;
for i := 0
to Elements.Count - 1
do
begin
Result := Result + Indent + '
<' + AnsiString(Elements[i].
Name);
Content := AnsiString(Trim(Elements[i].Content));
SmartEnd :=
not((Content <> '
')
or (Elements[i].Elements.Count > 0));
if not(SmartEnd)
then
Result := Result + '
>' + Content;
if Elements[i].Elements.Count > 0
then
Result := Expand(Result + CrLf, Indent + Idnt, Elements[i].Elements) + Indent;
if not(SmartEnd)
then
Result := Result + AnsiString(Format('
</%s>', [Elements[i].
Name]))
else
Result := Result + '
/>';
Result := Result + CrLf;
end;
end;
begin
Result := '
<?xml version="1.0" encoding="utf-8" ?>' + #13#10 + Expand('
', '
', Elements);
end;
Somit komme ich von ~18 Sekunden runter auf ~8 Sekunden. Nun habe ich aber folgendes Phänomen, das ich
nicht so ganz erklären kann:
Ersetze ich die beiden Konstanten am Anfang des Codes durch:
Delphi-Quellcode:
const
CrLf: '';
Idnt: '';
Werden aus den ~8 Sekunden schlanke 0,75 Sekunden (und aus den urspünglichen 18 Sekunden für
Unicode etwa 4!).
WARUM???
Was kann ich tun, um trotzdem CarriageReturn/Linefeeds und Spaces in meiner Ausgabe zu erhalten, ohne das die
Geschwindigkeit wieder zusammenbricht?
Vielen Dank & Gruß,
kaju