Browse Source

* fcl-xml, track attribute definition tags in reader instead of DTD. Removes need for multiple parsers processing documents based on the same DTD to keep their attribute tag counters in sync.

git-svn-id: trunk@20429 -
sergei 13 years ago
parent
commit
ede4da62cb
2 changed files with 23 additions and 12 deletions
  1. 3 3
      packages/fcl-xml/src/dtdmodel.pp
  2. 20 9
      packages/fcl-xml/src/xmlread.pp

+ 3 - 3
packages/fcl-xml/src/dtdmodel.pp

@@ -71,7 +71,7 @@ type
     FData: PNodeData;
     FDataType: TAttrDataType;
     FDefault: TAttrDefault;
-    FTag: Cardinal;
+    FIndex: Cardinal;
     FIsNamespaceDecl: Boolean;
     FEnumeration: array of XMLString;
   public
@@ -82,7 +82,7 @@ type
     property Data: PNodeData read FData;
     property Default: TAttrDefault read FDefault write FDefault;
     property DataType: TAttrDataType read FDataType write FDataType;
-    property Tag: Cardinal read FTag write FTag;
+    property Index: Cardinal read FIndex;
     property IsNamespaceDecl: Boolean read FIsNamespaceDecl;
   end;
 
@@ -375,7 +375,7 @@ procedure TElementDecl.AddAttrDef(aDef: TAttributeDef);
 begin
   if FAttrDefs = nil then
     FAttrDefs := TFPList.Create;
-  FAttrDefs.Add(aDef);
+  aDef.FIndex := FAttrDefs.Add(aDef);
   if aDef.Default in [adRequired, adDefault, adFixed] then
     FNeedsDefaultPass := True;
 end;

+ 20 - 9
packages/fcl-xml/src/xmlread.pp

@@ -293,6 +293,7 @@ type
     FNext: TXMLToken;
     FCurrEntity: TEntityDecl;
     FIDMap: THashTable;
+    FAttrDefIndex: array of Cardinal;
 
     FNSHelper: TNSSupport;
     FNsAttHash: TDblHashArray;
@@ -2625,7 +2626,6 @@ begin
     Exit;
   InnerReader := TXMLTextReader.Create(FCtrl);
   try
-    InnerReader.FAttrTag := FAttrTag;
     InnerReader.FDocType := FDocType.Reference;
     EntityToSource(AEntity, Src);
     Ent.SetReadOnly(False);
@@ -2633,7 +2633,6 @@ begin
       InnerReader.ProcessFragment(Src, Ent);
     AEntity.FResolved := True;
   finally
-    FAttrTag := InnerReader.FAttrTag;
     InnerReader.Free;
     AEntity.FOnStack := False;
     Ent.SetReadOnly(True);
@@ -3208,14 +3207,25 @@ var
   IsEmpty: Boolean;
   ElName: PHashItem;
   b: TBinding;
+  Len: Integer;
 begin
-  // we're about to process a new set of attributes
-  Inc(FAttrTag);
-
-  // Get hash entry for element name
   ElName := FNameTable.FindOrAdd(FName.Buffer, FName.Length);
-  // Find declaration for this element
   ElDef := TElementDecl(ElName^.Data);
+  if Assigned(ElDef) then
+    Len := ElDef.AttrDefCount+8  { overallocate a bit }
+  else
+    Len := 0;
+  // (re)initialize array of attribute definition tags
+  if (Len-8 > Length(FAttrDefIndex)) or (FAttrTag = 0) then
+  begin
+    SetLength(FAttrDefIndex, Len);
+    for Len := 0 to High(FAttrDefIndex) do
+      FAttrDefIndex[Len] := FAttrTag;
+  end;
+  // we're about to process a new set of attributes
+{$push}{$r-,q-}
+  Dec(FAttrTag);
+{$pop}
 
   IsEmpty := False;
   FAttrCount := 0;
@@ -3334,8 +3344,9 @@ begin
   if Assigned(ElDef) then
   begin
     AttDef := ElDef.GetAttrDef(attrName);
+    // mark attribute as specified
     if Assigned(AttDef) then
-      AttDef.Tag := FAttrTag;  // indicates that this one is specified
+      FAttrDefIndex[AttDef.Index] := FAttrTag;
   end
   else
     AttDef := nil;
@@ -3419,7 +3430,7 @@ begin
   begin
     AttDef := ElDef.AttrDefs[I];
 
-    if AttDef.Tag <> FAttrTag then  // this one wasn't specified
+    if FAttrDefIndex[AttDef.Index] <> FAttrTag then  // this one wasn't specified
     begin
       case AttDef.Default of
         adDefault, adFixed: begin