Browse Source

XPath: now when predicate filtering is no longer dependent on axis, it becomes possible to use the same code for TStep and TXPathFilterNode. Inherited TStep from TXPathFilterNode, removed duplicating code.

git-svn-id: trunk@15654 -
sergei 15 years ago
parent
commit
1876fb1c74
1 changed files with 15 additions and 63 deletions
  1. 15 63
      packages/fcl-xml/src/xpath.pp

+ 15 - 63
packages/fcl-xml/src/xpath.pp

@@ -233,12 +233,15 @@ type
   end;
   end;
 
 
 
 
+  TNodeSet = TFPList;
+
   // Filter node (for [20])
   // Filter node (for [20])
 
 
   TXPathFilterNode = class(TXPathExprNode)
   TXPathFilterNode = class(TXPathExprNode)
   private
   private
-    FExpr: TXPathExprNode;
+    FLeft: TXPathExprNode;
     FPredicates: TXPathNodeArray;
     FPredicates: TXPathNodeArray;
+    procedure ApplyPredicates(Nodes: TNodeSet; AEnvironment: TXPathEnvironment);
   public
   public
     constructor Create(AExpr: TXPathExprNode);
     constructor Create(AExpr: TXPathExprNode);
     destructor Destroy; override;
     destructor Destroy; override;
@@ -257,21 +260,15 @@ type
   TNodeTestType = (ntAnyPrincipal, ntName, ntTextNode,
   TNodeTestType = (ntAnyPrincipal, ntName, ntTextNode,
     ntCommentNode, ntPINode, ntAnyNode);
     ntCommentNode, ntPINode, ntAnyNode);
 
 
-  TNodeSet = TFPList;
-
-  TStep = class(TXPathExprNode)
+  TStep = class(TXPathFilterNode)
   private
   private
     procedure SelectNodes(ANode: TDOMNode; out ResultNodes: TNodeSet);
     procedure SelectNodes(ANode: TDOMNode; out ResultNodes: TNodeSet);
-    procedure ApplyPredicates(Nodes: TNodeSet; AEnvironment: TXPathEnvironment);
   public
   public
-    FLeft: TXPathExprNode;
     Axis: TAxis;
     Axis: TAxis;
     NodeTestType: TNodeTestType;
     NodeTestType: TNodeTestType;
     NodeTestString: DOMString;
     NodeTestString: DOMString;
     NSTestString: DOMString;
     NSTestString: DOMString;
-    Predicates: TXPathNodeArray;
     constructor Create(aAxis: TAxis; aTest: TNodeTestType);
     constructor Create(aAxis: TAxis; aTest: TNodeTestType);
-    destructor Destroy; override;
     function Evaluate(AContext: TXPathContext;
     function Evaluate(AContext: TXPathContext;
       AEnvironment: TXPathEnvironment): TXPathVariable; override;
       AEnvironment: TXPathEnvironment): TXPathVariable; override;
   end;
   end;
@@ -1042,14 +1039,14 @@ end;
 constructor TXPathFilterNode.Create(AExpr: TXPathExprNode);
 constructor TXPathFilterNode.Create(AExpr: TXPathExprNode);
 begin
 begin
   inherited Create;
   inherited Create;
-  FExpr := AExpr;
+  FLeft := AExpr;
 end;
 end;
 
 
 destructor TXPathFilterNode.Destroy;
 destructor TXPathFilterNode.Destroy;
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
-  FExpr.Free;
+  FLeft.Free;
   for i := 0 to High(FPredicates) do
   for i := 0 to High(FPredicates) do
     FPredicates[i].Free;
     FPredicates[i].Free;
   inherited Destroy;
   inherited Destroy;
@@ -1058,65 +1055,20 @@ end;
 function TXPathFilterNode.Evaluate(AContext: TXPathContext;
 function TXPathFilterNode.Evaluate(AContext: TXPathContext;
   AEnvironment: TXPathEnvironment): TXPathVariable;
   AEnvironment: TXPathEnvironment): TXPathVariable;
 var
 var
-  ExprResult: TXPathVariable;
-  NodeSet, NewNodeSet: TNodeSet;
-  i, j: Integer;
-  CurContextNode: TDOMNode;
-  NewContext: TXPathContext;
-  DoAdd: Boolean;
+  NodeSet: TNodeSet;
 begin
 begin
-  ExprResult := FExpr.Evaluate(AContext, AEnvironment);
-  NewContext := nil;
-  try
-    NodeSet := ExprResult.AsNodeSet;
-    NewContext := TXPathContext.Create(nil, 0, NodeSet.Count);
-    NewNodeSet := TNodeSet.Create;
-    try
-      for i := 0 to NodeSet.Count - 1 do
-      begin
-        CurContextNode := TDOMNode(NodeSet[i]);
-        NewContext.ContextNode := CurContextNode;
-        Inc(NewContext.ContextPosition);
-        DoAdd := True;
-        for j := 0 to High(FPredicates) do
-        begin
-          DoAdd := FPredicates[j].EvalPredicate(NewContext,
-            AEnvironment);
-          if not DoAdd then
-            Break;
-        end;
-        if DoAdd then
-          NewNodeSet.Add(CurContextNode);
-      end;
-    except
-      NewNodeSet.Free;
-      raise;
-    end;
-    Result := TXPathNodeSetVariable.Create(NewNodeSet);
-  finally
-    NewContext.Free;
-    ExprResult.Release;
-  end;
+  Result := FLeft.Evaluate(AContext, AEnvironment);
+  NodeSet := Result.AsNodeSet;
+  ApplyPredicates(NodeSet, AEnvironment);
 end;
 end;
 
 
 
 
 constructor TStep.Create(aAxis: TAxis; aTest: TNodeTestType);
 constructor TStep.Create(aAxis: TAxis; aTest: TNodeTestType);
 begin
 begin
-  inherited Create;
   Axis := aAxis;
   Axis := aAxis;
   NodeTestType := aTest;
   NodeTestType := aTest;
 end;
 end;
 
 
-destructor TStep.Destroy;
-var
-  i: Integer;
-begin
-  FLeft.Free;
-  for i := 0 to High(Predicates) do
-    Predicates[i].Free;
-  inherited destroy;
-end;
-
 procedure TStep.SelectNodes(ANode: TDOMNode; out ResultNodes: TNodeSet);
 procedure TStep.SelectNodes(ANode: TDOMNode; out ResultNodes: TNodeSet);
 var
 var
   Node, Node2: TDOMNode;
   Node, Node2: TDOMNode;
@@ -1305,12 +1257,12 @@ end;
   by nil. After one filter has been applied, Nodes is packed, and
   by nil. After one filter has been applied, Nodes is packed, and
   the next filter will be processed. }
   the next filter will be processed. }
 
 
-procedure TStep.ApplyPredicates(Nodes: TNodeSet; AEnvironment: TXPathEnvironment);
+procedure TXPathFilterNode.ApplyPredicates(Nodes: TNodeSet; AEnvironment: TXPathEnvironment);
 var
 var
   i, j: Integer;
   i, j: Integer;
   NewContext: TXPathContext;
   NewContext: TXPathContext;
 begin
 begin
-  for i := 0 to High(Predicates) do
+  for i := 0 to High(FPredicates) do
   begin
   begin
     NewContext := TXPathContext.Create(nil, 0, Nodes.Count);
     NewContext := TXPathContext.Create(nil, 0, Nodes.Count);
     try
     try
@@ -1318,7 +1270,7 @@ begin
       begin
       begin
         NewContext.ContextPosition := j+1;
         NewContext.ContextPosition := j+1;
         NewContext.ContextNode := TDOMNode(Nodes[j]);
         NewContext.ContextNode := TDOMNode(Nodes[j]);
-        if not Predicates[i].EvalPredicate(NewContext, AEnvironment) then
+        if not FPredicates[i].EvalPredicate(NewContext, AEnvironment) then
           Nodes[j] := nil;
           Nodes[j] := nil;
       end;
       end;
       Nodes.Pack;
       Nodes.Pack;
@@ -1893,7 +1845,7 @@ begin
       Axis := axisChild;
       Axis := axisChild;
 
 
     Result := ParseNodeTest(Axis);
     Result := ParseNodeTest(Axis);
-    ParsePredicates(Result.Predicates);
+    ParsePredicates(Result.FPredicates);
   end;
   end;
 end;
 end;