* xmlread.pp, implemented some c14n features: when parsing with Options.CanonicalForm=True, report all attributes as specified and drop superfluous namespace declaration attributes. Fixes level3/ls/canonicalform10 and level3/ls/canonicalform11.

git-svn-id: trunk@16253 -
This commit is contained in:
sergei 2010-10-29 03:36:55 +00:00
parent d96e17da77
commit b4aa087aad

View File

@ -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; tmp := chunk^.FNext;
{don't unlink chunks of default attributes, they are owned by DTD} chunk^.FNext := FFreeAttrChunk;
if not FNodeStack[FNesting+i].FIsDefault then FFreeAttrChunk := chunk;
while Assigned(chunk) do chunk := tmp;
begin
tmp := chunk^.FNext;
chunk^.FNext := FFreeAttrChunk;
FFreeAttrChunk := chunk;
chunk := tmp;
end;
FNodeStack[FNesting+i].FNext := nil;
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);