mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 03:49:19 +02:00
* fcl-xml, moved check for required attribute presence to ValidateCurrentNode
* improved wording of some validation errors - removed ExpectName function git-svn-id: trunk@20435 -
This commit is contained in:
parent
4a128cc006
commit
f44734d1bc
@ -98,6 +98,7 @@ type
|
|||||||
private
|
private
|
||||||
FAttrDefs: TFPList;
|
FAttrDefs: TFPList;
|
||||||
FNeedsDefaultPass: Boolean;
|
FNeedsDefaultPass: Boolean;
|
||||||
|
FHasRequiredAtts: Boolean;
|
||||||
function GetAttrDefCount: Integer;
|
function GetAttrDefCount: Integer;
|
||||||
function AttrDefByIndex(index: Integer): TAttributeDef;
|
function AttrDefByIndex(index: Integer): TAttributeDef;
|
||||||
public
|
public
|
||||||
@ -111,6 +112,7 @@ type
|
|||||||
property AttrDefCount: Integer read GetAttrDefCount;
|
property AttrDefCount: Integer read GetAttrDefCount;
|
||||||
property AttrDefs[index: Integer]: TAttributeDef read AttrDefByIndex;
|
property AttrDefs[index: Integer]: TAttributeDef read AttrDefByIndex;
|
||||||
property NeedsDefaultPass: Boolean read FNeedsDefaultPass;
|
property NeedsDefaultPass: Boolean read FNeedsDefaultPass;
|
||||||
|
property HasRequiredAtts: Boolean read FHasRequiredAtts;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TEntityDecl = class(TDTDObject)
|
TEntityDecl = class(TDTDObject)
|
||||||
@ -378,6 +380,8 @@ begin
|
|||||||
aDef.FIndex := FAttrDefs.Add(aDef);
|
aDef.FIndex := FAttrDefs.Add(aDef);
|
||||||
if aDef.Default in [adRequired, adDefault, adFixed] then
|
if aDef.Default in [adRequired, adDefault, adFixed] then
|
||||||
FNeedsDefaultPass := True;
|
FNeedsDefaultPass := True;
|
||||||
|
if aDef.Default = adRequired then
|
||||||
|
FHasRequiredAtts := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TAttributeDef }
|
{ TAttributeDef }
|
||||||
|
@ -328,7 +328,6 @@ type
|
|||||||
procedure AddForwardRef(Buf: PWideChar; Length: Integer);
|
procedure AddForwardRef(Buf: PWideChar; Length: Integer);
|
||||||
procedure ClearForwardRefs;
|
procedure ClearForwardRefs;
|
||||||
procedure ValidateIdRefs;
|
procedure ValidateIdRefs;
|
||||||
procedure StandaloneError(LineOffs: Integer = 0);
|
|
||||||
procedure CallErrorHandler(E: EXMLReadError);
|
procedure CallErrorHandler(E: EXMLReadError);
|
||||||
function FindOrCreateElDef: TElementDecl;
|
function FindOrCreateElDef: TElementDecl;
|
||||||
function SkipUntilSeq(const Delim: TSetOfChar; c1: WideChar): Boolean;
|
function SkipUntilSeq(const Delim: TSetOfChar; c1: WideChar): Boolean;
|
||||||
@ -372,7 +371,6 @@ type
|
|||||||
procedure RaiseNameNotFound;
|
procedure RaiseNameNotFound;
|
||||||
function CheckName(aFlags: TCheckNameFlags = []): Boolean;
|
function CheckName(aFlags: TCheckNameFlags = []): Boolean;
|
||||||
procedure CheckNCName;
|
procedure CheckNCName;
|
||||||
function ExpectName: XMLString; // [5]
|
|
||||||
function ParseLiteral(var ToFill: TWideCharBuf; aType: TLiteralType;
|
function ParseLiteral(var ToFill: TWideCharBuf; aType: TLiteralType;
|
||||||
Required: Boolean): Boolean;
|
Required: Boolean): Boolean;
|
||||||
procedure ExpectAttValue(attrData: PNodeData; NonCDATA: Boolean); // [10]
|
procedure ExpectAttValue(attrData: PNodeData; NonCDATA: Boolean); // [10]
|
||||||
@ -1451,12 +1449,6 @@ begin
|
|||||||
FatalError('Name starts with invalid character');
|
FatalError('Name starts with invalid character');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLTextReader.ExpectName: XMLString;
|
|
||||||
begin
|
|
||||||
CheckName;
|
|
||||||
SetString(Result, FName.Buffer, FName.Length);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TXMLTextReader.ResolvePredefined: Boolean;
|
function TXMLTextReader.ResolvePredefined: Boolean;
|
||||||
var
|
var
|
||||||
wc: WideChar;
|
wc: WideChar;
|
||||||
@ -2028,7 +2020,8 @@ begin
|
|||||||
FDTDProcessed := True; // assume success
|
FDTDProcessed := True; // assume success
|
||||||
FState := rsDTD;
|
FState := rsDTD;
|
||||||
|
|
||||||
FDocType.FName := ExpectName;
|
CheckName;
|
||||||
|
SetString(FDocType.FName, FName.Buffer, FName.Length);
|
||||||
SkipS(True);
|
SkipS(True);
|
||||||
ParseExternalID(FDocType.FSystemID, FDocType.FPublicID, False);
|
ParseExternalID(FDocType.FSystemID, FDocType.FPublicID, False);
|
||||||
SkipS;
|
SkipS;
|
||||||
@ -2092,11 +2085,6 @@ begin
|
|||||||
DoError(S, 'Parameter entities must be properly nested');
|
DoError(S, 'Parameter entities must be properly nested');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLTextReader.StandaloneError(LineOffs: Integer);
|
|
||||||
begin
|
|
||||||
ValidationError('Standalone constriant violation', [], LineOffs);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TXMLTextReader.ParseQuantity: TCPQuant;
|
function TXMLTextReader.ParseQuantity: TCPQuant;
|
||||||
begin
|
begin
|
||||||
case FSource.FBuf^ of
|
case FSource.FBuf^ of
|
||||||
@ -2249,8 +2237,9 @@ var
|
|||||||
NameStr, SysID, PubID: XMLString;
|
NameStr, SysID, PubID: XMLString;
|
||||||
begin
|
begin
|
||||||
ExpectWhitespace;
|
ExpectWhitespace;
|
||||||
NameStr := ExpectName;
|
CheckName;
|
||||||
CheckNCName;
|
CheckNCName;
|
||||||
|
SetString(NameStr, FName.Buffer, FName.Length);
|
||||||
ExpectWhitespace;
|
ExpectWhitespace;
|
||||||
if not ParseExternalID(SysID, PubID, True) then
|
if not ParseExternalID(SysID, PubID, True) then
|
||||||
FatalError('Expected external or public ID');
|
FatalError('Expected external or public ID');
|
||||||
@ -2457,8 +2446,9 @@ begin
|
|||||||
if FSource.Matches('NDATA') then
|
if FSource.Matches('NDATA') then
|
||||||
begin
|
begin
|
||||||
ExpectWhitespace;
|
ExpectWhitespace;
|
||||||
StoreLocation(FTokenStart);
|
StoreLocation(FTokenStart); { needed for AddForwardRef }
|
||||||
Entity.FNotationName := ExpectName;
|
CheckName;
|
||||||
|
SetString(Entity.FNotationName, FName.Buffer, FName.Length);
|
||||||
if FValidate then
|
if FValidate then
|
||||||
AddForwardRef(FName.Buffer, FName.Length);
|
AddForwardRef(FName.Buffer, FName.Length);
|
||||||
// SAX: DTDHandler.UnparsedEntityDecl(...);
|
// SAX: DTDHandler.UnparsedEntityDecl(...);
|
||||||
@ -2676,6 +2666,9 @@ begin
|
|||||||
|
|
||||||
PushVC(ElDef);
|
PushVC(ElDef);
|
||||||
|
|
||||||
|
if ElDef = nil then
|
||||||
|
Exit;
|
||||||
|
|
||||||
{ Validate attributes }
|
{ Validate attributes }
|
||||||
for i := 1 to FAttrCount do
|
for i := 1 to FAttrCount do
|
||||||
begin
|
begin
|
||||||
@ -2687,11 +2680,10 @@ begin
|
|||||||
else if ((AttDef.DataType <> dtCdata) or (AttDef.Default = adFixed)) then
|
else if ((AttDef.DataType <> dtCdata) or (AttDef.Default = adFixed)) then
|
||||||
begin
|
begin
|
||||||
if FStandalone and AttDef.ExternallyDeclared then
|
if FStandalone and AttDef.ExternallyDeclared then
|
||||||
{ TODO: perhaps should use different and more descriptive messages }
|
|
||||||
if attr^.FDenormalized then
|
if attr^.FDenormalized then
|
||||||
DoErrorPos(esError, 'Standalone constraint violation', attr^.FLoc2)
|
DoErrorPos(esError, 'In a standalone document, externally defined attribute cannot cause value normalization', attr^.FLoc2)
|
||||||
else if i > FSpecifiedAttrs then
|
else if i > FSpecifiedAttrs then
|
||||||
DoError(esError, 'Standalone constraint violation');
|
DoError(esError, 'In a standalone document, attribute cannot have a default value defined externally');
|
||||||
|
|
||||||
// TODO: what about normalization of AttDef.Value? (Currently it IS normalized)
|
// TODO: what about normalization of AttDef.Value? (Currently it IS normalized)
|
||||||
if (AttDef.Default = adFixed) and (AttDef.Data^.FValueStr <> attr^.FValueStr) then
|
if (AttDef.Default = adFixed) and (AttDef.Data^.FValueStr <> attr^.FValueStr) then
|
||||||
@ -2701,6 +2693,18 @@ begin
|
|||||||
ValidateAttrValue(AttDef, attr);
|
ValidateAttrValue(AttDef, attr);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Check presence of #REQUIRED attributes }
|
||||||
|
if ElDef.HasRequiredAtts then
|
||||||
|
for i := 0 to ElDef.AttrDefCount-1 do
|
||||||
|
begin
|
||||||
|
if FAttrDefIndex[i] = FAttrTag then
|
||||||
|
Continue;
|
||||||
|
AttDef := ElDef.AttrDefs[i];
|
||||||
|
if AttDef.Default = adRequired then
|
||||||
|
ValidationError('Required attribute ''%s'' of element ''%s'' is missing',
|
||||||
|
[AttDef.Data^.FQName^.Key, FCurrNode^.FQName^.Key], 0)
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ntEndElement:
|
ntEndElement:
|
||||||
@ -2719,7 +2723,7 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if FValidators[FValidatorNesting].FSaViolation then
|
if FValidators[FValidatorNesting].FSaViolation then
|
||||||
StandaloneError(-1);
|
ValidationError('Standalone constraint violation',[]);
|
||||||
FCurrNode^.FNodeType := ntWhitespace;
|
FCurrNode^.FNodeType := ntWhitespace;
|
||||||
end;
|
end;
|
||||||
ctEmpty:
|
ctEmpty:
|
||||||
@ -3428,10 +3432,9 @@ var
|
|||||||
begin
|
begin
|
||||||
for I := 0 to ElDef.AttrDefCount-1 do
|
for I := 0 to ElDef.AttrDefCount-1 do
|
||||||
begin
|
begin
|
||||||
AttDef := ElDef.AttrDefs[I];
|
if FAttrDefIndex[I] <> FAttrTag then // this one wasn't specified
|
||||||
|
|
||||||
if FAttrDefIndex[AttDef.Index] <> FAttrTag then // this one wasn't specified
|
|
||||||
begin
|
begin
|
||||||
|
AttDef := ElDef.AttrDefs[I];
|
||||||
case AttDef.Default of
|
case AttDef.Default of
|
||||||
adDefault, adFixed: begin
|
adDefault, adFixed: begin
|
||||||
attrData := AllocAttributeData;
|
attrData := AllocAttributeData;
|
||||||
@ -3456,9 +3459,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
adRequired:
|
|
||||||
ValidationError('Required attribute ''%s'' of element ''%s'' is missing',
|
|
||||||
[AttDef.Data^.FQName^.Key, FNodeStack[FNesting].FQName^.Key], 0)
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user