|
@@ -348,13 +348,15 @@ type
|
|
function AllocNodeData(AIndex: Integer): PNodeData;
|
|
function AllocNodeData(AIndex: Integer): PNodeData;
|
|
function AllocAttributeData(AName: PHashItem): PNodeData;
|
|
function AllocAttributeData(AName: PHashItem): PNodeData;
|
|
function AllocAttributeValueChunk(APrev: PNodeData): PNodeData;
|
|
function AllocAttributeValueChunk(APrev: PNodeData): PNodeData;
|
|
- procedure CleanupAttributeData;
|
|
|
|
|
|
+ procedure CleanupAttribute(aNode: PNodeData);
|
|
|
|
+ procedure CleanupAttributes;
|
|
procedure SetNodeInfoWithValue(typ: TXMLNodeType; AName: PHashItem = nil);
|
|
procedure SetNodeInfoWithValue(typ: TXMLNodeType; AName: PHashItem = nil);
|
|
protected
|
|
protected
|
|
FNesting: Integer;
|
|
FNesting: Integer;
|
|
FCurrNode: PNodeData;
|
|
FCurrNode: PNodeData;
|
|
FAttrCount: Integer;
|
|
FAttrCount: Integer;
|
|
FPrefixedAttrs: Integer;
|
|
FPrefixedAttrs: Integer;
|
|
|
|
+ FSpecifiedAttrs: Integer;
|
|
FNodeStack: TNodeDataDynArray;
|
|
FNodeStack: TNodeDataDynArray;
|
|
FCursorStack: TDOMNodeDynArray;
|
|
FCursorStack: TDOMNodeDynArray;
|
|
FValidators: TValidatorDynArray;
|
|
FValidators: TValidatorDynArray;
|
|
@@ -413,7 +415,7 @@ type
|
|
function ResolveEntity(const ASystemID, APublicID, ABaseURI: WideString; out Source: TXMLCharSource): Boolean;
|
|
function ResolveEntity(const ASystemID, APublicID, ABaseURI: WideString; out Source: TXMLCharSource): Boolean;
|
|
procedure ProcessDefaultAttributes(ElDef: TElementDecl);
|
|
procedure ProcessDefaultAttributes(ElDef: TElementDecl);
|
|
procedure ProcessNamespaceAtts;
|
|
procedure ProcessNamespaceAtts;
|
|
- procedure AddBinding(attrData: PNodeData);
|
|
|
|
|
|
+ function AddBinding(attrData: PNodeData): Boolean;
|
|
|
|
|
|
procedure PushVC(aElDef: TElementDecl);
|
|
procedure PushVC(aElDef: TElementDecl);
|
|
procedure PopVC;
|
|
procedure PopVC;
|
|
@@ -2765,7 +2767,7 @@ begin
|
|
FToken := xtEndElement;
|
|
FToken := xtEndElement;
|
|
FCurrNode^.FNodeType := ntEndElement;
|
|
FCurrNode^.FNodeType := ntEndElement;
|
|
if FAttrCleanupFlag then
|
|
if FAttrCleanupFlag then
|
|
- CleanupAttributeData;
|
|
|
|
|
|
+ CleanupAttributes;
|
|
FAttrCount := 0;
|
|
FAttrCount := 0;
|
|
Result := True;
|
|
Result := True;
|
|
Exit;
|
|
Exit;
|
|
@@ -2773,7 +2775,7 @@ begin
|
|
if FNext = xtPushElement then
|
|
if FNext = xtPushElement then
|
|
begin
|
|
begin
|
|
if FAttrCleanupFlag then
|
|
if FAttrCleanupFlag then
|
|
- CleanupAttributeData;
|
|
|
|
|
|
+ CleanupAttributes;
|
|
FAttrCount := 0;
|
|
FAttrCount := 0;
|
|
FNext := xtText;
|
|
FNext := xtText;
|
|
end
|
|
end
|
|
@@ -2977,6 +2979,7 @@ begin
|
|
IsEmpty := False;
|
|
IsEmpty := False;
|
|
FAttrCount := 0;
|
|
FAttrCount := 0;
|
|
FPrefixedAttrs := 0;
|
|
FPrefixedAttrs := 0;
|
|
|
|
+ FSpecifiedAttrs := 0;
|
|
PushVC(ElDef); // this increases FNesting
|
|
PushVC(ElDef); // this increases FNesting
|
|
FCursorStack[FNesting] := NewElem;
|
|
FCursorStack[FNesting] := NewElem;
|
|
|
|
|
|
@@ -3118,6 +3121,7 @@ begin
|
|
attrData^.FColonPos := FColonPos;
|
|
attrData^.FColonPos := FColonPos;
|
|
StoreLocation(attrData^.FLoc);
|
|
StoreLocation(attrData^.FLoc);
|
|
Dec(attrData^.FLoc.LinePos, FName.Length);
|
|
Dec(attrData^.FLoc.LinePos, FName.Length);
|
|
|
|
+ FSpecifiedAttrs := FAttrCount;
|
|
|
|
|
|
if Assigned(ElDef) then
|
|
if Assigned(ElDef) then
|
|
begin
|
|
begin
|
|
@@ -3166,7 +3170,14 @@ begin
|
|
CheckValue;
|
|
CheckValue;
|
|
end;
|
|
end;
|
|
if Assigned(attrData^.FNsUri) then
|
|
if Assigned(attrData^.FNsUri) then
|
|
- AddBinding(attrData);
|
|
|
|
|
|
+ begin
|
|
|
|
+ if (not AddBinding(attrData)) and FCanonical then
|
|
|
|
+ begin
|
|
|
|
+ CleanupAttribute(attrData);
|
|
|
|
+ Dec(FAttrCount);
|
|
|
|
+ Dec(FSpecifiedAttrs);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TXMLReader.AddForwardRef(aList: TFPList; Buf: PWideChar; Length: Integer);
|
|
procedure TXMLReader.AddForwardRef(aList: TFPList; Buf: PWideChar; Length: Integer);
|
|
@@ -3217,6 +3228,8 @@ begin
|
|
StandaloneError;
|
|
StandaloneError;
|
|
attrData := AllocAttributeData(nil);
|
|
attrData := AllocAttributeData(nil);
|
|
attrData^ := AttDef.Data^;
|
|
attrData^ := AttDef.Data^;
|
|
|
|
+ if FCanonical then
|
|
|
|
+ attrData^.FIsDefault := False;
|
|
|
|
|
|
if FNamespaces then
|
|
if FNamespaces then
|
|
begin
|
|
begin
|
|
@@ -3225,7 +3238,8 @@ begin
|
|
if attrData^.FColonPos > 0 then
|
|
if attrData^.FColonPos > 0 then
|
|
attrData^.FPrefix := FStdPrefix_xmlns;
|
|
attrData^.FPrefix := FStdPrefix_xmlns;
|
|
attrData^.FNsUri := FStdUri_xmlns;
|
|
attrData^.FNsUri := FStdUri_xmlns;
|
|
- AddBinding(attrData);
|
|
|
|
|
|
+ if (not AddBinding(attrData)) and FCanonical then
|
|
|
|
+ Dec(FAttrCount);
|
|
end
|
|
end
|
|
else if attrData^.FColonPos > 0 then
|
|
else if attrData^.FColonPos > 0 then
|
|
begin
|
|
begin
|
|
@@ -3243,7 +3257,7 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
-procedure TXMLReader.AddBinding(attrData: PNodeData);
|
|
|
|
|
|
+function TXMLReader.AddBinding(attrData: PNodeData): Boolean;
|
|
var
|
|
var
|
|
nsUri, Pfx: PHashItem;
|
|
nsUri, Pfx: PHashItem;
|
|
begin
|
|
begin
|
|
@@ -3266,7 +3280,9 @@ begin
|
|
if (attrData^.FValueStr = '') and not (FXML11 or (Pfx^.Key = '')) then
|
|
if (attrData^.FValueStr = '') and not (FXML11 or (Pfx^.Key = '')) then
|
|
FatalError('Illegal undefining of namespace'); { position - ? }
|
|
FatalError('Illegal undefining of namespace'); { position - ? }
|
|
|
|
|
|
- FNSHelper.BindPrefix(attrData^.FValueStr, Pfx);
|
|
|
|
|
|
+ Result := (Pfx^.Data = nil) or (TBinding(Pfx^.Data).uri <> attrData^.FValueStr);
|
|
|
|
+ if Result then
|
|
|
|
+ FNSHelper.BindPrefix(attrData^.FValueStr, Pfx);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TXMLReader.ProcessNamespaceAtts;
|
|
procedure TXMLReader.ProcessNamespaceAtts;
|
|
@@ -3539,26 +3555,29 @@ begin
|
|
APrev^.FNext := result;
|
|
APrev^.FNext := result;
|
|
end;
|
|
end;
|
|
|
|
|
|
-procedure TXMLReader.CleanupAttributeData;
|
|
|
|
|
|
+procedure TXMLReader.CleanupAttributes;
|
|
var
|
|
var
|
|
i: Integer;
|
|
i: Integer;
|
|
|
|
+begin
|
|
|
|
+ {cleanup only specified attributes; default ones are owned by DTD}
|
|
|
|
+ for i := 1 to FSpecifiedAttrs do
|
|
|
|
+ CleanupAttribute(@FNodeStack[FNesting+i]);
|
|
|
|
+ FAttrCleanupFlag := False;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TXMLReader.CleanupAttribute(aNode: PNodeData);
|
|
|
|
+var
|
|
chunk, tmp: PNodeData;
|
|
chunk, tmp: PNodeData;
|
|
begin
|
|
begin
|
|
- for i := 1 to FAttrCount do
|
|
|
|
|
|
+ chunk := aNode^.FNext;
|
|
|
|
+ while Assigned(chunk) do
|
|
begin
|
|
begin
|
|
- chunk := FNodeStack[FNesting+i].FNext;
|
|
|
|
- {don't unlink chunks of default attributes, they are owned by DTD}
|
|
|
|
- if not FNodeStack[FNesting+i].FIsDefault then
|
|
|
|
- while Assigned(chunk) do
|
|
|
|
- begin
|
|
|
|
- tmp := chunk^.FNext;
|
|
|
|
- chunk^.FNext := FFreeAttrChunk;
|
|
|
|
- FFreeAttrChunk := chunk;
|
|
|
|
- chunk := tmp;
|
|
|
|
- end;
|
|
|
|
- FNodeStack[FNesting+i].FNext := nil;
|
|
|
|
|
|
+ tmp := chunk^.FNext;
|
|
|
|
+ chunk^.FNext := FFreeAttrChunk;
|
|
|
|
+ FFreeAttrChunk := chunk;
|
|
|
|
+ chunk := tmp;
|
|
end;
|
|
end;
|
|
- FAttrCleanupFlag := False;
|
|
|
|
|
|
+ aNode^.FNext := nil;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TXMLReader.SetNodeInfoWithValue(typ: TXMLNodeType; AName: PHashItem = nil);
|
|
procedure TXMLReader.SetNodeInfoWithValue(typ: TXMLNodeType; AName: PHashItem = nil);
|