mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-26 15:57:19 +01:00
* Initial work to store element/attribute names as "namespaceURI+localname" pairs: remember pointers to reserved namespace URIs and use them for comparison.
git-svn-id: trunk@24305 -
This commit is contained in:
parent
e6dc52bac8
commit
6bb05dbc06
@ -451,6 +451,8 @@ type
|
|||||||
FMaxPoolSize: Integer;
|
FMaxPoolSize: Integer;
|
||||||
FPools: PNodePoolArray;
|
FPools: PNodePoolArray;
|
||||||
FXmlStandalone: Boolean;
|
FXmlStandalone: Boolean;
|
||||||
|
FStdUri_xml: PHashItem;
|
||||||
|
FStdUri_xmlns: PHashItem;
|
||||||
function GetDocumentElement: TDOMElement;
|
function GetDocumentElement: TDOMElement;
|
||||||
function GetDocType: TDOMDocumentType;
|
function GetDocType: TDOMDocumentType;
|
||||||
function GetNodeType: Integer; override;
|
function GetNodeType: Integer; override;
|
||||||
@ -465,6 +467,7 @@ type
|
|||||||
function Alloc(AClass: TDOMNodeClass): TDOMNode;
|
function Alloc(AClass: TDOMNodeClass): TDOMNode;
|
||||||
procedure SetXMLVersion(const aValue: DOMString); virtual;
|
procedure SetXMLVersion(const aValue: DOMString); virtual;
|
||||||
procedure SetXMLStandalone(aValue: Boolean); virtual;
|
procedure SetXMLStandalone(aValue: Boolean); virtual;
|
||||||
|
function ValidateQName(const nsUri, qName: DOMString; out nsidx: PHashItem): Integer;
|
||||||
public
|
public
|
||||||
function IndexOfNS(const nsURI: DOMString; AddIfAbsent: Boolean = False): Integer;
|
function IndexOfNS(const nsURI: DOMString; AddIfAbsent: Boolean = False): Integer;
|
||||||
function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; override;
|
function InsertBefore(NewChild, RefChild: TDOMNode): TDOMNode; override;
|
||||||
@ -2108,10 +2111,8 @@ end;
|
|||||||
// DOMImplementation
|
// DOMImplementation
|
||||||
// -------------------------------------------------------
|
// -------------------------------------------------------
|
||||||
|
|
||||||
{ if nsIdx = -1, checks only the name. Otherwise additionally checks if the prefix is
|
{ Non-negative return value is Pos(':', QName), negative is DOM error code. }
|
||||||
valid for standard namespace specified by nsIdx.
|
function CheckQName(const QName: DOMString): Integer;
|
||||||
Non-negative return value is Pos(':', QName), negative is DOM error code. }
|
|
||||||
function CheckQName(const QName: DOMString; nsIdx: Integer): Integer;
|
|
||||||
var
|
var
|
||||||
I, L: Integer;
|
I, L: Integer;
|
||||||
begin
|
begin
|
||||||
@ -2139,14 +2140,6 @@ begin
|
|||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if nsIdx < 0 then Exit;
|
|
||||||
// QName contains prefix, but no namespace
|
|
||||||
if ((nsIdx = 0) and (Result > 0)) or
|
|
||||||
// Bad usage of 'http://www.w3.org/2000/xmlns/'
|
|
||||||
((((L = 5) or (Result = 6)) and (Pos(DOMString('xmlns'), QName) = 1)) <> (nsIdx = 2)) or
|
|
||||||
// Bad usage of 'http://www.w3.org/XML/1998/namespace'
|
|
||||||
((Result = 4) and (Pos(DOMString('xml'), QName) = 1) and (nsIdx <> 1)) then
|
|
||||||
Result := -NAMESPACE_ERR;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDOMImplementation.HasFeature(const feature, version: DOMString):
|
function TDOMImplementation.HasFeature(const feature, version: DOMString):
|
||||||
@ -2166,7 +2159,7 @@ var
|
|||||||
res: Integer;
|
res: Integer;
|
||||||
model: TDTDModel;
|
model: TDTDModel;
|
||||||
begin
|
begin
|
||||||
res := CheckQName(QualifiedName, -1);
|
res := CheckQName(QualifiedName);
|
||||||
if res < 0 then
|
if res < 0 then
|
||||||
raise EDOMError.Create(-res, 'Implementation.CreateDocumentType');
|
raise EDOMError.Create(-res, 'Implementation.CreateDocumentType');
|
||||||
model := TDTDModel.Create(nil); // !!nowhere to get nametable from at this time
|
model := TDTDModel.Create(nil); // !!nowhere to get nametable from at this time
|
||||||
@ -2218,6 +2211,8 @@ begin
|
|||||||
FNamespaces[1] := stduri_xml;
|
FNamespaces[1] := stduri_xml;
|
||||||
FNamespaces[2] := stduri_xmlns;
|
FNamespaces[2] := stduri_xmlns;
|
||||||
FEmptyNode := TDOMElement.Create(Self);
|
FEmptyNode := TDOMElement.Create(Self);
|
||||||
|
FStdUri_xml := FNames.FindOrAdd(stduri_xml);
|
||||||
|
FStdUri_xmlns := FNames.FindOrAdd(stduri_xmlns);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TDOMDocument.Destroy;
|
destructor TDOMDocument.Destroy;
|
||||||
@ -2536,19 +2531,36 @@ begin
|
|||||||
FNodeLists.RemoveData(aList);
|
FNodeLists.RemoveData(aList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TDOMDocument.ValidateQName(const nsUri, qName: DOMString;
|
||||||
|
out nsidx: PHashItem): Integer;
|
||||||
|
begin
|
||||||
|
nsidx := FNames.FindOrAdd(DOMPChar(nsUri), Length(nsUri));
|
||||||
|
Result := CheckQName(qName);
|
||||||
|
if Result >= 0 then
|
||||||
|
begin
|
||||||
|
// QName contains prefix, but no namespace
|
||||||
|
if ((nsUri = '') and (Result > 0)) or
|
||||||
|
// Bad usage of 'http://www.w3.org/2000/xmlns/'
|
||||||
|
((((Length(QName) = 5) or (Result = 6)) and (Pos(DOMString('xmlns'), QName) = 1)) <> (nsIdx = FStdUri_xmlns)) or
|
||||||
|
// Bad usage of 'http://www.w3.org/XML/1998/namespace'
|
||||||
|
((Result = 4) and (Pos(DOMString('xml'), QName) = 1) and (nsIdx <> FStdUri_xml)) then
|
||||||
|
Result := -NAMESPACE_ERR;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TDOMDocument.CreateAttributeNS(const nsURI,
|
function TDOMDocument.CreateAttributeNS(const nsURI,
|
||||||
QualifiedName: DOMString): TDOMAttr;
|
QualifiedName: DOMString): TDOMAttr;
|
||||||
var
|
var
|
||||||
idx, PrefIdx: Integer;
|
PrefIdx: Integer;
|
||||||
|
nsidx: PHashItem;
|
||||||
begin
|
begin
|
||||||
idx := IndexOfNS(nsURI, True);
|
PrefIdx := ValidateQName(nsURI, QualifiedName, nsidx);
|
||||||
PrefIdx := CheckQName(QualifiedName, idx);
|
|
||||||
if PrefIdx < 0 then
|
if PrefIdx < 0 then
|
||||||
raise EDOMError.Create(-PrefIdx, 'Document.CreateAttributeNS');
|
raise EDOMError.Create(-PrefIdx, 'Document.CreateAttributeNS');
|
||||||
TDOMNode(Result) := Alloc(TDOMAttr);
|
TDOMNode(Result) := Alloc(TDOMAttr);
|
||||||
Result.Create(Self);
|
Result.Create(Self);
|
||||||
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(QualifiedName), Length(QualifiedName));
|
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(QualifiedName), Length(QualifiedName));
|
||||||
Result.FNSI.NSIndex := Word(idx);
|
Result.FNSI.NSIndex := Word(IndexOfNS(nsURI, True));
|
||||||
Result.FNSI.PrefixLen := Word(PrefIdx);
|
Result.FNSI.PrefixLen := Word(PrefIdx);
|
||||||
Include(Result.FFlags, nfLevel2);
|
Include(Result.FFlags, nfLevel2);
|
||||||
Include(Result.FFlags, nfSpecified);
|
Include(Result.FFlags, nfSpecified);
|
||||||
@ -2557,16 +2569,16 @@ end;
|
|||||||
function TDOMDocument.CreateElementNS(const nsURI,
|
function TDOMDocument.CreateElementNS(const nsURI,
|
||||||
QualifiedName: DOMString): TDOMElement;
|
QualifiedName: DOMString): TDOMElement;
|
||||||
var
|
var
|
||||||
idx, PrefIdx: Integer;
|
PrefIdx: Integer;
|
||||||
|
nsidx: PHashItem;
|
||||||
begin
|
begin
|
||||||
idx := IndexOfNS(nsURI, True);
|
PrefIdx := ValidateQName(nsURI, QualifiedName, nsidx);
|
||||||
PrefIdx := CheckQName(QualifiedName, idx);
|
|
||||||
if PrefIdx < 0 then
|
if PrefIdx < 0 then
|
||||||
raise EDOMError.Create(-PrefIdx, 'Document.CreateElementNS');
|
raise EDOMError.Create(-PrefIdx, 'Document.CreateElementNS');
|
||||||
TDOMNode(Result) := Alloc(TDOMElement);
|
TDOMNode(Result) := Alloc(TDOMElement);
|
||||||
Result.Create(Self);
|
Result.Create(Self);
|
||||||
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(QualifiedName), Length(QualifiedName));
|
Result.FNSI.QName := FNames.FindOrAdd(DOMPChar(QualifiedName), Length(QualifiedName));
|
||||||
Result.FNSI.NSIndex := Word(idx);
|
Result.FNSI.NSIndex := Word(IndexOfNS(nsURI, True));
|
||||||
Result.FNSI.PrefixLen := Word(PrefIdx);
|
Result.FNSI.PrefixLen := Word(PrefIdx);
|
||||||
Include(Result.FFlags, nfLevel2);
|
Include(Result.FFlags, nfLevel2);
|
||||||
Result.AttachDefaultAttrs;
|
Result.AttachDefaultAttrs;
|
||||||
@ -2972,31 +2984,28 @@ end;
|
|||||||
procedure TDOMElement.RestoreDefaultAttr(AttrDef: TAttributeDef);
|
procedure TDOMElement.RestoreDefaultAttr(AttrDef: TAttributeDef);
|
||||||
var
|
var
|
||||||
Attr: TDOMAttr;
|
Attr: TDOMAttr;
|
||||||
ColonPos: Integer;
|
AttrData: TNodeData;
|
||||||
AttrName, nsuri: DOMString;
|
nsuri: DOMString;
|
||||||
begin
|
begin
|
||||||
if nfDestroying in FOwnerDocument.FFlags then
|
if nfDestroying in FOwnerDocument.FFlags then
|
||||||
Exit;
|
Exit;
|
||||||
Attr := LoadAttribute(FOwnerDocument, AttrDef.Data);
|
{ Copy data and maybe fixup namespace fields }
|
||||||
|
AttrData := AttrDef.Data^;
|
||||||
AttrName := Attr.Name;
|
if AttrDef.IsNamespaceDecl then
|
||||||
ColonPos := Pos(WideChar(':'), AttrName);
|
AttrData.FNsUri := FOwnerDocument.FStdUri_xmlns
|
||||||
if Pos(DOMString('xmlns'), AttrName) = 1 then
|
else if AttrData.FColonPos > 0 then
|
||||||
begin
|
begin
|
||||||
if (Length(AttrName) = 5) or (ColonPos = 6) then
|
if (AttrData.FColonPos = 3) and (Pos(DOMString('xml'), AttrData.FQName^.Key) = 1) then
|
||||||
Attr.SetNSI(stduri_xmlns, ColonPos);
|
AttrData.FNsUri := FOwnerDocument.FStdUri_xml
|
||||||
end
|
|
||||||
else if ColonPos > 0 then
|
|
||||||
begin
|
|
||||||
if (ColonPos = 4) and (Pos(DOMString('xml'), AttrName) = 1) then
|
|
||||||
Attr.SetNSI(stduri_xml, 4)
|
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
nsuri := LookupNamespaceURI(Copy(AttrName, 1, ColonPos-1));
|
nsuri := LookupNamespaceURI(Copy(AttrData.FQName^.Key, 1, AttrData.FColonPos));
|
||||||
// TODO: what if prefix isn't defined?
|
// TODO: what if prefix isn't defined?
|
||||||
Attr.SetNSI(nsuri, ColonPos);
|
AttrData.FNsUri := FOwnerDocument.FNames.FindOrAdd(nsuri);
|
||||||
end
|
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
Attr := LoadAttribute(FOwnerDocument, @AttrData);
|
||||||
|
|
||||||
// TODO: this is cheat, should look at config['namespaces'] instead.
|
// TODO: this is cheat, should look at config['namespaces'] instead.
|
||||||
// revisit when it is implemented.
|
// revisit when it is implemented.
|
||||||
if nfLevel2 in FFlags then
|
if nfLevel2 in FFlags then
|
||||||
@ -3087,10 +3096,11 @@ var
|
|||||||
I: Cardinal;
|
I: Cardinal;
|
||||||
Attr: TDOMAttr;
|
Attr: TDOMAttr;
|
||||||
idx, prefIdx: Integer;
|
idx, prefIdx: Integer;
|
||||||
|
nsidx: PHashItem;
|
||||||
begin
|
begin
|
||||||
Changing;
|
Changing;
|
||||||
idx := FOwnerDocument.IndexOfNS(nsURI, True);
|
idx := FOwnerDocument.IndexOfNS(nsURI, True);
|
||||||
prefIdx := CheckQName(qualifiedName, idx);
|
prefIdx := FOwnerDocument.ValidateQName(nsURI, qualifiedName, nsidx);
|
||||||
if prefIdx < 0 then
|
if prefIdx < 0 then
|
||||||
raise EDOMError.Create(-prefIdx, 'Element.SetAttributeNS');
|
raise EDOMError.Create(-prefIdx, 'Element.SetAttributeNS');
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user