Browse Source

* Moved TDOMAttrDef class from xmlread.pp to dom.pp (in order to implement default attribute handling at DOM level).
* Using regular CloneNode() method to create copies of TDOMAttrDef.

git-svn-id: trunk@13176 -

sergei 16 years ago
parent
commit
17bbe72d08
2 changed files with 92 additions and 86 deletions
  1. 75 1
      packages/fcl-xml/src/dom.pp
  2. 17 85
      packages/fcl-xml/src/xmlread.pp

+ 75 - 1
packages/fcl-xml/src/dom.pp

@@ -97,6 +97,7 @@ type
   TDOMDocumentType = class;
   TDOMDocumentType = class;
   TDOMEntityReference = class;
   TDOMEntityReference = class;
   TDOMProcessingInstruction = class;
   TDOMProcessingInstruction = class;
+  TDOMAttrDef = class;
 
 
 
 
 // -------------------------------------------------------
 // -------------------------------------------------------
@@ -442,6 +443,7 @@ type
       TDOMProcessingInstruction; virtual;
       TDOMProcessingInstruction; virtual;
     function CreateAttribute(const name: DOMString): TDOMAttr;
     function CreateAttribute(const name: DOMString): TDOMAttr;
     function CreateAttributeBuf(Buf: DOMPChar; Length: Integer): TDOMAttr;
     function CreateAttributeBuf(Buf: DOMPChar; Length: Integer): TDOMAttr;
+    function CreateAttributeDef(Buf: DOMPChar; Length: Integer): TDOMAttrDef;
     function CreateEntityReference(const name: DOMString): TDOMEntityReference;
     function CreateEntityReference(const name: DOMString): TDOMEntityReference;
       virtual;
       virtual;
     function GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
     function GetElementsByTagName(const tagname: DOMString): TDOMNodeList;
@@ -527,7 +529,8 @@ type
     property Value: DOMString read GetNodeValue write SetNodeValue;
     property Value: DOMString read GetNodeValue write SetNodeValue;
     property OwnerElement: TDOMElement read FOwnerElement;
     property OwnerElement: TDOMElement read FOwnerElement;
     // extensions
     // extensions
-    property DataType: TAttrDataType read FDataType;
+    // TODO: this is to be replaced with DOM 3 TypeInfo
+    property DataType: TAttrDataType read FDataType write FDataType;
   end;
   end;
 
 
 
 
@@ -706,6 +709,31 @@ type
     property Data: DOMString read FNodeValue write SetNodeValue;
     property Data: DOMString read FNodeValue write SetNodeValue;
   end;
   end;
 
 
+// Attribute declaration - Attr descendant which carries rudimentary type info
+// must be severely improved while developing Level 3
+
+  TAttrDefault = (
+    adImplied,
+    adDefault,
+    adRequired,
+    adFixed
+  );
+
+  TDOMAttrDef = class(TDOMAttr)
+  protected
+    FExternallyDeclared: Boolean;
+    FDefault: TAttrDefault;
+    FTag: Cardinal;
+    FEnumeration: array of DOMString;
+  public
+    function AddEnumToken(Buf: DOMPChar; Len: Integer): Boolean;
+    function HasEnumToken(const aValue: DOMString): Boolean;
+    function CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode; overload; override;
+    property Default: TAttrDefault read FDefault write FDefault;
+    property ExternallyDeclared: Boolean read FExternallyDeclared write FExternallyDeclared;
+    property Tag: Cardinal read FTag write FTag;
+  end;
+
 // URIs of predefined namespaces
 // URIs of predefined namespaces
 const
 const
   stduri_xml: DOMString = 'http://www.w3.org/XML/1998/namespace';
   stduri_xml: DOMString = 'http://www.w3.org/XML/1998/namespace';
@@ -1939,6 +1967,12 @@ begin
   Include(Result.FFlags, nfSpecified);
   Include(Result.FFlags, nfSpecified);
 end;
 end;
 
 
+function TDOMDocument.CreateAttributeDef(Buf: DOMPChar; Length: Integer): TDOMAttrDef;
+begin
+  Result := TDOMAttrDef.Create(Self);
+  Result.FNSI.QName := FNames.FindOrAdd(Buf, Length);
+end;
+
 function TDOMDocument.CreateEntityReference(const name: DOMString):
 function TDOMDocument.CreateEntityReference(const name: DOMString):
   TDOMEntityReference;
   TDOMEntityReference;
 begin
 begin
@@ -2593,4 +2627,44 @@ begin
   FNodeValue := AValue;
   FNodeValue := AValue;
 end;
 end;
 
 
+{ TDOMAttrDef }
+
+function TDOMAttrDef.CloneNode(deep: Boolean; ACloneOwner: TDOMDocument): TDOMNode;
+begin
+  Result := inherited CloneNode(deep, ACloneOwner);
+  Exclude(Result.FFlags, nfSpecified);
+end;
+
+function TDOMAttrDef.AddEnumToken(Buf: DOMPChar; Len: Integer): Boolean;
+var
+  I, L: Integer;
+begin
+  // TODO: this implementaion is the slowest possible...
+  Result := False;
+  L := Length(FEnumeration);
+  for I := 0 to L-1 do
+  begin
+    if CompareDomStrings(Buf, DOMPChar(FEnumeration[I]), Len, Length(FEnumeration[I])) = 0 then
+      Exit;
+  end;
+  SetLength(FEnumeration, L+1);
+  SetString(FEnumeration[L], Buf, Len);
+  Result := True;
+end;
+
+function TDOMAttrDef.HasEnumToken(const aValue: DOMString): Boolean;
+var
+  I: Integer;
+begin
+  Result := True;
+  if Length(FEnumeration) = 0 then
+    Exit;
+  for I := 0 to Length(FEnumeration)-1 do
+  begin
+    if FEnumeration[I] = aValue then
+      Exit;
+  end;
+  Result := False;
+end;
+
 end.
 end.

+ 17 - 85
packages/fcl-xml/src/xmlread.pp

@@ -146,7 +146,6 @@ type
   TDOMNotationEx = class(TDOMNotation);
   TDOMNotationEx = class(TDOMNotation);
   TDOMDocumentTypeEx = class(TDOMDocumentType);
   TDOMDocumentTypeEx = class(TDOMDocumentType);
   TDOMElementDef = class;
   TDOMElementDef = class;
-  TDOMAttrDef = class;
 
 
   TDTDSubsetType = (dsNone, dsInternal, dsExternal);
   TDTDSubsetType = (dsNone, dsInternal, dsExternal);
 
 
@@ -289,13 +288,6 @@ type
 
 
   TXMLReadState = (rsProlog, rsDTD, rsRoot, rsEpilog);
   TXMLReadState = (rsProlog, rsDTD, rsRoot, rsEpilog);
 
 
-  TAttrDefault = (
-    adImplied,
-    adDefault,
-    adRequired,
-    adFixed
-  );
-
   TElementContentType = (
   TElementContentType = (
     ctAny,
     ctAny,
     ctEmpty,
     ctEmpty,
@@ -437,20 +429,6 @@ type
 
 
   // Attribute/Element declarations
   // Attribute/Element declarations
 
 
-  TDOMAttrDef = class(TDOMAttr)
-  private
-    FTag: Cardinal;
-  protected
-    FExternallyDeclared: Boolean;
-    FDefault: TAttrDefault;
-    FEnumeration: array of WideString;
-    function AddEnumToken(Buf: DOMPChar; Len: Integer): Boolean;
-    function HasEnumToken(const aValue: WideString): Boolean;
-    function Clone(AElement: TDOMElement): TDOMAttr;
-  public
-    property Tag: Cardinal read FTag write FTag;
-  end;
-
   TDOMElementDef = class(TDOMElement)
   TDOMElementDef = class(TDOMElement)
   public
   public
     FExternallyDeclared: Boolean;
     FExternallyDeclared: Boolean;
@@ -2329,10 +2307,9 @@ begin
   begin
   begin
     CheckName;
     CheckName;
     ExpectWhitespace;
     ExpectWhitespace;
-    AttDef := TDOMAttrDef.Create(doc);
+    AttDef := doc.CreateAttributeDef(FName.Buffer, FName.Length);
     try
     try
-      AttDef.FExternallyDeclared := FSource.DTDSubsetType <> dsInternal;
-      AttDef.FNSI.QName := doc.Names.FindOrAdd(FName.Buffer, FName.Length);
+      AttDef.ExternallyDeclared := FSource.DTDSubsetType <> dsInternal;
 // In case of duplicate declaration of the same attribute, we must discard it,
 // In case of duplicate declaration of the same attribute, we must discard it,
 // not modifying ElDef, and suppressing certain validation errors.
 // not modifying ElDef, and suppressing certain validation errors.
       DiscardIt := Assigned(ElDef.GetAttributeNode(AttDef.Name));
       DiscardIt := Assigned(ElDef.GetAttributeNode(AttDef.Name));
@@ -2341,7 +2318,7 @@ begin
 
 
       if CheckForChar('(') then     // [59]
       if CheckForChar('(') then     // [59]
       begin
       begin
-        AttDef.FDataType := dtNmToken;
+        AttDef.DataType := dtNmToken;
         repeat
         repeat
           SkipWhitespace;
           SkipWhitespace;
           CheckName([cnToken]);
           CheckName([cnToken]);
@@ -2364,7 +2341,7 @@ begin
         end;
         end;
         if Found and SkipWhitespace then
         if Found and SkipWhitespace then
         begin
         begin
-          AttDef.FDataType := dt;
+          AttDef.DataType := dt;
           if (dt = dtId) and not DiscardIt then
           if (dt = dtId) and not DiscardIt then
           begin
           begin
             if Assigned(ElDef.IDAttr) then
             if Assigned(ElDef.IDAttr) then
@@ -2406,18 +2383,18 @@ begin
       end;
       end;
       StoreLocation(FTokenStart);
       StoreLocation(FTokenStart);
       if FSource.Matches('#REQUIRED') then
       if FSource.Matches('#REQUIRED') then
-        AttDef.FDefault := adRequired
+        AttDef.Default := adRequired
       else if FSource.Matches('#IMPLIED') then
       else if FSource.Matches('#IMPLIED') then
-        AttDef.FDefault := adImplied
+        AttDef.Default := adImplied
       else if FSource.Matches('#FIXED') then
       else if FSource.Matches('#FIXED') then
       begin
       begin
-        AttDef.FDefault := adFixed;
+        AttDef.Default := adFixed;
         ExpectWhitespace;
         ExpectWhitespace;
       end
       end
       else
       else
-        AttDef.FDefault := adDefault;
+        AttDef.Default := adDefault;
 
 
-      if AttDef.FDefault in [adDefault, adFixed] then
+      if AttDef.Default in [adDefault, adFixed] then
       begin
       begin
         if AttDef.DataType = dtId then
         if AttDef.DataType = dtId then
           ValidationError('An attribute of type ID cannot have a default value',[]);
           ValidationError('An attribute of type ID cannot have a default value',[]);
@@ -2950,21 +2927,21 @@ procedure CheckValue;
 var
 var
   AttValue, OldValue: WideString;
   AttValue, OldValue: WideString;
 begin
 begin
-  if FStandalone and AttDef.FExternallyDeclared then
+  if FStandalone and AttDef.ExternallyDeclared then
   begin
   begin
     OldValue := Attr.Value;
     OldValue := Attr.Value;
-    TDOMAttrDef(Attr).FDataType := AttDef.FDataType;
+    Attr.DataType := AttDef.DataType;
     AttValue := Attr.Value;
     AttValue := Attr.Value;
     if AttValue <> OldValue then
     if AttValue <> OldValue then
       StandaloneError(-1);
       StandaloneError(-1);
   end
   end
   else
   else
   begin
   begin
-    TDOMAttrDef(Attr).FDataType := AttDef.FDataType;
+    Attr.DataType := AttDef.DataType;
     AttValue := Attr.Value;
     AttValue := Attr.Value;
   end;
   end;
   // TODO: what about normalization of AttDef.Value? (Currently it IS normalized)
   // TODO: what about normalization of AttDef.Value? (Currently it IS normalized)
-  if (AttDef.FDefault = adFixed) and (AttDef.Value <> AttValue) then
+  if (AttDef.Default = adFixed) and (AttDef.Value <> AttValue) then
     ValidationError('Value of attribute ''%s'' does not match its #FIXED default',[AttDef.Name], -1);
     ValidationError('Value of attribute ''%s'' does not match its #FIXED default',[AttDef.Name], -1);
   if not ValidateAttrSyntax(AttDef, AttValue) then
   if not ValidateAttrSyntax(AttDef, AttValue) then
     ValidationError('Attribute ''%s'' type mismatch', [AttDef.Name], -1);
     ValidationError('Attribute ''%s'' type mismatch', [AttDef.Name], -1);
@@ -2997,7 +2974,7 @@ begin
   FCursor := attr;
   FCursor := attr;
   ExpectAttValue;
   ExpectAttValue;
 
 
-  if Assigned(AttDef) and ((AttDef.FDataType <> dtCdata) or (AttDef.FDefault = adFixed)) then
+  if Assigned(AttDef) and ((AttDef.DataType <> dtCdata) or (AttDef.Default = adFixed)) then
     CheckValue;
     CheckValue;
 end;
 end;
 
 
@@ -3049,11 +3026,11 @@ begin
 
 
     if AttDef.Tag <> FAttrTag then  // this one wasn't specified
     if AttDef.Tag <> FAttrTag then  // this one wasn't specified
     begin
     begin
-      case AttDef.FDefault of
+      case AttDef.Default of
         adDefault, adFixed: begin
         adDefault, adFixed: begin
-          if FStandalone and AttDef.FExternallyDeclared then
+          if FStandalone and AttDef.ExternallyDeclared then
             StandaloneError;
             StandaloneError;
-          Attr := AttDef.Clone(Element);
+          Attr := TDOMAttr(AttDef.CloneNode(True));
           Element.SetAttributeNode(Attr);
           Element.SetAttributeNode(Attr);
           ValidateAttrValue(Attr, Attr.Value);
           ValidateAttrValue(Attr, Attr.Value);
         end;
         end;
@@ -3273,51 +3250,6 @@ begin
   end;
   end;
 end;
 end;
 
 
-{ TDOMAttrDef }
-
-function TDOMAttrDef.AddEnumToken(Buf: DOMPChar; Len: Integer): Boolean;
-var
-  I, L: Integer;
-begin
-  // TODO: this implementaion is the slowest possible...
-  Result := False;
-  L := Length(FEnumeration);
-  for I := 0 to L-1 do
-  begin
-    if (Len = Length(FEnumeration[I])) and CompareMem(Buf, DOMPChar(FEnumeration[I]), Len*sizeof(WideChar)) then
-      Exit;
-  end;
-  SetLength(FEnumeration, L+1);
-  SetString(FEnumeration[L], Buf, Len);
-  Result := True;
-end;
-
-function TDOMAttrDef.HasEnumToken(const aValue: WideString): Boolean;
-var
-  I: Integer;
-begin
-  Result := True;
-  if Length(FEnumeration) = 0 then
-    Exit;
-  for I := 0 to Length(FEnumeration)-1 do
-  begin
-    if FEnumeration[I] = aValue then
-      Exit;
-  end;
-  Result := False;
-end;
-
-type
-  TDOMAttrEx = class(TDOMAttr);
-
-function TDOMAttrDef.Clone(AElement: TDOMElement): TDOMAttr;
-begin
-  Result := TDOMAttr.Create(FOwnerDocument);
-  TDOMAttrEx(Result).FNSI.QName := Self.FNSI.QName;
-  TDOMAttrEx(Result).FDataType := FDataType;
-  CloneChildren(Result, FOwnerDocument);
-end;
-
 { TElementValidator }
 { TElementValidator }
 
 
 function TElementValidator.IsElementAllowed(Def: TDOMElementDef): Boolean;
 function TElementValidator.IsElementAllowed(Def: TDOMElementDef): Boolean;