summaryrefslogtreecommitdiff
path: root/packages/fcl-xml
diff options
context:
space:
mode:
authorsergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-09-26 04:50:55 +0000
committersergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-09-26 04:50:55 +0000
commit70cb8082280a51686a59102dd76155650d883463 (patch)
treec845539edc51ab26373801234d3c832caacfc21a /packages/fcl-xml
parent1dc880632caa2dbbb8027a6040cbcdcaa6b0e43f (diff)
downloadfpc-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.pp66
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