mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-10 22:06:08 +02:00
* Patch from Sergei Gorelkin:
src/xmlread.pp, src/dom.pp * Improvements to attribute processing: attributes are now validated as they come. This enables reporting of the corresponding validation errors at correct positions (previously everything was reported at the end of element start-tag). * Search for a declaration for attribute, not for an attribute corresponding to the declaration. This reduces number of lookups (because unspecified attributes are not searched) and obsoletes the need in FDeclared field on every attribute. tests/domunit.pp, tests/testgen.pp: * Various improvements required to support converting of the DOM level 3 XPath module. git-svn-id: trunk@12026 -
This commit is contained in:
parent
e5920bc2b8
commit
67f56b7adf
@ -501,8 +501,7 @@ type
|
|||||||
protected
|
protected
|
||||||
FName: DOMString;
|
FName: DOMString;
|
||||||
FOwnerElement: TDOMElement;
|
FOwnerElement: TDOMElement;
|
||||||
// TODO: following 2 - replace with a link to AttDecl ??
|
// TODO: replace with a link to AttDecl ??
|
||||||
FDeclared: Boolean;
|
|
||||||
FDataType: TAttrDataType;
|
FDataType: TAttrDataType;
|
||||||
function GetNodeValue: DOMString; override;
|
function GetNodeValue: DOMString; override;
|
||||||
function GetNodeType: Integer; override;
|
function GetNodeType: Integer; override;
|
||||||
@ -2016,7 +2015,6 @@ begin
|
|||||||
// Cloned attribute is always specified and carries its children
|
// Cloned attribute is always specified and carries its children
|
||||||
Result := ACloneOwner.CreateAttribute(FName);
|
Result := ACloneOwner.CreateAttribute(FName);
|
||||||
TDOMAttr(Result).FDataType := FDataType;
|
TDOMAttr(Result).FDataType := FDataType;
|
||||||
// Declared = ?
|
|
||||||
CloneChildren(Result, ACloneOwner);
|
CloneChildren(Result, ACloneOwner);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -318,6 +318,7 @@ type
|
|||||||
FSaViolation: Boolean;
|
FSaViolation: Boolean;
|
||||||
FDTDStartPos: PWideChar;
|
FDTDStartPos: PWideChar;
|
||||||
FIntSubset: TWideCharBuf;
|
FIntSubset: TWideCharBuf;
|
||||||
|
FAttrTag: Cardinal;
|
||||||
|
|
||||||
FColonPos: Integer;
|
FColonPos: Integer;
|
||||||
FValidate: Boolean; // parsing options, copy of FCtrl.Options
|
FValidate: Boolean; // parsing options, copy of FCtrl.Options
|
||||||
@ -340,6 +341,7 @@ type
|
|||||||
procedure ParseQuantity(CP: TContentParticle);
|
procedure ParseQuantity(CP: TContentParticle);
|
||||||
procedure StoreLocation(out Loc: TLocation);
|
procedure StoreLocation(out Loc: TLocation);
|
||||||
function ValidateAttrSyntax(AttrDef: TDOMAttrDef; const aValue: WideString): Boolean;
|
function ValidateAttrSyntax(AttrDef: TDOMAttrDef; const aValue: WideString): Boolean;
|
||||||
|
procedure ValidateAttrValue(Attr: TDOMAttr; const aValue: WideString);
|
||||||
procedure AddForwardRef(aList: TFPList; Buf: PWideChar; Length: Integer);
|
procedure AddForwardRef(aList: TFPList; Buf: PWideChar; Length: Integer);
|
||||||
procedure ClearRefs(aList: TFPList);
|
procedure ClearRefs(aList: TFPList);
|
||||||
procedure ValidateIdRefs;
|
procedure ValidateIdRefs;
|
||||||
@ -425,6 +427,8 @@ type
|
|||||||
// Attribute/Element declarations
|
// Attribute/Element declarations
|
||||||
|
|
||||||
TDOMAttrDef = class(TDOMAttr)
|
TDOMAttrDef = class(TDOMAttr)
|
||||||
|
private
|
||||||
|
FTag: Cardinal;
|
||||||
protected
|
protected
|
||||||
FExternallyDeclared: Boolean;
|
FExternallyDeclared: Boolean;
|
||||||
FDefault: TAttrDefault;
|
FDefault: TAttrDefault;
|
||||||
@ -432,6 +436,8 @@ type
|
|||||||
function AddEnumToken(Buf: DOMPChar; Len: Integer): Boolean;
|
function AddEnumToken(Buf: DOMPChar; Len: Integer): Boolean;
|
||||||
function HasEnumToken(const aValue: WideString): Boolean;
|
function HasEnumToken(const aValue: WideString): Boolean;
|
||||||
function Clone(AElement: TDOMElement): TDOMAttr;
|
function Clone(AElement: TDOMElement): TDOMAttr;
|
||||||
|
public
|
||||||
|
property Tag: Cardinal read FTag write FTag;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TDOMElementDef = class(TDOMElement)
|
TDOMElementDef = class(TDOMElement)
|
||||||
@ -2625,6 +2631,8 @@ begin
|
|||||||
|
|
||||||
NewElem := doc.CreateElementBuf(FName.Buffer, FName.Length);
|
NewElem := doc.CreateElementBuf(FName.Buffer, FName.Length);
|
||||||
FCursor.AppendChild(NewElem);
|
FCursor.AppendChild(NewElem);
|
||||||
|
// we're about to process a new set of attributes
|
||||||
|
Inc(FAttrTag);
|
||||||
|
|
||||||
// Find declaration for this element
|
// Find declaration for this element
|
||||||
ElDef := nil;
|
ElDef := nil;
|
||||||
@ -2697,10 +2705,49 @@ end;
|
|||||||
procedure TXMLReader.ParseAttribute(Elem: TDOMElement; ElDef: TDOMElementDef);
|
procedure TXMLReader.ParseAttribute(Elem: TDOMElement; ElDef: TDOMElementDef);
|
||||||
var
|
var
|
||||||
attr: TDOMAttr;
|
attr: TDOMAttr;
|
||||||
|
AttDef: TDOMAttrDef;
|
||||||
OldAttr: TDOMNode;
|
OldAttr: TDOMNode;
|
||||||
|
|
||||||
|
procedure CheckValue;
|
||||||
|
var
|
||||||
|
AttValue, OldValue: WideString;
|
||||||
|
begin
|
||||||
|
if FStandalone and AttDef.FExternallyDeclared then
|
||||||
|
begin
|
||||||
|
OldValue := Attr.Value;
|
||||||
|
TDOMAttrDef(Attr).FDataType := AttDef.FDataType;
|
||||||
|
AttValue := Attr.Value;
|
||||||
|
if AttValue <> OldValue then
|
||||||
|
StandaloneError(-1);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
TDOMAttrDef(Attr).FDataType := AttDef.FDataType;
|
||||||
|
AttValue := Attr.Value;
|
||||||
|
end;
|
||||||
|
// TODO: what about normalization of AttDef.Value? (Currently it IS normalized)
|
||||||
|
if (AttDef.FDefault = adFixed) and (AttDef.Value <> AttValue) then
|
||||||
|
ValidationError('Value of attribute ''%s'' does not match its #FIXED default',[AttDef.Name], -1);
|
||||||
|
if not ValidateAttrSyntax(AttDef, AttValue) then
|
||||||
|
ValidationError('Attribute ''%s'' type mismatch', [AttDef.Name], -1);
|
||||||
|
ValidateAttrValue(Attr, AttValue);
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
CheckName;
|
CheckName;
|
||||||
attr := doc.CreateAttributeBuf(FName.Buffer, FName.Length);
|
attr := doc.CreateAttributeBuf(FName.Buffer, FName.Length);
|
||||||
|
|
||||||
|
if Assigned(ElDef) then
|
||||||
|
begin
|
||||||
|
AttDef := TDOMAttrDef(ElDef.GetAttributeNode(attr.Name));
|
||||||
|
if AttDef = nil then
|
||||||
|
ValidationError('Using undeclared attribute ''%s'' on element ''%s''',[attr.Name, Elem.TagName], FName.Length)
|
||||||
|
else
|
||||||
|
AttDef.Tag := FAttrTag; // indicates that this one is specified
|
||||||
|
end
|
||||||
|
else
|
||||||
|
AttDef := nil;
|
||||||
|
|
||||||
// !!cannot use TDOMElement.SetAttributeNode because it will free old attribute
|
// !!cannot use TDOMElement.SetAttributeNode because it will free old attribute
|
||||||
OldAttr := Elem.Attributes.SetNamedItem(Attr);
|
OldAttr := Elem.Attributes.SetNamedItem(Attr);
|
||||||
if Assigned(OldAttr) then
|
if Assigned(OldAttr) then
|
||||||
@ -2711,6 +2758,9 @@ begin
|
|||||||
ExpectEq;
|
ExpectEq;
|
||||||
FCursor := attr;
|
FCursor := attr;
|
||||||
ExpectAttValue;
|
ExpectAttValue;
|
||||||
|
|
||||||
|
if Assigned(AttDef) and ((AttDef.FDataType <> dtCdata) or (AttDef.FDefault = adFixed)) then
|
||||||
|
CheckValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.AddForwardRef(aList: TFPList; Buf: PWideChar; Length: Integer);
|
procedure TXMLReader.AddForwardRef(aList: TFPList; Buf: PWideChar; Length: Integer);
|
||||||
@ -2719,9 +2769,13 @@ var
|
|||||||
begin
|
begin
|
||||||
New(w);
|
New(w);
|
||||||
SetString(w^.Value, Buf, Abs(Length));
|
SetString(w^.Value, Buf, Abs(Length));
|
||||||
StoreLocation(w^.Loc);
|
|
||||||
if Length > 0 then
|
if Length > 0 then
|
||||||
|
begin
|
||||||
|
StoreLocation(w^.Loc);
|
||||||
Dec(w^.Loc.LinePos, Length);
|
Dec(w^.Loc.LinePos, Length);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
w^.Loc := FTokenStart;
|
||||||
aList.Add(w);
|
aList.Add(w);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2752,9 +2806,7 @@ var
|
|||||||
|
|
||||||
procedure DoDefaulting;
|
procedure DoDefaulting;
|
||||||
var
|
var
|
||||||
AttValue: WideString;
|
I: Integer;
|
||||||
I, L, StartPos, EndPos: Integer;
|
|
||||||
Entity: TDOMEntity;
|
|
||||||
AttDef: TDOMAttrDef;
|
AttDef: TDOMAttrDef;
|
||||||
begin
|
begin
|
||||||
Map := ElDef.FAttributes;
|
Map := ElDef.FAttributes;
|
||||||
@ -2763,96 +2815,25 @@ begin
|
|||||||
begin
|
begin
|
||||||
AttDef := Map[I] as TDOMAttrDef;
|
AttDef := Map[I] as TDOMAttrDef;
|
||||||
|
|
||||||
Attr := Element.GetAttributeNode(AttDef.Name);
|
if AttDef.Tag <> FAttrTag then // this one wasn't specified
|
||||||
if Attr = nil then
|
|
||||||
begin
|
begin
|
||||||
// attribute needs defaulting
|
|
||||||
case AttDef.FDefault of
|
case AttDef.FDefault of
|
||||||
adDefault, adFixed: begin
|
adDefault, adFixed: begin
|
||||||
if FStandalone and AttDef.FExternallyDeclared then
|
if FStandalone and AttDef.FExternallyDeclared then
|
||||||
StandaloneError;
|
StandaloneError;
|
||||||
Attr := AttDef.Clone(Element);
|
Attr := AttDef.Clone(Element);
|
||||||
Element.SetAttributeNode(Attr);
|
Element.SetAttributeNode(Attr);
|
||||||
|
ValidateAttrValue(Attr, Attr.Value);
|
||||||
end;
|
end;
|
||||||
adRequired: ValidationError('Required attribute ''%s'' of element ''%s'' is missing',[AttDef.Name, Element.TagName], 0)
|
adRequired: ValidationError('Required attribute ''%s'' of element ''%s'' is missing',[AttDef.Name, Element.TagName], 0)
|
||||||
end;
|
end;
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
TDOMAttrDef(Attr).FDeclared := True;
|
|
||||||
// bypass heavyweight operations if possible
|
|
||||||
if (AttDef.DataType <> dtCdata) or (AttDef.FDefault = adFixed) then
|
|
||||||
begin
|
|
||||||
AttValue := Attr.Value; // unnormalized
|
|
||||||
// now assign DataType so that value is correctly normalized
|
|
||||||
TDOMAttrDef(Attr).FDataType := AttDef.FDataType;
|
|
||||||
if FStandalone and AttDef.FExternallyDeclared and (Attr.Value <> AttValue) then
|
|
||||||
StandaloneError;
|
|
||||||
AttValue := Attr.Value; // recalculate
|
|
||||||
// TODO: what about normalization of AttDef.Value? (Currently it IS normalized)
|
|
||||||
if (AttDef.FDefault = adFixed) and (AttDef.Value <> AttValue) then
|
|
||||||
ValidationError('Value of attribute ''%s'' does not match its #FIXED default',[AttDef.Name], 0);
|
|
||||||
if not ValidateAttrSyntax(AttDef, AttValue) then
|
|
||||||
ValidationError('Attribute ''%s'' type mismatch', [AttDef.Name], 0);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Attr = nil then
|
|
||||||
Continue;
|
|
||||||
L := Length(AttValue);
|
|
||||||
case Attr.DataType of
|
|
||||||
dtId: if not Doc.AddID(Attr) then
|
|
||||||
ValidationError('The ID ''%s'' is not unique', [AttValue], 0);
|
|
||||||
|
|
||||||
dtIdRef, dtIdRefs: begin
|
|
||||||
StartPos := 1;
|
|
||||||
while StartPos <= L do
|
|
||||||
begin
|
|
||||||
EndPos := StartPos;
|
|
||||||
while (EndPos <= L) and (AttValue[EndPos] <> #32) do
|
|
||||||
Inc(EndPos);
|
|
||||||
// pass negative Length, so current location is not altered
|
|
||||||
AddForwardRef(FIDRefs, @AttValue[StartPos], StartPos-EndPos);
|
|
||||||
StartPos := EndPos + 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
dtEntity, dtEntities: begin
|
|
||||||
StartPos := 1;
|
|
||||||
while StartPos <= L do
|
|
||||||
begin
|
|
||||||
EndPos := StartPos;
|
|
||||||
while (EndPos <= L) and (AttValue[EndPos] <> #32) do
|
|
||||||
Inc(EndPos);
|
|
||||||
Entity := TDOMEntity(FDocType.Entities.GetNamedItem(Copy(AttValue, StartPos, EndPos-StartPos)));
|
|
||||||
if (Entity = nil) or (Entity.NotationName = '') then
|
|
||||||
ValidationError('Attribute ''%s'' type mismatch', [Attr.Name], 0);
|
|
||||||
StartPos := EndPos + 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ReportUndeclared;
|
|
||||||
var
|
|
||||||
I: Integer;
|
|
||||||
begin
|
|
||||||
Map := Element.Attributes;
|
|
||||||
for I := 0 to Map.Length-1 do
|
|
||||||
begin
|
|
||||||
Attr := TDOMAttr(Map[I]);
|
|
||||||
if not TDOMAttrDef(Attr).FDeclared then
|
|
||||||
ValidationError('Using undeclared attribute ''%s'' on element ''%s''',[Attr.Name, Element.TagName], 0);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if Assigned(ElDef) and Assigned(ElDef.FAttributes) then
|
if Assigned(ElDef) and Assigned(ElDef.FAttributes) then
|
||||||
DoDefaulting;
|
DoDefaulting;
|
||||||
// Now report undeclared attributes
|
|
||||||
if Assigned(FDocType) and Element.HasAttributes then
|
|
||||||
ReportUndeclared;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXMLReader.ParseExternalID(out SysID, PubID: WideString; // [75]
|
function TXMLReader.ParseExternalID(out SysID, PubID: WideString; // [75]
|
||||||
@ -2895,6 +2876,45 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TXMLReader.ValidateAttrValue(Attr: TDOMAttr; const aValue: WideString);
|
||||||
|
var
|
||||||
|
L, StartPos, EndPos: Integer;
|
||||||
|
Entity: TDOMEntity;
|
||||||
|
begin
|
||||||
|
L := Length(aValue);
|
||||||
|
case Attr.DataType of
|
||||||
|
dtId: if not Doc.AddID(Attr) then
|
||||||
|
ValidationError('The ID ''%s'' is not unique', [aValue], -1);
|
||||||
|
|
||||||
|
dtIdRef, dtIdRefs: begin
|
||||||
|
StartPos := 1;
|
||||||
|
while StartPos <= L do
|
||||||
|
begin
|
||||||
|
EndPos := StartPos;
|
||||||
|
while (EndPos <= L) and (aValue[EndPos] <> #32) do
|
||||||
|
Inc(EndPos);
|
||||||
|
// pass negative length, so uses FTokenStart as location
|
||||||
|
AddForwardRef(FIDRefs, @aValue[StartPos], StartPos-EndPos);
|
||||||
|
StartPos := EndPos + 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
dtEntity, dtEntities: begin
|
||||||
|
StartPos := 1;
|
||||||
|
while StartPos <= L do
|
||||||
|
begin
|
||||||
|
EndPos := StartPos;
|
||||||
|
while (EndPos <= L) and (aValue[EndPos] <> #32) do
|
||||||
|
Inc(EndPos);
|
||||||
|
Entity := TDOMEntity(FDocType.Entities.GetNamedItem(Copy(aValue, StartPos, EndPos-StartPos)));
|
||||||
|
if (Entity = nil) or (Entity.NotationName = '') then
|
||||||
|
ValidationError('Attribute ''%s'' type mismatch', [Attr.Name], -1);
|
||||||
|
StartPos := EndPos + 1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TXMLReader.ValidateRoot;
|
procedure TXMLReader.ValidateRoot;
|
||||||
begin
|
begin
|
||||||
if Assigned(FDocType) then
|
if Assigned(FDocType) then
|
||||||
@ -3068,7 +3088,6 @@ begin
|
|||||||
Result := TDOMAttr.Create(FOwnerDocument);
|
Result := TDOMAttr.Create(FOwnerDocument);
|
||||||
TDOMAttrEx(Result).FName := Self.FName;
|
TDOMAttrEx(Result).FName := Self.FName;
|
||||||
TDOMAttrEx(Result).FDataType := FDataType;
|
TDOMAttrEx(Result).FDataType := FDataType;
|
||||||
TDOMAttrEx(Result).FDeclared := True;
|
|
||||||
CloneChildren(Result, FOwnerDocument);
|
CloneChildren(Result, FOwnerDocument);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ type
|
|||||||
|
|
||||||
procedure _append(var coll: _collection; const Value: DOMString);
|
procedure _append(var coll: _collection; const Value: DOMString);
|
||||||
procedure _assign(out rslt: _collection; const value: array of DOMString);
|
procedure _assign(out rslt: _collection; const value: array of DOMString);
|
||||||
|
function IsSame(exp, act: TDOMNode): Boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -86,6 +87,11 @@ begin
|
|||||||
rslt[I] := value[I];
|
rslt[I] := value[I];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function IsSame(exp, act: TDOMNode): Boolean;
|
||||||
|
begin
|
||||||
|
Result := exp = act;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDOMTestBase.SetUp;
|
procedure TDOMTestBase.SetUp;
|
||||||
begin
|
begin
|
||||||
FParser := TDOMParser.Create;
|
FParser := TDOMParser.Create;
|
||||||
|
@ -29,7 +29,7 @@ var
|
|||||||
|
|
||||||
function PascalType(const s: WideString): string;
|
function PascalType(const s: WideString): string;
|
||||||
begin
|
begin
|
||||||
if (s = 'DOMString') or (s = 'boolean') or (s = 'DOMError') then
|
if (s = 'DOMString') or (s = 'boolean') or (s = 'DOMError') or (s = 'double') then
|
||||||
result := s
|
result := s
|
||||||
else if s = 'int' then
|
else if s = 'int' then
|
||||||
result := 'Integer'
|
result := 'Integer'
|
||||||
@ -39,7 +39,7 @@ begin
|
|||||||
result := '_collection'
|
result := '_collection'
|
||||||
else if s = 'List' then
|
else if s = 'List' then
|
||||||
result := '_list'
|
result := '_list'
|
||||||
else if Pos(WideString('DOM'), s) = 1 then
|
else if (Pos(WideString('DOM'), s) = 1) or (Pos(WideString('XPath'), s) = 1) then
|
||||||
result := 'T' + s
|
result := 'T' + s
|
||||||
else
|
else
|
||||||
result := 'TDOM'+s;
|
result := 'TDOM'+s;
|
||||||
@ -147,6 +147,11 @@ begin
|
|||||||
else
|
else
|
||||||
r := 'bad_condition(''contains intf=' + e['interface'] + ''')';
|
r := 'bad_condition(''contains intf=' + e['interface'] + ''')';
|
||||||
end
|
end
|
||||||
|
else if e.TagName = 'same' then
|
||||||
|
begin
|
||||||
|
// maybe it would be sufficient to just compare pointers, but let's emit a helper for now
|
||||||
|
r := 'IsSame('+ e['expected'] + ', ' + e['actual'] + ')';
|
||||||
|
end
|
||||||
else if e.TagName = 'not' then
|
else if e.TagName = 'not' then
|
||||||
begin
|
begin
|
||||||
child := e.FirstChild;
|
child := e.FirstChild;
|
||||||
@ -304,6 +309,10 @@ begin
|
|||||||
|
|
||||||
s := node.TagName;
|
s := node.TagName;
|
||||||
apinode := api.GetElementById(s);
|
apinode := api.GetElementById(s);
|
||||||
|
// If not found by name only, try prepending the interface name.
|
||||||
|
// This enables support of same-named methods with different param lists on different objects
|
||||||
|
if (apinode = nil) and node.HasAttribute('interface') then
|
||||||
|
apinode := api.GetElementById(node['interface'] + '.' + s);
|
||||||
if assigned(apinode) then
|
if assigned(apinode) then
|
||||||
begin
|
begin
|
||||||
// handle most of DOM API in consistent way
|
// handle most of DOM API in consistent way
|
||||||
@ -369,9 +378,15 @@ begin
|
|||||||
// service (non-DOM) statements follow
|
// service (non-DOM) statements follow
|
||||||
|
|
||||||
else if s = 'append' then
|
else if s = 'append' then
|
||||||
rslt.Add(indent + '_append(' + node['collection'] + ', ' + node['item'] + ');')
|
rslt.Add(indent + '_append(' + node['collection'] + ', ' + ReplaceQuotes(node['item']) + ');')
|
||||||
else if s = 'assign' then
|
else if s = 'assign' then
|
||||||
|
begin
|
||||||
|
cond := TypeOfVar(node['var']);
|
||||||
|
if (cond = '_collection') or (cond = '_list') then
|
||||||
rslt.Add(indent + '_assign(' + node['var'] + ', ' + node['value'] + ');')
|
rslt.Add(indent + '_assign(' + node['var'] + ', ' + node['value'] + ');')
|
||||||
|
else // emit an assignment operator. Force type for the case where they assign Document to Element.
|
||||||
|
rslt.Add(indent + node['var'] + ' := ' + TypeOfVar(node['var']) + '(' + ReplaceQuotes(node['value']) + ');');
|
||||||
|
end
|
||||||
else if s = 'increment' then
|
else if s = 'increment' then
|
||||||
rslt.Add(indent + 'Inc(' + node['var'] + ', ' + node['value'] + ');')
|
rslt.Add(indent + 'Inc(' + node['var'] + ', ' + node['value'] + ');')
|
||||||
else if s = 'decrement' then
|
else if s = 'decrement' then
|
||||||
@ -433,6 +448,10 @@ begin
|
|||||||
rslt.Add(indent + 'Load('+node['var']+', '''+ node['href']+''');')
|
rslt.Add(indent + 'Load('+node['var']+', '''+ node['href']+''');')
|
||||||
else if s = 'implementationAttribute' then
|
else if s = 'implementationAttribute' then
|
||||||
rslt.Add(indent + s + '[''' + node['name'] + '''] := ' + node['value'] + ';')
|
rslt.Add(indent + s + '[''' + node['name'] + '''] := ' + node['value'] + ';')
|
||||||
|
else if s = 'createXPathEvaluator' then
|
||||||
|
rslt.Add(indent + node['var'] + ' := CreateXPathEvaluator(' + node['document'] + ');')
|
||||||
|
else if s = 'comment' then
|
||||||
|
rslt.Add(indent + '{ Source comment: ' + node.TextContent + ' }')
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if not FailFlag then
|
if not FailFlag then
|
||||||
@ -442,12 +461,44 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure ConvertException(el: TDOMElement; const ExceptClass: string; indent: string);
|
||||||
|
var
|
||||||
|
excode: string;
|
||||||
|
begin
|
||||||
|
if not SuccessVarFlag then
|
||||||
|
rslt.Insert(2, ' success: Boolean;');
|
||||||
|
SuccessVarFlag := True;
|
||||||
|
rslt.Add(indent+'success := False;');
|
||||||
|
rslt.Add(indent+'try');
|
||||||
|
child := el.FirstChild;
|
||||||
|
while assigned(child) do
|
||||||
|
begin
|
||||||
|
if child.nodeType = ELEMENT_NODE then
|
||||||
|
begin
|
||||||
|
excode := child.nodeName;
|
||||||
|
subchild := child.FirstChild;
|
||||||
|
while Assigned(subchild) do
|
||||||
|
begin
|
||||||
|
if subchild.nodeType = ELEMENT_NODE then
|
||||||
|
ConvertStatement(TDOMElement(subchild), indent + ' ');
|
||||||
|
subchild := subchild.NextSibling;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
child := child.NextSibling;
|
||||||
|
end;
|
||||||
|
rslt.Add(indent+'except');
|
||||||
|
rslt.Add(indent+' on E: Exception do');
|
||||||
|
rslt.Add(indent+' success := (E is ' + ExceptClass +') and (' + ExceptClass + '(E).Code = ' + excode + ');');
|
||||||
|
rslt.Add(indent+'end;');
|
||||||
|
rslt.Add(indent+'AssertTrue('''+el['id']+''', success);');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure ConvertBlock(el: TDOMNode; indent: string);
|
procedure ConvertBlock(el: TDOMNode; indent: string);
|
||||||
var
|
var
|
||||||
curr: TDOMNode;
|
curr: TDOMNode;
|
||||||
element: TDOMElement;
|
element: TDOMElement;
|
||||||
List: TList;
|
List: TList;
|
||||||
cond, excode: string;
|
cond: string;
|
||||||
Frag: TDOMDocumentFragment;
|
Frag: TDOMDocumentFragment;
|
||||||
I: Integer;
|
I: Integer;
|
||||||
ElseNode: TDOMNode;
|
ElseNode: TDOMNode;
|
||||||
@ -467,34 +518,9 @@ begin
|
|||||||
element := TDOMElement(curr);
|
element := TDOMElement(curr);
|
||||||
n := element.TagName;
|
n := element.TagName;
|
||||||
if n = 'assertDOMException' then
|
if n = 'assertDOMException' then
|
||||||
begin
|
ConvertException(element, 'EDOMError', indent)
|
||||||
if not SuccessVarFlag then
|
else if n = 'assertXPathException' then
|
||||||
rslt.Insert(2, ' success: Boolean;');
|
ConvertException(element, 'EXPathException', indent)
|
||||||
SuccessVarFlag := True;
|
|
||||||
rslt.Add(indent+'success := False;');
|
|
||||||
rslt.Add(indent+'try');
|
|
||||||
child := curr.FirstChild;
|
|
||||||
while assigned(child) do
|
|
||||||
begin
|
|
||||||
if child.nodeType = ELEMENT_NODE then
|
|
||||||
begin
|
|
||||||
excode := child.nodeName;
|
|
||||||
subchild := child.FirstChild;
|
|
||||||
while Assigned(subchild) do
|
|
||||||
begin
|
|
||||||
if subchild.nodeType = ELEMENT_NODE then
|
|
||||||
ConvertStatement(TDOMElement(subchild), indent + ' ');
|
|
||||||
subchild := subchild.NextSibling;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
child := child.NextSibling;
|
|
||||||
end;
|
|
||||||
rslt.Add(indent+'except');
|
|
||||||
rslt.Add(indent+' on E: Exception do');
|
|
||||||
rslt.Add(indent+' success := (E is EDOMError) and (EDOMError(E).Code = ' + excode + ');');
|
|
||||||
rslt.Add(indent+'end;');
|
|
||||||
rslt.Add(indent+'AssertTrue('''+element['id']+''', success);');
|
|
||||||
end
|
|
||||||
else if n = 'try' then
|
else if n = 'try' then
|
||||||
begin
|
begin
|
||||||
GetChildElements(curr, List);
|
GetChildElements(curr, List);
|
||||||
@ -658,7 +684,11 @@ begin
|
|||||||
try
|
try
|
||||||
if subvars.Count > 0 then
|
if subvars.Count > 0 then
|
||||||
begin
|
begin
|
||||||
TypedConsts.Add(' ' + Node['name'] + ': array[0..' + IntToStr(subvars.Count-1) + '] of DOMString = (');
|
if TDOMElement(subvars[0]).HasAttribute('type') then
|
||||||
|
hs := PascalType(TDOMElement(subvars[0]).GetAttribute('type'))
|
||||||
|
else
|
||||||
|
hs := 'DOMString';
|
||||||
|
TypedConsts.Add(' ' + Node['name'] + ': array[0..' + IntToStr(subvars.Count-1) + '] of ' + hs + ' = (');
|
||||||
for J := 0 to subvars.Count-1 do
|
for J := 0 to subvars.Count-1 do
|
||||||
begin
|
begin
|
||||||
hs := ' ' + ReplaceQuotes(subvars[J].TextContent);
|
hs := ' ' + ReplaceQuotes(subvars[J].TextContent);
|
||||||
@ -817,7 +847,12 @@ begin
|
|||||||
if root['name'] = 'attrname' then
|
if root['name'] = 'attrname' then
|
||||||
root['name'] := 'attr_name';
|
root['name'] := 'attr_name';
|
||||||
sl.Add('procedure ' + class_name + '.' + root['name'] + ';');
|
sl.Add('procedure ' + class_name + '.' + root['name'] + ';');
|
||||||
|
try
|
||||||
ConvertTest(root, sl);
|
ConvertTest(root, sl);
|
||||||
|
except
|
||||||
|
Writeln('An exception occured while converting '+root['name']);
|
||||||
|
raise;
|
||||||
|
end;
|
||||||
if sl.Count > 0 then
|
if sl.Count > 0 then
|
||||||
begin
|
begin
|
||||||
all.add(' procedure '+root['name']+';');
|
all.add(' procedure '+root['name']+';');
|
||||||
|
Loading…
Reference in New Issue
Block a user