Forráskód Böngészése

* Some fixes from Sebastian Guenther, obtained through Kris Leech

git-svn-id: trunk@6648 -
michael 18 éve
szülő
commit
b225a70853
1 módosított fájl, 54 hozzáadás és 29 törlés
  1. 54 29
      fcl/xml/xpath.pp

+ 54 - 29
fcl/xml/xpath.pp

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