diff options
| author | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2010-09-26 04:50:55 +0000 |
|---|---|---|
| committer | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2010-09-26 04:50:55 +0000 |
| commit | 70cb8082280a51686a59102dd76155650d883463 (patch) | |
| tree | c845539edc51ab26373801234d3c832caacfc21a /packages/fcl-xml | |
| parent | 1dc880632caa2dbbb8027a6040cbcdcaa6b0e43f (diff) | |
| download | fpc-70cb8082280a51686a59102dd76155650d883463.tar.gz | |
XML reader:
* Parse entities by creating another instance of TXMLReader. This is much more straightforward than saving/restoring context of the existing reader.
* Fixed version setting logic so that ReadXMLFragment procedures are now suitable to read entities:
accept streams conforming to extParsedEnt [78], correctly read fragments into documents having version=1.1.
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@16046 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/fcl-xml')
| -rw-r--r-- | packages/fcl-xml/src/xmlread.pp | 66 |
1 files changed, 29 insertions, 37 deletions
diff --git a/packages/fcl-xml/src/xmlread.pp b/packages/fcl-xml/src/xmlread.pp index 64f5c7e9ec..1d4c19e41e 100644 --- a/packages/fcl-xml/src/xmlread.pp +++ b/packages/fcl-xml/src/xmlread.pp @@ -358,6 +358,7 @@ type procedure SkipQuote(out Delim: WideChar; required: Boolean = True); procedure Initialize(ASource: TXMLCharSource); + procedure EntityToSource(AEntity: TDOMEntityEx; out Src: TXMLCharSource); function ContextPush(AEntity: TDOMEntityEx): Boolean; function ContextPop(Forced: Boolean = False): Boolean; procedure XML11_BuildTables; @@ -817,8 +818,6 @@ procedure TXMLDecodingSource.Initialize; begin inherited; FLineNo := 1; - FXml11Rules := FReader.FXML11; - FDecoder.Decode := @Decode_UTF8; FFixedUCS2 := ''; @@ -847,9 +846,11 @@ begin begin FBufSize := 3; // don't decode past XML declaration Inc(FBuf, Length(XmlSign)); - FReader.ParseXmlOrTextDecl(FParent <> nil); + FReader.ParseXmlOrTextDecl((FParent <> nil) or (FReader.FState <> rsProlog)); end; FBufSize := 2047; + if FReader.FXML11 then + FReader.XML11_BuildTables; end; function TXMLDecodingSource.SetEncoding(const AEncoding: string): Boolean; @@ -1337,8 +1338,9 @@ begin doc := AOwner.OwnerDocument; FCursor := AOwner as TDOMNode_WithChildren; FState := rsRoot; - Initialize(ASource); FXML11 := doc.InheritsFrom(TXMLDocument) and (TXMLDocument(doc).XMLVersion = '1.1'); + Initialize(ASource); + FDocType := TDOMDocumentTypeEx(doc.DocType); ParseContent; end; @@ -1581,20 +1583,18 @@ end; const PrefixChar: array[Boolean] of string = ('', '%'); -function TXMLReader.ContextPush(AEntity: TDOMEntityEx): Boolean; -var - Src: TXMLCharSource; +procedure TXMLReader.EntityToSource(AEntity: TDOMEntityEx; out Src: TXMLCharSource); begin if AEntity.FOnStack then FatalError('Entity ''%s%s'' recursively references itself', [PrefixChar[AEntity.FIsPE], AEntity.FName]); if (AEntity.SystemID <> '') and not AEntity.FPrefetched then begin - Result := ResolveEntity(AEntity.SystemID, AEntity.PublicID, AEntity.FURI, Src); - if not Result then + if not ResolveEntity(AEntity.SystemID, AEntity.PublicID, AEntity.FURI, Src) then begin // TODO: a detailed message like SysErrorMessage(GetLastError) would be great here ValidationError('Unable to resolve external entity ''%s''', [AEntity.FName]); + Src := nil; Exit; end; end @@ -1610,9 +1610,16 @@ begin AEntity.FOnStack := True; Src.FEntity := AEntity; +end; - Initialize(Src); - Result := True; +function TXMLReader.ContextPush(AEntity: TDOMEntityEx): Boolean; +var + Src: TXMLCharSource; +begin + EntityToSource(AEntity, Src); + Result := Assigned(Src); + if Result then + Initialize(Src); end; function TXMLReader.ContextPop(Forced: Boolean): Boolean; @@ -1644,10 +1651,8 @@ function TXMLReader.EntityCheck(NoExternals: Boolean): TDOMEntityEx; var RefName: WideString; cnt: Integer; - SaveCursor: TDOMNode_WithChildren; - SaveState: TXMLReadState; - SaveElDef: TDOMElementDef; - SaveValue: TWideCharBuf; + InnerReader: TXMLReader; + Src: TXMLCharSource; begin Result := nil; SetString(RefName, FName.Buffer, FName.Length); @@ -1676,30 +1681,17 @@ begin if not Result.FResolved then begin // To build children of the entity itself, we must parse it "out of context" - SaveCursor := FCursor; - SaveElDef := FValidator[FNesting].FElementDef; - SaveState := FState; - SaveValue := FValue; - if ContextPush(Result) then + InnerReader := TXMLReader.Create; try - FCursor := Result; // build child node tree for the entity + EntityToSource(Result, Src); Result.SetReadOnly(False); - FState := rsRoot; - FValidator[FNesting].FElementDef := nil; - UpdateConstraints; - FSource.DTDSubsetType := dsExternal; // avoids ContextPop at the end - BufAllocate(FValue, 256); - ParseContent; + if Assigned(Src) then + InnerReader.ProcessFragment(Src, Result); Result.FResolved := True; finally - FreeMem(FValue.Buffer); - FValue := SaveValue; + InnerReader.Free; + Result.FOnStack := False; Result.SetReadOnly(True); - ContextPop(True); - FCursor := SaveCursor; - FState := SaveState; - FValidator[FNesting].FElementDef := SaveElDef; - UpdateConstraints; end; end; // at this point we know the charcount of the entity being included @@ -2042,8 +2034,8 @@ begin ExpectString('?>'); { Switch to 1.1 rules only after declaration is parsed completely. This is to ensure that NEL and LSEP within declaration are rejected (rmt-056, rmt-057) } - if (not TextDecl) and (Ver = xmlVersion11) then - XML11_BuildTables; + if Ver = xmlVersion11 then + FXML11 := True; end; procedure TXMLReader.DTDReloadHook; @@ -2759,7 +2751,7 @@ begin FatalError('Illegal at document level'); StoreLocation(FTokenStart); InCDATA := True; - if FCDSectionsAsText then + if FCDSectionsAsText or (FValue.Length = 0) then Continue; tok := xtCDSect; end |
