소스 검색

xpath.pp: Honor axis direction when filtering step result with predicates. For reverse axes, ContextPosition is now relative to the last node of the set. The third argument of TXPathExprNode.EvalPredicate() is redundant and has been removed.

git-svn-id: trunk@13129 -
sergei 16 년 전
부모
커밋
7a478e64c2
1개의 변경된 파일12개의 추가작업 그리고 6개의 파일을 삭제
  1. 12 6
      packages/fcl-xml/src/xpath.pp

+ 12 - 6
packages/fcl-xml/src/xpath.pp

@@ -101,7 +101,7 @@ type
   TXPathExprNode = class
   protected
     function EvalPredicate(AContext: TXPathContext;
-      AEnvironment: TXPathEnvironment; APosition: Integer): Boolean;
+      AEnvironment: TXPathEnvironment): Boolean;
   public
     function Evaluate(AContext: TXPathContext;
       AEnvironment: TXPathEnvironment): TXPathVariable; virtual; abstract;
@@ -586,14 +586,14 @@ end;
 { XPath parse tree classes }
 
 function TXPathExprNode.EvalPredicate(AContext: TXPathContext;
-  AEnvironment: TXPathEnvironment; APosition: Integer): Boolean;
+  AEnvironment: TXPathEnvironment): Boolean;
 var
   resvar: TXPathVariable;
 begin
   resvar := Evaluate(AContext, AEnvironment);
   try
     if resvar.InheritsFrom(TXPathNumberVariable) then
-      Result := resvar.AsNumber = APosition + 1   // TODO: trunc/round?
+      Result := resvar.AsNumber = AContext.ContextPosition   // TODO: trunc/round?
     else
       Result := resvar.AsBoolean;
   finally
@@ -1030,7 +1030,7 @@ begin
         for j := 0 to FPredicates.Count - 1 do
         begin
           DoAdd := TXPathExprNode(FPredicates[j]).EvalPredicate(NewContext,
-            AEnvironment, i);
+            AEnvironment);
           if not DoAdd then
             Break;
         end;
@@ -1258,10 +1258,16 @@ var
         Predicate := TXPathExprNode(AStep.Predicates[i]);
         for j := 0 to StepNodes.Count - 1 do
         begin
+          // ContextPosition must honor the axis direction
+          if AStep.Axis in [axisAncestor, axisAncestorOrSelf,
+            axisPreceding, axisPrecedingSibling] then
+            NewContext.ContextPosition := StepNodes.Count - j
+          else
+            NewContext.ContextPosition := j+1;
+
           Node := TDOMNode(StepNodes[j]);
           NewContext.ContextNode := Node;
-          Inc(NewContext.ContextPosition);
-          if Predicate.EvalPredicate(NewContext, AEnvironment, j) then
+          if Predicate.EvalPredicate(NewContext, AEnvironment) then
             NewStepNodes.Add(Node);
         end;
       finally