mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-11 05:41:29 +01:00
Implementation of XPath function lang() + tests.
git-svn-id: trunk@13060 -
This commit is contained in:
parent
1c8d79c57f
commit
e17ac308e0
@ -31,6 +31,8 @@ function IsValidXmlEncoding(const Value: WideString): Boolean;
|
|||||||
function Xml11NamePages: PByteArray;
|
function Xml11NamePages: PByteArray;
|
||||||
procedure NormalizeSpaces(var Value: WideString);
|
procedure NormalizeSpaces(var Value: WideString);
|
||||||
function Hash(InitValue: LongWord; Key: PWideChar; KeyLen: Integer): LongWord;
|
function Hash(InitValue: LongWord; Key: PWideChar; KeyLen: Integer): LongWord;
|
||||||
|
{ beware, works in ASCII range only }
|
||||||
|
function WStrLIComp(S1, S2: PWideChar; Len: Integer): Integer;
|
||||||
|
|
||||||
{ a simple hash table with WideString keys }
|
{ a simple hash table with WideString keys }
|
||||||
|
|
||||||
@ -275,6 +277,33 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function WStrLIComp(S1, S2: PWideChar; Len: Integer): Integer;
|
||||||
|
var
|
||||||
|
counter: Integer;
|
||||||
|
c1, c2: Word;
|
||||||
|
begin
|
||||||
|
counter := 0;
|
||||||
|
result := 0;
|
||||||
|
if Len = 0 then
|
||||||
|
exit;
|
||||||
|
repeat
|
||||||
|
c1 := ord(S1[counter]);
|
||||||
|
c2 := ord(S2[counter]);
|
||||||
|
if (c1 = 0) or (c2 = 0) then break;
|
||||||
|
if c1 <> c2 then
|
||||||
|
begin
|
||||||
|
if c1 in [97..122] then
|
||||||
|
Dec(c1, 32);
|
||||||
|
if c2 in [97..122] then
|
||||||
|
Dec(c2, 32);
|
||||||
|
if c1 <> c2 then
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
Inc(counter);
|
||||||
|
until counter >= Len;
|
||||||
|
result := c1 - c2;
|
||||||
|
end;
|
||||||
|
|
||||||
function Hash(InitValue: LongWord; Key: PWideChar; KeyLen: Integer): LongWord;
|
function Hash(InitValue: LongWord; Key: PWideChar; KeyLen: Integer): LongWord;
|
||||||
begin
|
begin
|
||||||
Result := InitValue;
|
Result := InitValue;
|
||||||
|
|||||||
@ -567,6 +567,28 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function GetNodeLanguage(aNode: TDOMNode): DOMString;
|
||||||
|
var
|
||||||
|
Attr: TDomAttr;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
if aNode = nil then
|
||||||
|
Exit;
|
||||||
|
case aNode.NodeType of
|
||||||
|
ELEMENT_NODE: begin
|
||||||
|
Attr := TDomElement(aNode).GetAttributeNode('xml:lang');
|
||||||
|
if Assigned(Attr) then
|
||||||
|
Result := Attr.Value
|
||||||
|
else
|
||||||
|
Result := GetNodeLanguage(aNode.ParentNode);
|
||||||
|
end;
|
||||||
|
TEXT_NODE, CDATA_SECTION_NODE, ENTITY_REFERENCE_NODE,
|
||||||
|
PROCESSING_INSTRUCTION_NODE, COMMENT_NODE:
|
||||||
|
Result := GetNodeLanguage(aNode.ParentNode);
|
||||||
|
ATTRIBUTE_NODE:
|
||||||
|
Result := GetNodeLanguage(TDOMAttr(aNode).OwnerElement);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ XPath parse tree classes }
|
{ XPath parse tree classes }
|
||||||
|
|
||||||
@ -2628,10 +2650,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TXPathEnvironment.xpLang(Context: TXPathContext; Args: TXPathVarList): TXPathVariable;
|
function TXPathEnvironment.xpLang(Context: TXPathContext; Args: TXPathVarList): TXPathVariable;
|
||||||
|
var
|
||||||
|
L: Integer;
|
||||||
|
TheArg, NodeLang: DOMString;
|
||||||
|
res: Boolean;
|
||||||
begin
|
begin
|
||||||
if Args.Count <> 1 then
|
if Args.Count <> 1 then
|
||||||
EvaluationError(SEvalInvalidArgCount);
|
EvaluationError(SEvalInvalidArgCount);
|
||||||
EvaluationError(SEvalFunctionNotImplementedYet, ['lang']); // !!!
|
TheArg := TXPathVariable(Args[0]).AsText;
|
||||||
|
NodeLang := GetNodeLanguage(Context.ContextNode);
|
||||||
|
|
||||||
|
L := Length(TheArg);
|
||||||
|
res := (L <= Length(NodeLang)) and
|
||||||
|
(WStrLIComp(DOMPChar(NodeLang), DOMPChar(TheArg), L) = 0) and
|
||||||
|
((L = Length(NodeLang)) or (NodeLang[L+1] = '-'));
|
||||||
|
|
||||||
|
Result := TXPathBooleanVariable.Create(res);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TXPathEnvironment.xpNumber(Context: TXPathContext; Args: TXPathVarList): TXPathVariable;
|
function TXPathEnvironment.xpNumber(Context: TXPathContext; Args: TXPathVarList): TXPathVariable;
|
||||||
|
|||||||
@ -394,7 +394,16 @@ const
|
|||||||
'<e>-37</e>'+
|
'<e>-37</e>'+
|
||||||
'</doc>';
|
'</doc>';
|
||||||
|
|
||||||
FunctionTests: array[0..45] of TTestRec = (
|
expr01='<doc>'+
|
||||||
|
'<para id="1" xml:lang="en">en</para>'+
|
||||||
|
'<div xml:lang="en">'+
|
||||||
|
' <para>en</para>'+
|
||||||
|
'</div>'+
|
||||||
|
'<para id="3" xml:lang="EN">EN</para>'+
|
||||||
|
'<para id="4" xml:lang="en-us">en-us</para>'+
|
||||||
|
'</doc>';
|
||||||
|
|
||||||
|
FunctionTests: array[0..49] of TTestRec = (
|
||||||
// last()
|
// last()
|
||||||
// position()
|
// position()
|
||||||
// count()
|
// count()
|
||||||
@ -419,9 +428,13 @@ const
|
|||||||
(expr: 'not(true())'; rt: rtBool; b: False),
|
(expr: 'not(true())'; rt: rtBool; b: False),
|
||||||
(expr: 'not(false())'; rt: rtBool; b: True),
|
(expr: 'not(false())'; rt: rtBool; b: True),
|
||||||
(expr: 'not("")'; rt: rtBool; b: True),
|
(expr: 'not("")'; rt: rtBool; b: True),
|
||||||
{
|
|
||||||
lang() -- involves nodes
|
// lang() tests. These ones, however, test much more than lang().
|
||||||
}
|
// Moreover, I've added string(), otherwise result would be a nodeset
|
||||||
|
(data: expr01; expr: 'string(para[@id="1" and lang("en")])'; rt: rtString; s: 'en'), // expression01
|
||||||
|
(data: expr01; expr: 'string(para[@id="4" and lang("en")])'; rt: rtString; s: 'en-us'), // expression03
|
||||||
|
(data: expr01; expr: 'string(div/para[lang("en")])'; rt: rtString; s: 'en'), // expression04
|
||||||
|
(data: expr01; expr: 'string(para[@id="3" and lang("en")])'; rt: rtString; s: 'EN'), // expression05
|
||||||
|
|
||||||
(expr: 'number("1.5")'; rt: rtNumber; n: 1.5),
|
(expr: 'number("1.5")'; rt: rtNumber; n: 1.5),
|
||||||
(expr: 'number("abc")'; rt: rtNumber; n: NaN),
|
(expr: 'number("abc")'; rt: rtNumber; n: NaN),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user