mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-13 09:59:08 +02:00
* fcl-xml, improved TNSSupport class to work directly with hashed strings, reduces amount of hash lookups.
git-svn-id: trunk@20538 -
This commit is contained in:
parent
0cbdc1ae6e
commit
60fe15b01a
@ -1409,7 +1409,7 @@ begin
|
|||||||
FCurrAttrIndex := -1;
|
FCurrAttrIndex := -1;
|
||||||
if FNamespaces then
|
if FNamespaces then
|
||||||
begin
|
begin
|
||||||
FNSHelper := TNSSupport.Create;
|
FNSHelper := TNSSupport.Create(FNameTable);
|
||||||
FNsAttHash := TDblHashArray.Create;
|
FNsAttHash := TDblHashArray.Create;
|
||||||
FStdPrefix_xml := FNSHelper.GetPrefix(@PrefixDefault, 3);
|
FStdPrefix_xml := FNSHelper.GetPrefix(@PrefixDefault, 3);
|
||||||
FStdPrefix_xmlns := FNSHelper.GetPrefix(@PrefixDefault, 5);
|
FStdPrefix_xmlns := FNSHelper.GetPrefix(@PrefixDefault, 5);
|
||||||
@ -2946,18 +2946,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLTextReader.LookupNamespace(const APrefix: XMLString): XMLString;
|
function TXMLTextReader.LookupNamespace(const APrefix: XMLString): XMLString;
|
||||||
var
|
|
||||||
prefixatom: PHashItem;
|
|
||||||
b: TBinding;
|
|
||||||
begin
|
begin
|
||||||
result := '';
|
if Assigned(FNSHelper) then
|
||||||
if FNamespaces then
|
result := FNSHelper.LookupNamespace(APrefix)
|
||||||
begin
|
else
|
||||||
prefixatom := FNSHelper.GetPrefix(PWideChar(APrefix),Length(APrefix));
|
result := '';
|
||||||
b := TBinding(prefixatom^.Data);
|
|
||||||
if Assigned(b) then
|
|
||||||
result := b.Uri;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLTextReader.MoveToFirstAttribute: Boolean;
|
function TXMLTextReader.MoveToFirstAttribute: Boolean;
|
||||||
@ -3739,7 +3732,7 @@ begin
|
|||||||
|
|
||||||
if FNamespaces then
|
if FNamespaces then
|
||||||
begin
|
begin
|
||||||
FNSHelper.StartElement;
|
FNSHelper.PushScope;
|
||||||
if FColonPos > 0 then
|
if FColonPos > 0 then
|
||||||
FCurrNode^.FPrefix := FNSHelper.GetPrefix(FName.Buffer, FColonPos);
|
FCurrNode^.FPrefix := FNSHelper.GetPrefix(FName.Buffer, FColonPos);
|
||||||
end;
|
end;
|
||||||
@ -3774,15 +3767,15 @@ begin
|
|||||||
if Assigned(FCurrNode^.FPrefix) then
|
if Assigned(FCurrNode^.FPrefix) then
|
||||||
begin
|
begin
|
||||||
b := TBinding(FCurrNode^.FPrefix^.Data);
|
b := TBinding(FCurrNode^.FPrefix^.Data);
|
||||||
if not (Assigned(b) and (b.uri <> '')) then
|
if not (Assigned(b) and Assigned(b.uri) and (b.uri^.Key <> '')) then
|
||||||
DoErrorPos(esFatal, 'Unbound element name prefix "%s"', [FCurrNode^.FPrefix^.Key],FCurrNode^.FLoc);
|
DoErrorPos(esFatal, 'Unbound element name prefix "%s"', [FCurrNode^.FPrefix^.Key],FCurrNode^.FLoc);
|
||||||
FCurrNode^.FNsUri := FNameTable.FindOrAdd(b.uri);
|
FCurrNode^.FNsUri := b.uri;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
b := FNSHelper.DefaultNSBinding;
|
b := FNSHelper.DefaultNSBinding;
|
||||||
if Assigned(b) then
|
if Assigned(b) then
|
||||||
FCurrNode^.FNsUri := FNameTable.FindOrAdd(b.uri);
|
FCurrNode^.FNsUri := b.uri;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3990,9 +3983,9 @@ begin
|
|||||||
if (attrData^.FValueStr = '') and not (FXML11 or (Pfx^.Key = '')) then
|
if (attrData^.FValueStr = '') and not (FXML11 or (Pfx^.Key = '')) then
|
||||||
DoErrorPos(esFatal, 'Illegal undefining of namespace', attrData^.FLoc2);
|
DoErrorPos(esFatal, 'Illegal undefining of namespace', attrData^.FLoc2);
|
||||||
|
|
||||||
Result := (Pfx^.Data = nil) or (TBinding(Pfx^.Data).uri <> attrData^.FValueStr);
|
Result := (Pfx^.Data = nil) or (TBinding(Pfx^.Data).uri <> nsUri);
|
||||||
if Result then
|
if Result then
|
||||||
FNSHelper.BindPrefix(attrData^.FValueStr, Pfx);
|
FNSHelper.BindPrefix(nsUri, Pfx);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLTextReader.ProcessNamespaceAtts;
|
procedure TXMLTextReader.ProcessNamespaceAtts;
|
||||||
@ -4011,17 +4004,17 @@ begin
|
|||||||
|
|
||||||
Pfx := attrData^.FPrefix;
|
Pfx := attrData^.FPrefix;
|
||||||
b := TBinding(Pfx^.Data);
|
b := TBinding(Pfx^.Data);
|
||||||
if not (Assigned(b) and (b.uri <> '')) then
|
if not (Assigned(b) and Assigned (b.uri) and (b.uri^.Key <> '')) then
|
||||||
DoErrorPos(esFatal, 'Unbound attribute name prefix "%s"', [Pfx^.Key], attrData^.FLoc);
|
DoErrorPos(esFatal, 'Unbound attribute name prefix "%s"', [Pfx^.Key], attrData^.FLoc);
|
||||||
|
|
||||||
{ detect duplicates }
|
{ detect duplicates }
|
||||||
J := attrData^.FColonPos+1;
|
J := attrData^.FColonPos+1;
|
||||||
AttrName := attrData^.FQName;
|
AttrName := attrData^.FQName;
|
||||||
|
|
||||||
if FNsAttHash.Locate(@b.uri, @AttrName^.Key[J], Length(AttrName^.Key) - J+1) then
|
if FNsAttHash.Locate(b.uri, @AttrName^.Key[J], Length(AttrName^.Key) - J+1) then
|
||||||
DoErrorPos(esFatal, 'Duplicate prefixed attribute', attrData^.FLoc);
|
DoErrorPos(esFatal, 'Duplicate prefixed attribute', attrData^.FLoc);
|
||||||
|
|
||||||
attrData^.FNsUri := FNameTable.FindOrAdd(b.uri);
|
attrData^.FNsUri := b.uri;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -4256,7 +4249,7 @@ end;
|
|||||||
procedure TXMLTextReader.PopElement;
|
procedure TXMLTextReader.PopElement;
|
||||||
begin
|
begin
|
||||||
if FNamespaces then
|
if FNamespaces then
|
||||||
FNSHelper.EndElement;
|
FNSHelper.PopScope;
|
||||||
|
|
||||||
if (FNesting = 0) and (not FFragmentMode) then
|
if (FNesting = 0) and (not FFragmentMode) then
|
||||||
FState := rsEpilog;
|
FState := rsEpilog;
|
||||||
|
@ -123,7 +123,7 @@ type
|
|||||||
TExpHashEntry = record
|
TExpHashEntry = record
|
||||||
rev: LongWord;
|
rev: LongWord;
|
||||||
hash: LongWord;
|
hash: LongWord;
|
||||||
uriPtr: PXMLString;
|
uriPtr: Pointer;
|
||||||
lname: PWideChar;
|
lname: PWideChar;
|
||||||
lnameLen: Integer;
|
lnameLen: Integer;
|
||||||
end;
|
end;
|
||||||
@ -137,7 +137,7 @@ type
|
|||||||
FData: PExpHashEntryArray;
|
FData: PExpHashEntryArray;
|
||||||
public
|
public
|
||||||
procedure Init(NumSlots: Integer);
|
procedure Init(NumSlots: Integer);
|
||||||
function Locate(uri: PXMLString; localName: PWideChar; localLength: Integer): Boolean;
|
function Locate(uri: Pointer; localName: PWideChar; localLength: Integer): Boolean;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ type
|
|||||||
|
|
||||||
TBinding = class
|
TBinding = class
|
||||||
public
|
public
|
||||||
uri: XMLString;
|
uri: PHashItem;
|
||||||
next: TBinding;
|
next: TBinding;
|
||||||
prevPrefixBinding: TObject;
|
prevPrefixBinding: TObject;
|
||||||
Prefix: PHashItem;
|
Prefix: PHashItem;
|
||||||
@ -196,6 +196,7 @@ type
|
|||||||
|
|
||||||
TNSSupport = class(TObject)
|
TNSSupport = class(TObject)
|
||||||
private
|
private
|
||||||
|
FNameTable: THashTable;
|
||||||
FNesting: Integer;
|
FNesting: Integer;
|
||||||
FPrefixSeqNo: Integer;
|
FPrefixSeqNo: Integer;
|
||||||
FFreeBindings: TBinding;
|
FFreeBindings: TBinding;
|
||||||
@ -204,17 +205,17 @@ type
|
|||||||
FPrefixes: THashTable;
|
FPrefixes: THashTable;
|
||||||
FDefaultPrefix: THashItem;
|
FDefaultPrefix: THashItem;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create(aNameTable: THashTable);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure DefineBinding(const Prefix, nsURI: XMLString; out Binding: TBinding);
|
procedure DefineBinding(const Prefix, nsURI: XMLString; out Binding: TBinding);
|
||||||
function CheckAttribute(const Prefix, nsURI: XMLString;
|
function CheckAttribute(const Prefix, nsURI: XMLString;
|
||||||
out Binding: TBinding): TAttributeAction;
|
out Binding: TBinding): TAttributeAction;
|
||||||
function IsPrefixBound(P: PWideChar; Len: Integer; out Prefix: PHashItem): Boolean;
|
|
||||||
function GetPrefix(P: PWideChar; Len: Integer): PHashItem;
|
function GetPrefix(P: PWideChar; Len: Integer): PHashItem;
|
||||||
function BindPrefix(const nsURI: XMLString; aPrefix: PHashItem): TBinding;
|
function BindPrefix(nsURI, aPrefix: PHashItem): TBinding;
|
||||||
function DefaultNSBinding: TBinding;
|
function DefaultNSBinding: TBinding;
|
||||||
procedure StartElement;
|
function LookupNamespace(const APrefix: XMLString): XMLString;
|
||||||
procedure EndElement;
|
procedure PushScope;
|
||||||
|
function PopScope: Boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Buffer builder, used to compose long strings without too much memory allocations }
|
{ Buffer builder, used to compose long strings without too much memory allocations }
|
||||||
@ -685,15 +686,14 @@ begin
|
|||||||
Dec(FRevision);
|
Dec(FRevision);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDblHashArray.Locate(uri: PXMLString; localName: PWideChar; localLength: Integer): Boolean;
|
function TDblHashArray.Locate(uri: Pointer; localName: PWideChar; localLength: Integer): Boolean;
|
||||||
var
|
var
|
||||||
step: Byte;
|
step: Byte;
|
||||||
mask: LongWord;
|
mask: LongWord;
|
||||||
idx: Integer;
|
idx: Integer;
|
||||||
HashValue: LongWord;
|
HashValue: LongWord;
|
||||||
begin
|
begin
|
||||||
HashValue := Hash(0, PWideChar(uri^), Length(uri^));
|
HashValue := Hash(PtrUInt(uri), localName, localLength);
|
||||||
HashValue := Hash(HashValue, localName, localLength);
|
|
||||||
|
|
||||||
mask := (1 shl FSizeLog) - 1;
|
mask := (1 shl FSizeLog) - 1;
|
||||||
step := (HashValue and (not mask)) shr (FSizeLog-1) and (mask shr 2) or 1;
|
step := (HashValue and (not mask)) shr (FSizeLog-1) and (mask shr 2) or 1;
|
||||||
@ -701,7 +701,7 @@ begin
|
|||||||
result := True;
|
result := True;
|
||||||
while FData^[idx].rev = FRevision do
|
while FData^[idx].rev = FRevision do
|
||||||
begin
|
begin
|
||||||
if (HashValue = FData^[idx].hash) and (FData^[idx].uriPtr^ = uri^) and
|
if (HashValue = FData^[idx].hash) and (FData^[idx].uriPtr = uri) and
|
||||||
(FData^[idx].lnameLen = localLength) and
|
(FData^[idx].lnameLen = localLength) and
|
||||||
CompareMem(FData^[idx].lname, localName, localLength * sizeof(WideChar)) then
|
CompareMem(FData^[idx].lname, localName, localLength * sizeof(WideChar)) then
|
||||||
Exit;
|
Exit;
|
||||||
@ -723,11 +723,12 @@ end;
|
|||||||
|
|
||||||
{ TNSSupport }
|
{ TNSSupport }
|
||||||
|
|
||||||
constructor TNSSupport.Create;
|
constructor TNSSupport.Create(aNameTable: THashTable);
|
||||||
var
|
var
|
||||||
b: TBinding;
|
b: TBinding;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
FNameTable := aNameTable;
|
||||||
FPrefixes := THashTable.Create(16, False);
|
FPrefixes := THashTable.Create(16, False);
|
||||||
FBindings := TFPList.Create;
|
FBindings := TFPList.Create;
|
||||||
SetLength(FBindingStack, 16);
|
SetLength(FBindingStack, 16);
|
||||||
@ -747,7 +748,7 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TNSSupport.BindPrefix(const nsURI: XMLString; aPrefix: PHashItem): TBinding;
|
function TNSSupport.BindPrefix(nsURI, aPrefix: PHashItem): TBinding;
|
||||||
begin
|
begin
|
||||||
{ try to reuse an existing binding }
|
{ try to reuse an existing binding }
|
||||||
result := FFreeBindings;
|
result := FFreeBindings;
|
||||||
@ -778,13 +779,14 @@ end;
|
|||||||
procedure TNSSupport.DefineBinding(const Prefix, nsURI: XMLString;
|
procedure TNSSupport.DefineBinding(const Prefix, nsURI: XMLString;
|
||||||
out Binding: TBinding);
|
out Binding: TBinding);
|
||||||
var
|
var
|
||||||
Pfx: PHashItem;
|
Pfx, uri: PHashItem;
|
||||||
begin
|
begin
|
||||||
Pfx := @FDefaultPrefix;
|
Pfx := @FDefaultPrefix;
|
||||||
if (nsURI <> '') and (Prefix <> '') then
|
if (nsURI <> '') and (Prefix <> '') then
|
||||||
Pfx := FPrefixes.FindOrAdd(PWideChar(Prefix), Length(Prefix));
|
Pfx := FPrefixes.FindOrAdd(PWideChar(Prefix), Length(Prefix));
|
||||||
if (Pfx^.Data = nil) or (TBinding(Pfx^.Data).uri <> nsURI) then
|
uri := FNameTable.FindOrAdd(PWideChar(nsURI),Length(nsURI));
|
||||||
Binding := BindPrefix(nsURI, Pfx)
|
if (Pfx^.Data = nil) or (TBinding(Pfx^.Data).uri <> uri) then
|
||||||
|
Binding := BindPrefix(uri, Pfx)
|
||||||
else
|
else
|
||||||
Binding := nil;
|
Binding := nil;
|
||||||
end;
|
end;
|
||||||
@ -797,6 +799,7 @@ var
|
|||||||
b: TBinding;
|
b: TBinding;
|
||||||
buf: array[0..31] of WideChar;
|
buf: array[0..31] of WideChar;
|
||||||
p: PWideChar;
|
p: PWideChar;
|
||||||
|
uri: PHashItem;
|
||||||
begin
|
begin
|
||||||
Binding := nil;
|
Binding := nil;
|
||||||
Pfx := nil;
|
Pfx := nil;
|
||||||
@ -805,8 +808,9 @@ begin
|
|||||||
Pfx := FPrefixes.FindOrAdd(PWideChar(Prefix), Length(Prefix))
|
Pfx := FPrefixes.FindOrAdd(PWideChar(Prefix), Length(Prefix))
|
||||||
else if nsURI = '' then
|
else if nsURI = '' then
|
||||||
Exit;
|
Exit;
|
||||||
|
uri := FNameTable.FindOrAdd(PWideChar(nsURI), Length(nsURI));
|
||||||
{ if the prefix is already bound to correct URI, we're done }
|
{ if the prefix is already bound to correct URI, we're done }
|
||||||
if Assigned(Pfx) and Assigned(Pfx^.Data) and (TBinding(Pfx^.Data).uri = nsURI) then
|
if Assigned(Pfx) and Assigned(Pfx^.Data) and (TBinding(Pfx^.Data).uri = uri) then
|
||||||
Exit;
|
Exit;
|
||||||
|
|
||||||
{ see if there's another prefix bound to the target URI }
|
{ see if there's another prefix bound to the target URI }
|
||||||
@ -816,7 +820,7 @@ begin
|
|||||||
b := FBindingStack[i];
|
b := FBindingStack[i];
|
||||||
while Assigned(b) do
|
while Assigned(b) do
|
||||||
begin
|
begin
|
||||||
if (b.uri = nsURI) and (b.Prefix <> @FDefaultPrefix) then
|
if (b.uri = uri) and (b.Prefix <> @FDefaultPrefix) then
|
||||||
begin
|
begin
|
||||||
Binding := b; // found one -> override the attribute's prefix
|
Binding := b; // found one -> override the attribute's prefix
|
||||||
Result := aaPrefix;
|
Result := aaPrefix;
|
||||||
@ -841,17 +845,10 @@ begin
|
|||||||
p^ := 'N';
|
p^ := 'N';
|
||||||
Pfx := FPrefixes.FindOrAdd(p, @Buf[high(Buf)]-p+1);
|
Pfx := FPrefixes.FindOrAdd(p, @Buf[high(Buf)]-p+1);
|
||||||
until Pfx^.Data = nil;
|
until Pfx^.Data = nil;
|
||||||
Binding := BindPrefix(nsURI, Pfx);
|
Binding := BindPrefix(uri, Pfx);
|
||||||
Result := aaBoth;
|
Result := aaBoth;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TNSSupport.IsPrefixBound(P: PWideChar; Len: Integer; out
|
|
||||||
Prefix: PHashItem): Boolean;
|
|
||||||
begin
|
|
||||||
Prefix := FPrefixes.FindOrAdd(P, Len);
|
|
||||||
Result := Assigned(Prefix^.Data) and (TBinding(Prefix^.Data).uri <> '');
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TNSSupport.GetPrefix(P: PWideChar; Len: Integer): PHashItem;
|
function TNSSupport.GetPrefix(P: PWideChar; Len: Integer): PHashItem;
|
||||||
begin
|
begin
|
||||||
if Assigned(P) and (Len > 0) then
|
if Assigned(P) and (Len > 0) then
|
||||||
@ -860,17 +857,34 @@ begin
|
|||||||
Result := @FDefaultPrefix;
|
Result := @FDefaultPrefix;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TNSSupport.StartElement;
|
function TNSSupport.LookupNamespace(const APrefix: XMLString): XMLString;
|
||||||
|
var
|
||||||
|
prefixatom: PHashItem;
|
||||||
|
b: TBinding;
|
||||||
|
begin
|
||||||
|
prefixatom := GetPrefix(PWideChar(APrefix),Length(APrefix));
|
||||||
|
b := TBinding(prefixatom^.Data);
|
||||||
|
if Assigned(b) and Assigned(b.Uri) then
|
||||||
|
result := b.Uri^.Key
|
||||||
|
else
|
||||||
|
result := '';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TNSSupport.PushScope;
|
||||||
begin
|
begin
|
||||||
Inc(FNesting);
|
Inc(FNesting);
|
||||||
if FNesting >= Length(FBindingStack) then
|
if FNesting >= Length(FBindingStack) then
|
||||||
SetLength(FBindingStack, FNesting * 2);
|
SetLength(FBindingStack, FNesting * 2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TNSSupport.EndElement;
|
function TNSSupport.PopScope: Boolean;
|
||||||
var
|
var
|
||||||
b, temp: TBinding;
|
b, temp: TBinding;
|
||||||
begin
|
begin
|
||||||
|
{ don't unbind prefixes declared before the first call to PushScope }
|
||||||
|
Result := FNesting > 0;
|
||||||
|
if not Result then
|
||||||
|
Exit;
|
||||||
temp := FBindingStack[FNesting];
|
temp := FBindingStack[FNesting];
|
||||||
while Assigned(temp) do
|
while Assigned(temp) do
|
||||||
begin
|
begin
|
||||||
@ -881,8 +895,7 @@ begin
|
|||||||
b.Prefix^.Data := b.prevPrefixBinding;
|
b.Prefix^.Data := b.prevPrefixBinding;
|
||||||
end;
|
end;
|
||||||
FBindingStack[FNesting] := nil;
|
FBindingStack[FNesting] := nil;
|
||||||
if FNesting > 0 then
|
Dec(FNesting);
|
||||||
Dec(FNesting);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Buffer builder utils }
|
{ Buffer builder utils }
|
||||||
|
@ -90,7 +90,7 @@ type
|
|||||||
procedure VisitDocumentType(Node: TDOMNode);
|
procedure VisitDocumentType(Node: TDOMNode);
|
||||||
procedure VisitPI(Node: TDOMNode);
|
procedure VisitPI(Node: TDOMNode);
|
||||||
public
|
public
|
||||||
constructor Create(AStream: TStream);
|
constructor Create(AStream: TStream; ANameTable: THashTable);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ const
|
|||||||
ltStr = '<';
|
ltStr = '<';
|
||||||
gtStr = '>';
|
gtStr = '>';
|
||||||
|
|
||||||
constructor TXMLWriter.Create(AStream: TStream);
|
constructor TXMLWriter.Create(AStream: TStream; ANameTable: THashTable);
|
||||||
var
|
var
|
||||||
I: Integer;
|
I: Integer;
|
||||||
begin
|
begin
|
||||||
@ -165,7 +165,7 @@ begin
|
|||||||
FIndent[2] := ' ';
|
FIndent[2] := ' ';
|
||||||
for I := 3 to 100 do FIndent[I] := ' ';
|
for I := 3 to 100 do FIndent[I] := ' ';
|
||||||
FIndentCount := 0;
|
FIndentCount := 0;
|
||||||
FNSHelper := TNSSupport.Create;
|
FNSHelper := TNSSupport.Create(ANameTable);
|
||||||
FScratch := TFPList.Create;
|
FScratch := TFPList.Create;
|
||||||
FNSDefs := TFPList.Create;
|
FNSDefs := TFPList.Create;
|
||||||
FAttrFixups := TFPList.Create;
|
FAttrFixups := TFPList.Create;
|
||||||
@ -426,7 +426,8 @@ begin
|
|||||||
wrtStr(B.Prefix^.Key);
|
wrtStr(B.Prefix^.Key);
|
||||||
end;
|
end;
|
||||||
wrtChars('="', 2);
|
wrtChars('="', 2);
|
||||||
ConvWrite(B.uri, AttrSpecialChars, @AttrSpecialCharCallback);
|
if Assigned(B.uri) then
|
||||||
|
ConvWrite(B.uri^.Key, AttrSpecialChars, @AttrSpecialCharCallback);
|
||||||
wrtChr('"');
|
wrtChr('"');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -575,7 +576,7 @@ var
|
|||||||
begin
|
begin
|
||||||
if not FInsideTextNode then
|
if not FInsideTextNode then
|
||||||
wrtIndent;
|
wrtIndent;
|
||||||
FNSHelper.StartElement;
|
FNSHelper.PushScope;
|
||||||
wrtChr('<');
|
wrtChr('<');
|
||||||
wrtStr(TDOMElement(node).TagName);
|
wrtStr(TDOMElement(node).TagName);
|
||||||
|
|
||||||
@ -611,7 +612,7 @@ begin
|
|||||||
wrtStr(TDOMElement(Node).TagName);
|
wrtStr(TDOMElement(Node).TagName);
|
||||||
wrtChr('>');
|
wrtChr('>');
|
||||||
end;
|
end;
|
||||||
FNSHelper.EndElement;
|
FNSHelper.PopScope;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLWriter.VisitText(node: TDOMNode);
|
procedure TXMLWriter.VisitText(node: TDOMNode);
|
||||||
@ -825,7 +826,7 @@ var
|
|||||||
begin
|
begin
|
||||||
s := TTextStream.Create(AFile);
|
s := TTextStream.Create(AFile);
|
||||||
try
|
try
|
||||||
with TXMLWriter.Create(s) do
|
with TXMLWriter.Create(s, doc.Names) do
|
||||||
try
|
try
|
||||||
WriteNode(doc);
|
WriteNode(doc);
|
||||||
finally
|
finally
|
||||||
@ -838,7 +839,7 @@ end;
|
|||||||
|
|
||||||
procedure WriteXMLFile(doc: TXMLDocument; AStream: TStream);
|
procedure WriteXMLFile(doc: TXMLDocument; AStream: TStream);
|
||||||
begin
|
begin
|
||||||
with TXMLWriter.Create(AStream) do
|
with TXMLWriter.Create(AStream, doc.Names) do
|
||||||
try
|
try
|
||||||
WriteNode(doc);
|
WriteNode(doc);
|
||||||
finally
|
finally
|
||||||
|
Loading…
Reference in New Issue
Block a user