diff options
| author | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2011-02-22 13:14:31 +0000 |
|---|---|---|
| committer | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2011-02-22 13:14:31 +0000 |
| commit | a05d9f0f2d832d8c0ec8621dd1abe4d4f969fbcd (patch) | |
| tree | ae052e0186758ed372568d36d766d663861ac502 /packages/fcl-xml | |
| parent | 45ffaa2a45e0f874ea30608137d9a29d951d803f (diff) | |
| download | fpc-a05d9f0f2d832d8c0ec8621dd1abe4d4f969fbcd.tar.gz | |
* xmlread.pp: split handling of node and validation stacks. Validation stack is now maintained only in validation mode.
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@16973 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/fcl-xml')
| -rw-r--r-- | packages/fcl-xml/src/xmlread.pp | 101 |
1 files changed, 47 insertions, 54 deletions
diff --git a/packages/fcl-xml/src/xmlread.pp b/packages/fcl-xml/src/xmlread.pp index 20b3862db1..b3a225a48b 100644 --- a/packages/fcl-xml/src/xmlread.pp +++ b/packages/fcl-xml/src/xmlread.pp @@ -249,6 +249,8 @@ type FElementDef: TElementDecl; FCurCP: TContentParticle; FFailed: Boolean; + FSaViolation: Boolean; + FContentType: TElementContentType; // =ctAny when FElementDef is nil function IsElementAllowed(Def: TElementDecl): Boolean; function Incomplete: Boolean; end; @@ -284,8 +286,6 @@ type FDocType: TDTDModel; FPEMap: THashTable; FForwardRefs: TFPList; - FCurrContentType: TElementContentType; - FSaViolation: Boolean; FDTDStartPos: PWideChar; FIntSubset: TWideCharBuf; FAttrTag: Cardinal; @@ -347,6 +347,7 @@ type FPrefixedAttrs: Integer; FSpecifiedAttrs: Integer; FNodeStack: TNodeDataDynArray; + FValidatorNesting: Integer; FValidators: TValidatorDynArray; FAttrChunks: TFPList; FFreeAttrChunk: PNodeData; @@ -413,7 +414,6 @@ type procedure PushVC(aElDef: TElementDecl); procedure PopVC; - procedure UpdateConstraints; procedure ValidateDTD; procedure ValidateCurrentNode; procedure ValidationError(const Msg: string; const args: array of const; LineOffs: Integer = -1); @@ -1316,6 +1316,7 @@ begin FNameTable := doc.Names; FState := rsProlog; FNesting := 0; + FValidatorNesting := 0; FCurrNode := @FNodeStack[0]; FFragmentMode := False; NSPrepare; @@ -1344,6 +1345,7 @@ begin FNameTable := doc.Names; FState := rsRoot; FNesting := 0; + FValidatorNesting := 0; FCurrNode := @FNodeStack[0]; FFragmentMode := True; FXML11 := doc.InheritsFrom(TXMLDocument) and (TXMLDocument(doc).XMLVersion = '1.1'); @@ -2673,7 +2675,6 @@ begin case FCurrNode^.FNodeType of ntElement: begin - { TODO: pushing *validation* context must be moved here } if (FNesting = 1) and (not FFragmentMode) then begin if Assigned(FDocType) then @@ -2688,9 +2689,11 @@ begin if (ElDef = nil) or (ElDef.ContentType = ctUndeclared) then DoErrorPos(esError, 'Using undeclared element ''%s''',[FCurrNode^.FQName^.Key], FCurrNode^.FLoc); - if not FValidators[FNesting-1].IsElementAllowed(ElDef) then + if not FValidators[FValidatorNesting].IsElementAllowed(ElDef) then DoErrorPos(esError, 'Element ''%s'' is not allowed in this context',[FCurrNode^.FQName^.Key], FCurrNode^.FLoc); + PushVC(ElDef); + { Validate attributes } for i := 1 to FAttrCount do begin @@ -2720,32 +2723,37 @@ begin ntEndElement: begin - if FValidators[FNesting].Incomplete then + if FValidators[FValidatorNesting].Incomplete then ValidationError('Element ''%s'' is missing required sub-elements', [FCurrNode^.FQName^.Key], -1); + if FValidatorNesting > 0 then + Dec(FValidatorNesting); end; - ntText, ntWhitespace: - case FCurrContentType of + ntText, ntSignificantWhitespace: + case FValidators[FValidatorNesting].FContentType of ctChildren: if FCurrNode^.FNodeType = ntText then ValidationError('Character data is not allowed in element-only content',[]) else - if FSaViolation then + begin + if FValidators[FValidatorNesting].FSaViolation then StandaloneError(-1); + FCurrNode^.FNodeType := ntWhitespace; + end; ctEmpty: ValidationError('Character data is not allowed in EMPTY elements', []); end; ntCDATA: - if FCurrContentType = ctChildren then + if FValidators[FValidatorNesting].FContentType = ctChildren then ValidationError('CDATA sections are not allowed in element-only content',[]); ntProcessingInstruction: - if FCurrContentType = ctEmpty then + if FValidators[FValidatorNesting].FContentType = ctEmpty then ValidationError('Processing instructions are not allowed within EMPTY elements', []); ntComment: - if FCurrContentType = ctEmpty then + if FValidators[FValidatorNesting].FContentType = ctEmpty then ValidationError('Comments are not allowed within EMPTY elements', []); ntDocumentType: @@ -2765,12 +2773,12 @@ end; procedure TXMLReader.HandleEntityEnd; begin - FValidators[FNesting-1] := FValidators[FNesting]; ContextPop(True); - PopVC; + if FNesting > 0 then Dec(FNesting); FCurrNode := @FNodeStack[FNesting+1]; FCurrNode^.FNodeType := ntEndEntity; // TODO: other properties of FCurrNode + FNext := xtText; end; procedure TXMLReader.ResolveEntity; @@ -2787,7 +2795,8 @@ procedure TXMLReader.DoStartEntity; var src: TXMLCharSource; begin - PushVC(nil); + Inc(FNesting); + FCurrNode := AllocNodeData(FNesting); if Assigned(FCurrEntity) then ContextPush(FCurrEntity) else @@ -2797,10 +2806,6 @@ begin src.Kind := skManualPop; Initialize(src); end; - - { Compensate for an extra entry in node stack } - FValidators[FNesting] := FValidators[FNesting-1]; - UpdateConstraints; FNext := xtText; end; @@ -2873,7 +2878,7 @@ const ); textNodeTypes: array[Boolean] of TXMLNodeType = ( - ntWhitespace, + ntSignificantWhitespace, ntText ); @@ -2892,9 +2897,9 @@ begin ntText: cursor.InternalAppend(doc.CreateTextNodeBuf(FValue.Buffer, FValue.Length, False)); - ntWhitespace: + ntWhitespace, ntSignificantWhitespace: if FPreserveWhitespace then - cursor.InternalAppend(doc.CreateTextNodeBuf(FValue.Buffer, FValue.Length, FCurrContentType = ctChildren)) + cursor.InternalAppend(doc.CreateTextNodeBuf(FValue.Buffer, FValue.Length, FCurrNode^.FNodeType = ntWhitespace)) else Continue; @@ -3062,7 +3067,7 @@ begin if FState <> rsRoot then FatalError('Illegal at document level'); - if FCurrContentType = ctEmpty then + if FValidators[FValidatorNesting].FContentType = ctEmpty then ValidationError('References are illegal in EMPTY elements', []); if ParseRef(FValue) or ResolvePredefined then @@ -3157,8 +3162,9 @@ begin FAttrCount := 0; FPrefixedAttrs := 0; FSpecifiedAttrs := 0; - PushVC(ElDef); // this increases FNesting + Inc(FNesting); + FCurrNode := AllocNodeData(FNesting); FCurrNode^.FQName := ElName; FCurrNode^.FNodeType := ntElement; FCurrNode^.FColonPos := FColonPos; @@ -3592,9 +3598,6 @@ function TXMLReader.AllocAttributeData: PNodeData; begin Result := AllocNodeData(FNesting + FAttrCount + 1); Result^.FNodeType := ntAttribute; - Result^.FPrefix := nil; - Result^.FNsUri := nil; - Result^.FIDEntry := nil; Result^.FIsDefault := False; Inc(FAttrCount); end; @@ -3606,6 +3609,9 @@ begin SetLength(FNodeStack, AIndex * 2 + 2); Result := @FNodeStack[AIndex]; + Result^.FPrefix := nil; + Result^.FNsUri := nil; + Result^.FIDEntry := nil; end; function TXMLReader.AllocAttributeValueChunk(APrev: PNodeData): PNodeData; @@ -3671,21 +3677,23 @@ end; procedure TXMLReader.PushVC(aElDef: TElementDecl); begin - Inc(FNesting); - FCurrNode := AllocNodeData(FNesting); - FCurrNode^.FPrefix := nil; - FCurrNode^.FNsUri := nil; - FCurrNode^.FIDEntry := nil; + Inc(FValidatorNesting); + if FValidatorNesting >= Length(FValidators) then + SetLength(FValidators, FValidatorNesting * 2); - if FNesting >= Length(FValidators) then + with FValidators[FValidatorNesting] do begin - SetLength(FValidators, FNesting * 2); + FElementDef := aElDef; + FCurCP := nil; + FFailed := False; + FContentType := ctAny; + FSaViolation := False; + if Assigned(aElDef) then + begin + FContentType := aElDef.ContentType; + FSaViolation := FStandalone and aElDef.ExternallyDeclared; + end; end; - - FValidators[FNesting].FElementDef := aElDef; - FValidators[FNesting].FCurCP := nil; - FValidators[FNesting].FFailed := False; - UpdateConstraints; end; procedure TXMLReader.PopVC; @@ -3694,24 +3702,9 @@ begin FState := rsEpilog; if FNesting > 0 then Dec(FNesting); FCurrNode := @FNodeStack[FNesting]; - UpdateConstraints; FNext := xtText; end; -procedure TXMLReader.UpdateConstraints; -begin - if FValidate and Assigned(FValidators[FNesting].FElementDef) then - begin - FCurrContentType := FValidators[FNesting].FElementDef.ContentType; - FSaViolation := FStandalone and (FValidators[FNesting].FElementDef.ExternallyDeclared); - end - else - begin - FCurrContentType := ctAny; - FSaViolation := False; - end; -end; - { TElementValidator } function TElementValidator.IsElementAllowed(Def: TElementDecl): Boolean; |
