Browse Source

* Some fixes from Sebastian Guenther, obtained through Kris Leech

git-svn-id: trunk@6648 -
michael 18 years ago
parent
commit
b225a70853
1 changed files with 54 additions and 29 deletions
  1. 54 29
      fcl/xml/xpath.pp

+ 54 - 29
fcl/xml/xpath.pp

@@ -14,6 +14,8 @@
 
 
  **********************************************************************}
  **********************************************************************}
 
 
+{$MODE objfpc}
+{$H+}
 
 
 unit XPath;
 unit XPath;
 
 
@@ -322,7 +324,7 @@ type
 
 
   TXPathScannerState = class
   TXPathScannerState = class
   private
   private
-    FCurData: PChar;
+    FCurData: PWideChar;
     FCurToken: TXPathToken;
     FCurToken: TXPathToken;
     FCurTokenString: DOMString;
     FCurTokenString: DOMString;
     FDoUnget: Boolean;
     FDoUnget: Boolean;
@@ -330,7 +332,7 @@ type
 
 
   TXPathScanner = class
   TXPathScanner = class
   private
   private
-    FExpressionString, FCurData: PChar;  // !!!: Change to PWideChar in future
+    FExpressionString, FCurData: PWideChar;
     FCurToken: TXPathToken;
     FCurToken: TXPathToken;
     FCurTokenString: DOMString;
     FCurTokenString: DOMString;
     FDoUnget: Boolean;
     FDoUnget: Boolean;
@@ -459,16 +461,20 @@ var
   Child: TDOMNode;
   Child: TDOMNode;
 begin
 begin
   case Node.NodeType of
   case Node.NodeType of
-    DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE, ELEMENT_NODE:
+    DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE{, ELEMENT_NODE}:
       begin
       begin
         SetLength(Result, 0);
         SetLength(Result, 0);
         Child := Node.FirstChild;
         Child := Node.FirstChild;
         while Assigned(Child) do
         while Assigned(Child) do
         begin
         begin
+	  if Result <> '' then
+	    Result := Result + LineEnding;
           Result := Result + NodeToText(Child);
           Result := Result + NodeToText(Child);
           Child := Child.NextSibling;
           Child := Child.NextSibling;
         end;
         end;
       end;
       end;
+    ELEMENT_NODE:
+      Result := Node.NodeName;
     ATTRIBUTE_NODE, PROCESSING_INSTRUCTION_NODE, COMMENT_NODE, TEXT_NODE,
     ATTRIBUTE_NODE, PROCESSING_INSTRUCTION_NODE, COMMENT_NODE, TEXT_NODE,
       CDATA_SECTION_NODE, ENTITY_REFERENCE_NODE:
       CDATA_SECTION_NODE, ENTITY_REFERENCE_NODE:
       Result := Node.NodeValue;
       Result := Node.NodeValue;
@@ -956,7 +962,7 @@ var
   var
   var
     Node, Node2: TDOMNode;
     Node, Node2: TDOMNode;
     Attr: TDOMNamedNodeMap;
     Attr: TDOMNamedNodeMap;
-    i, j, k: Integer;
+    i, j: Integer;
     DoAdd: Boolean;
     DoAdd: Boolean;
 
 
     NewContext: TXPathContext;
     NewContext: TXPathContext;
@@ -1062,7 +1068,6 @@ var
         DoNodeTest(AContext.ContextNode);
         DoNodeTest(AContext.ContextNode);
     end;
     end;
 
 
-
     { Filter the nodes of this step using the predicates: The current
     { Filter the nodes of this step using the predicates: The current
       node set (StepNodes) is filtered, all passed nodes will be added
       node set (StepNodes) is filtered, all passed nodes will be added
       to NewStepNodes. After one filter has been applied, NewStepNodes
       to NewStepNodes. After one filter has been applied, NewStepNodes
@@ -1148,7 +1153,9 @@ begin
         NewContext.Free;
         NewContext.Free;
       end;
       end;
     end else
     end else
+    begin
       EvaluateStep(FFirstStep, AContext);
       EvaluateStep(FFirstStep, AContext);
+    end;
   except
   except
     ResultNodeSet.Free;
     ResultNodeSet.Free;
     raise;
     raise;
@@ -1234,11 +1241,21 @@ begin
 end;
 end;
 
 
 function TXPathNodeSetVariable.AsText: DOMString;
 function TXPathNodeSetVariable.AsText: DOMString;
+var
+  i: Integer;
 begin
 begin
   if FValue.Count = 0 then
   if FValue.Count = 0 then
     SetLength(Result, 0)
     SetLength(Result, 0)
   else
   else
-    Result := NodeToText(TDOMNode(FValue[0]));
+  begin
+    Result := '';
+    for i := 0 to FValue.Count - 1 do
+    begin
+      if i > 0 then
+        Result := Result + LineEnding;
+      Result := Result + NodeToText(TDOMNode(FValue[i]));
+    end;
+  end;
 end;
 end;
 
 
 
 
@@ -1338,7 +1355,7 @@ end;
 constructor TXPathScanner.Create(const AExpressionString: DOMString);
 constructor TXPathScanner.Create(const AExpressionString: DOMString);
 begin
 begin
   inherited Create;
   inherited Create;
-  FExpressionString := PChar(AExpressionString);
+  FExpressionString := PWideChar(AExpressionString);
   FCurData := FExpressionString;
   FCurData := FExpressionString;
 end;
 end;
 
 
@@ -2009,21 +2026,26 @@ constructor TXPathExpression.Create(AScanner: TXPathScanner;
   var
   var
     IsAbsolute, NeedColonColon: Boolean;
     IsAbsolute, NeedColonColon: Boolean;
     FirstStep, CurStep, NextStep: TStep;
     FirstStep, CurStep, NextStep: TStep;
+    NextToken: TXPathToken;
   begin
   begin
     IsAbsolute := False;
     IsAbsolute := False;
     CurStep := nil;
     CurStep := nil;
+    Result := nil;
 
 
     case AScanner.NextToken of
     case AScanner.NextToken of
       tkSlash:          // [2] AbsoluteLocationPath, first case
       tkSlash:          // [2] AbsoluteLocationPath, first case
         begin
         begin
-          IsAbsolute := True;
-          if not (AScanner.NextToken in
-            [tkDot, tkDotDot, tkAsterisk, tkAt, tkIdentifier]) then
-          begin
-            AScanner.UngetToken;
+	  NextToken := AScanner.NextToken;
+	  AScanner.UngetToken;
+	  if NextToken = tkEndOfStream then
+	  begin
+            CurStep := TStep.Create;
+            CurStep.Axis := axisSelf;
+            CurStep.NodeTestType := ntAnyNode;
+	  end else if not (NextToken in
+            [tkDot, tkDotDot, tkAsterisk, tkAt, tkIdentifier, tkEndOfStream]) then
             exit;
             exit;
-          end;
-          AScanner.UngetToken;
+          IsAbsolute := True;
         end;
         end;
       tkSlashSlash:     // [10] AbbreviatedAbsoluteLocationPath
       tkSlashSlash:     // [10] AbbreviatedAbsoluteLocationPath
         begin
         begin
@@ -2043,31 +2065,32 @@ constructor TXPathExpression.Create(AScanner: TXPathScanner;
     FirstStep := CurStep;
     FirstStep := CurStep;
     while True do
     while True do
     begin
     begin
-      NextStep := TStep.Create;
-      if Assigned(CurStep) then
-        CurStep.NextStep := NextStep
-      else
-        FirstStep := NextStep;
-      CurStep := NextStep;
+      NextToken := AScanner.NextToken;
+      if NextToken <> tkEndOfStream then
+      begin
+        NextStep := TStep.Create;
+        if Assigned(CurStep) then
+          CurStep.NextStep := NextStep
+        else
+          FirstStep := NextStep;
+        CurStep := NextStep;
+      end;
 
 
       // Parse [4] Step
       // Parse [4] Step
-      case AScanner.NextToken of
+      case NextToken of
         tkDot:          // [12] Abbreviated step, first case
         tkDot:          // [12] Abbreviated step, first case
           begin
           begin
             CurStep.Axis := axisSelf;
             CurStep.Axis := axisSelf;
             CurStep.NodeTestType := ntAnyNode;
             CurStep.NodeTestType := ntAnyNode;
           end;
           end;
-        tkDotDot:               // [12] Abbreviated step, second case
+        tkDotDot:	// [12] Abbreviated step, second case
           begin
           begin
             CurStep.Axis := axisParent;
             CurStep.Axis := axisParent;
             CurStep.NodeTestType := ntAnyNode;
             CurStep.NodeTestType := ntAnyNode;
           end;
           end;
-        else
-        begin
-          AScanner.UngetToken;
-
-          // Parse [5] AxisSpecifier
-          case AScanner.NextToken of
+        else		// Parse [5] AxisSpecifier
+	begin
+	  case NextToken of
             tkAt:               // [13] AbbreviatedAxisSpecifier
             tkAt:               // [13] AbbreviatedAxisSpecifier
               CurStep.Axis := axisAttribute;
               CurStep.Axis := axisAttribute;
             tkIdentifier:       // [5] AxisName '::'
             tkIdentifier:       // [5] AxisName '::'
@@ -2112,7 +2135,8 @@ constructor TXPathExpression.Create(AScanner: TXPathScanner;
             else
             else
             begin
             begin
               AScanner.UngetToken;
               AScanner.UngetToken;
-              CurStep.Axis := axisChild;
+	      if NextToken <> tkEndOfStream then
+                CurStep.Axis := axisChild;
             end;
             end;
           end;
           end;
 
 
@@ -2155,6 +2179,7 @@ constructor TXPathExpression.Create(AScanner: TXPathScanner;
                   CurStep.NodeTestString := AScanner.CurTokenString;
                   CurStep.NodeTestString := AScanner.CurTokenString;
                 end;
                 end;
               end;
               end;
+	    tkEndOfStream:	// Enable support of "/" and "//" as path
             else
             else
               Error(SParserInvalidNodeTest);
               Error(SParserInvalidNodeTest);
           end;
           end;