Переглянути джерело

2004-03-11 Atsushi Enomoto <[email protected]>

	* Expression.cs,
	  DefaultContext.cs : Removed unused NeedAbsoluteMatching.
	  Added Peer and Subtree (for "peer & subtree optimization. See:
	  http://idealliance.org/papers/dx_xmle04/papers/02-03-02/02-03-02.html
	  Fixed some ToString() that caused NullReferenceException.

	* Iterator.cs : Predicate does not affect on RequireSorting.
	  Added SimpleSlashIterator for peer & subtree optimization.

	  Added PreserveWhitespace() consideration in BaseIterator.MoveNext().

	* XslKey.cs : removed unused NeedAbsoluteMatching.
	* XslFunctions.cs : Added Peer (for peer & subtree optimization).
	  Added some missing ToString() overrides.


svn path=/trunk/mcs/; revision=41687
Atsushi Eno 21 роки тому
батько
коміт
a643fbe57b

+ 6 - 0
mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog

@@ -1,3 +1,9 @@
+2005-03-11  Atsushi Enomoto  <[email protected]>
+
+	* XslKey.cs : removed unused NeedAbsoluteMatching.
+	* XslFunctions.cs : Added Peer (for peer & subtree optimization).
+	  Added some missing ToString() overrides.
+
 2005-03-09  Atsushi Enomoto  <[email protected]>
 
 	* XslStylesheet.cs, XslCompiledContext.cs : Fixed PreserveWhitespace()

+ 58 - 1
mcs/class/System.XML/Mono.Xml.Xsl/XslFunctions.cs

@@ -193,6 +193,15 @@ namespace Mono.Xml.Xsl
 		{
 			return new SelfIterator ((iter.NamespaceManager as XsltCompiledContext).Processor.CurrentNode, null);
 		}
+
+		internal override bool Peer {
+			get { return false; }
+		}
+
+		public override string ToString ()
+		{
+			return "current()";
+		}
 	}
 	
 	class XsltDocument : XPathFunction 
@@ -211,7 +220,11 @@ namespace Mono.Xml.Xsl
 			doc = c.Input.Clone ();
 		}
 		public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
-		
+
+		internal override bool Peer {
+			get { return arg0.Peer && (arg1 != null ? arg1.Peer : true); }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			string baseUri = null;
@@ -279,6 +292,15 @@ namespace Mono.Xml.Xsl
 			
 			return new SelfIterator (n, xsltContext);
 		}
+
+		public override string ToString ()
+		{
+			return String.Concat ("document(",
+				arg0.ToString (),
+				arg1 != null ? "," : String.Empty,
+				arg1 != null ? arg1.ToString () : String.Empty,
+				")");
+		}
 	}
 	
 	class XsltElementAvailable : XPathFunction 
@@ -297,6 +319,10 @@ namespace Mono.Xml.Xsl
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			QName name = XslNameUtil.FromString (arg0.EvaluateString (iter), ctx);
@@ -346,6 +372,10 @@ namespace Mono.Xml.Xsl
 			}
 		}
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer && (arg2 != null ? arg2.Peer : true); }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -380,6 +410,10 @@ namespace Mono.Xml.Xsl
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -451,6 +485,11 @@ namespace Mono.Xml.Xsl
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			XPathNavigator n;
@@ -504,6 +543,10 @@ namespace Mono.Xml.Xsl
 		public Expression KeyName { get { return arg0; } }
 		public Expression Field { get { return arg1; } }
 		public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -580,6 +623,11 @@ namespace Mono.Xml.Xsl
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			QName name = XslNameUtil.FromString (arg0.EvaluateString (iter), ctx);
@@ -609,6 +657,11 @@ namespace Mono.Xml.Xsl
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			IHasXmlNode xn = iter.Current as IHasXmlNode;
@@ -645,6 +698,10 @@ namespace Mono.Xml.Xsl
 			}
 		}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			XsltCompiledContext ctx = iter.NamespaceManager as XsltCompiledContext;

+ 1 - 10
mcs/class/System.XML/Mono.Xml.Xsl/XslKey.cs

@@ -63,11 +63,6 @@ namespace Mono.Xml.Xsl
 			get { return expr.EvaluatedNodeType; }
 		}
 
-		internal override bool NeedAbsoluteMatching {
-			// This must be evaluated at any point.
-			get { return true; }
-		}
-
 		public override XPathResultType ReturnType {
 			get { return expr.ReturnType; }
 		}
@@ -120,11 +115,7 @@ namespace Mono.Xml.Xsl
 		{
 			XPathNavigator nav = doc.Clone ();
 			nav.MoveToRoot ();
-//			Expression expr = ((ExprKeyContainer) MatchPattern.ExpressionNode).BodyExpression;
-//			if (expr.NeedAbsoluteMatching)
-//				CollectAbsoluteMatchNodes (nav);
-//			else
-				CollectRelativeMatchNodes (nav);
+			CollectRelativeMatchNodes (nav);
 		}
 
 		private void CollectAbsoluteMatchNodes (XPathNavigator nav)

+ 13 - 0
mcs/class/System.XML/System.Xml.XPath/ChangeLog

@@ -1,3 +1,16 @@
+2004-03-11  Atsushi Enomoto  <[email protected]>
+
+	* Expression.cs,
+	  DefaultContext.cs : Removed unused NeedAbsoluteMatching.
+	  Added Peer and Subtree (for "peer & subtree optimization. See:
+	  http://idealliance.org/papers/dx_xmle04/papers/02-03-02/02-03-02.html
+	  Fixed some ToString() that caused NullReferenceException.
+
+	* Iterator.cs : Predicate does not affect on RequireSorting.
+	  Added SimpleSlashIterator for peer & subtree optimization.
+
+	  Added PreserveWhitespace() consideration in BaseIterator.MoveNext().
+
 2004-03-09  Atsushi Enomoto  <[email protected]>
 
 	* Expression.cs,

+ 102 - 3
mcs/class/System.XML/System.Xml.XPath/DefaultContext.cs

@@ -213,7 +213,11 @@ namespace System.Xml.XPath
 		}
 
 		public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
-		
+
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			return (double) arg0.EvaluateNodeSet (iter).Count;
@@ -251,6 +255,10 @@ namespace System.Xml.XPath
 		private static char [] rgchWhitespace = {' ', '\t', '\r', '\n'};
 		public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			String strArgs;
@@ -297,6 +305,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0 != null ? arg0.Peer : true; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -328,6 +340,10 @@ namespace System.Xml.XPath
 					throw new XPathException ("namespace-uri takes 1 or zero args");
 			}
 		}
+
+		internal override bool Peer {
+			get { return arg0 != null ? arg0.Peer : true; }
+		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
 		
@@ -363,6 +379,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0 != null ? arg0.Peer : true; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -377,7 +397,9 @@ namespace System.Xml.XPath
 
 		public override string ToString ()
 		{
-			return "name(" + arg0.ToString () + ")";
+			return String.Concat ("name(",
+				 arg0 != null ? arg0.ToString () : String.Empty,
+				 ")");
 		}
 	}
 
@@ -391,12 +413,16 @@ namespace System.Xml.XPath
 			if (args != null) {
 				arg0 = args.Arg;
 				if (args.Tail != null)
-					throw new XPathException ("boolean takes 1 or zero args");
+					throw new XPathException ("string takes 1 or zero args");
 			}
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
 
+		internal override bool Peer {
+			get { return arg0 != null ? arg0.Peer : true; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			if (arg0 == null)
@@ -424,6 +450,15 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get {
+				for (int i = 0; i < rgs.Count; i++)
+					if (!((Expression) rgs [i]).Peer)
+						return false;
+				return true;
+			}
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -465,6 +500,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -492,6 +531,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -519,6 +562,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -551,6 +598,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -585,6 +636,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer && (arg2 != null ? arg2.Peer : true); }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -642,6 +697,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
+
+		internal override bool Peer {
+			get { return arg0 != null ? arg0.Peer : true; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -676,6 +735,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
 
+		internal override bool Peer {
+			get { return arg0 !=null ? arg0.Peer : true; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			string str;
@@ -730,6 +793,10 @@ namespace System.Xml.XPath
 		}
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.String; }}
+
+		internal override bool Peer {
+			get { return arg0.Peer && arg1.Peer && arg2.Peer; }
+		}
 		
 		public override object Evaluate (BaseIterator iter)
 		{
@@ -783,6 +850,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
 
+		internal override bool Peer {
+			get { return arg0 != null ? arg0.Peer : true; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			if (arg0 == null)
@@ -810,6 +881,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			return !arg0.EvaluateBoolean (iter);
@@ -878,6 +953,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Boolean; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			string lang = arg0.EvaluateString (iter).ToLower (CultureInfo.InvariantCulture);
@@ -908,6 +987,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
 
+		internal override bool Peer {
+			get { return arg0 != null ? arg0.Peer : true; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			if (arg0 == null)
@@ -935,6 +1018,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			XPathNodeIterator itr = arg0.EvaluateNodeSet (iter);
@@ -966,6 +1053,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			return Math.Floor (arg0.EvaluateNumber (iter));
@@ -991,6 +1082,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			return Math.Ceiling (arg0.EvaluateNumber (iter));
@@ -1016,6 +1111,10 @@ namespace System.Xml.XPath
 		
 		public override XPathResultType ReturnType { get { return XPathResultType.Number; }}
 
+		internal override bool Peer {
+			get { return arg0.Peer; }
+		}
+
 		public override object Evaluate (BaseIterator iter)
 		{
 			double arg = arg0.EvaluateNumber (iter);

+ 109 - 28
mcs/class/System.XML/System.Xml.XPath/Expression.cs

@@ -431,11 +431,11 @@ namespace System.Xml.XPath
 			get { return XPathNodeType.All; }
 		}
 
-		internal virtual bool NeedAbsoluteMatching {
+		internal virtual bool IsPositional {
 			get { return false; }
 		}
 
-		internal virtual bool IsPositional {
+		internal virtual bool Peer {
 			get { return false; }
 		}
 
@@ -580,6 +580,10 @@ namespace System.Xml.XPath
 		internal override bool IsPositional {
 			get { return _left.IsPositional || _right.IsPositional; }
 		}
+
+		internal override bool Peer {
+			get { return _left.Peer && _right.Peer; }
+		}
 	}
 
 	internal abstract class ExprBoolean : ExprBinary
@@ -940,11 +944,13 @@ namespace System.Xml.XPath
 	internal abstract class NodeSet : Expression
 	{
 		public override XPathResultType ReturnType { get { return XPathResultType.NodeSet; }}
+
+		internal abstract bool Subtree { get; }
 	}
 
 	internal class ExprUNION : NodeSet
 	{
-		public readonly Expression left, right;
+		internal readonly Expression left, right;
 		public ExprUNION (Expression left, Expression right)
 		{
 			this.left = left;
@@ -958,10 +964,6 @@ namespace System.Xml.XPath
 			return new UnionIterator (iter, iterLeft, iterRight);
 		}
 
-		internal override bool NeedAbsoluteMatching {
-			get { return left.NeedAbsoluteMatching || right.NeedAbsoluteMatching; }
-		}
-
 		internal override XPathNodeType EvaluatedNodeType {
 			get { return left.EvaluatedNodeType == right.EvaluatedNodeType ? left.EvaluatedNodeType : XPathNodeType.All; }
 		}
@@ -969,6 +971,18 @@ namespace System.Xml.XPath
 		internal override bool IsPositional {
 			get { return left.IsPositional || right.IsPositional; }
 		}
+
+		internal override bool Peer {
+			get { return left.Peer && right.Peer; }
+		}
+
+		internal override bool Subtree {
+			get {
+				NodeSet nl = left as NodeSet;
+				NodeSet nr = right as NodeSet;
+				return nl != null && nr != null && nl.Subtree && nr.Subtree;
+			}
+		}
 	}
 
 	internal class ExprSLASH : NodeSet
@@ -984,15 +998,13 @@ namespace System.Xml.XPath
 		public override object Evaluate (BaseIterator iter)
 		{
 			BaseIterator iterLeft = left.EvaluateNodeSet (iter);
-			return new SlashIterator (iterLeft, right, left.RequireSorting || right.RequireSorting);
+			if (left.Peer && right.Subtree && !RequireSorting)
+				return new SimpleSlashIterator (iterLeft, right);
+			return new SlashIterator (iterLeft, right, RequireSorting);
 		}
 
 		public override bool RequireSorting { get { return left.RequireSorting || right.RequireSorting; } }
 
-		internal override bool NeedAbsoluteMatching {
-			get { return true; }
-		}
-
 		internal override XPathNodeType EvaluatedNodeType {
 			get { return right.EvaluatedNodeType; }
 		}
@@ -1000,6 +1012,17 @@ namespace System.Xml.XPath
 		internal override bool IsPositional {
 			get { return left.IsPositional || right.IsPositional; }
 		}
+
+		internal override bool Peer {
+			get { return left.Peer && right.Peer; }
+		}
+
+		internal override bool Subtree {
+			get {
+				NodeSet n = left as NodeSet;
+				return n != null && n.Subtree && right.Subtree;
+			}
+		}
 	}
 	
 	internal class ExprSLASH2 : NodeSet {
@@ -1029,10 +1052,6 @@ namespace System.Xml.XPath
 
 		public override bool RequireSorting { get { return left.RequireSorting || right.RequireSorting; } }
 
-		internal override bool NeedAbsoluteMatching {
-			get { return true; }
-		}
-
 		internal override XPathNodeType EvaluatedNodeType {
 			get { return right.EvaluatedNodeType; }
 		}
@@ -1040,6 +1059,17 @@ namespace System.Xml.XPath
 		internal override bool IsPositional {
 			get { return left.IsPositional || right.IsPositional; }
 		}
+
+		internal override bool Peer {
+			get { return false; }
+		}
+
+		internal override bool Subtree {
+			get {
+				NodeSet n = left as NodeSet;
+				return n != null && n.Subtree && right.Subtree;
+			}
+		}
 	}
 
 	internal class ExprRoot : NodeSet
@@ -1052,13 +1082,17 @@ namespace System.Xml.XPath
 			return new SelfIterator (navRoot, iter.NamespaceManager);
 		}
 
-		internal override bool NeedAbsoluteMatching {
-			get { return false; }
-		}
-
 		internal override XPathNodeType EvaluatedNodeType {
 			get { return XPathNodeType.Root; }
 		}
+
+		internal override bool Peer {
+			get { return true; }
+		}
+
+		internal override bool Subtree {
+			get { return false; }
+		}
 	}
 
 	internal enum Axes
@@ -1205,6 +1239,38 @@ namespace System.Xml.XPath
 
 		}
 
+		internal override bool Peer {
+			get {
+				switch (_axis.Axis) {
+				case Axes.Ancestor:
+				case Axes.AncestorOrSelf:
+				case Axes.DescendantOrSelf:
+				case Axes.Descendant:
+				case Axes.Preceding:
+				case Axes.Following:
+					return false;
+				default:
+					return true;
+				}
+			}
+		}
+
+		internal override bool Subtree {
+			get {
+				switch (_axis.Axis) {
+				case Axes.Parent:
+				case Axes.Ancestor:
+				case Axes.AncestorOrSelf:
+				case Axes.Preceding:
+				case Axes.Following:
+					return false;
+				default:
+					return true;
+				}
+			}
+
+		}
+
 		internal override XPathNodeType EvaluatedNodeType {
 			get { return _axis.NodeType; }
 		}
@@ -1384,10 +1450,6 @@ namespace System.Xml.XPath
 			return new PredicateIterator (iterExpr, pred);
 		}
 
-		internal override bool NeedAbsoluteMatching {
-			get { return expr.NeedAbsoluteMatching; }
-		}
-
 		internal override XPathNodeType EvaluatedNodeType {
 			get { return expr.EvaluatedNodeType; }
 		}
@@ -1399,6 +1461,17 @@ namespace System.Xml.XPath
 				return expr.IsPositional || pred.IsPositional;
 			}
 		}
+
+		internal override bool Peer {
+			get { return expr.Peer && pred.Peer; }
+		}
+
+		internal override bool Subtree {
+			get {
+				NodeSet n = expr as NodeSet;
+				return n != null && n.Subtree;
+			}
+		}
 	}
 
 	internal class ExprNumber : Expression
@@ -1486,6 +1559,10 @@ namespace System.Xml.XPath
 				return iterResult is BaseIterator ? iterResult : new WrapperIterator (iterResult, iter.NamespaceManager);
 			return objResult;
 		}
+
+		internal override bool Peer {
+			get { return false; }
+		}
 	}
 
 	internal class ExprParens : Expression
@@ -1513,10 +1590,6 @@ namespace System.Xml.XPath
 				return o;
 		}
 
-		internal override bool NeedAbsoluteMatching {
-			get { return _expr.NeedAbsoluteMatching; }
-		}
-
 		internal override XPathNodeType EvaluatedNodeType {
 			get { return _expr.EvaluatedNodeType; }
 		}
@@ -1524,6 +1597,10 @@ namespace System.Xml.XPath
 		internal override bool IsPositional {
 			get { return _expr.IsPositional; }
 		}
+
+		internal override bool Peer {
+			get { return _expr.Peer; }
+		}
 	}
 
 	internal class FunctionArguments
@@ -1671,5 +1748,9 @@ namespace System.Xml.XPath
 			}
 			return func.Invoke (context, rgArgs, iter.Current);
 		}
+
+		internal override bool Peer {
+			get { return false; }
+		}
 	}
 }

+ 54 - 1
mcs/class/System.XML/System.Xml.XPath/Iterator.cs

@@ -91,6 +91,11 @@ namespace System.Xml.XPath
 			if (!MoveNextCore ())
 				return false;
 			position++;
+			if (Current != null &&
+				Current.NodeType == XPathNodeType.Whitespace &&
+				_nsm is XsltContext &&
+				!((XsltContext) _nsm).PreserveWhitespace (Current))
+				return MoveNext ();
 			return true;
 		}
 
@@ -831,6 +836,54 @@ namespace System.Xml.XPath
 		public override bool RequireSorting { get { return _iter.RequireSorting; } }
 	}
 
+	internal class SimpleSlashIterator : BaseIterator
+	{
+		private NodeSet _expr;
+		private BaseIterator _left, _right;
+		private XPathNavigator _current;
+
+		public SimpleSlashIterator (BaseIterator left, NodeSet expr)
+			: base (left.NamespaceManager)
+		{
+			this._left = left;
+			this._expr = expr;
+		}
+
+		private SimpleSlashIterator (SimpleSlashIterator other)
+			: base (other)
+		{
+			_expr = other._expr;
+			_left = (BaseIterator) other._left.Clone ();
+			if (other._right != null)
+				_right = (BaseIterator) other._right.Clone ();
+		}
+
+		public override XPathNodeIterator Clone () { return new SimpleSlashIterator (this); }
+
+		public override bool MoveNextCore ()
+		{
+			while (_right == null || !_right.MoveNext ()) {
+				if (!_left.MoveNext ())
+					return false;
+				_right = _expr.EvaluateNodeSet (_left);
+			}
+			if (_current == null)
+				_current = _right.Current.Clone ();
+			else
+				_current.MoveTo (_right.Current);
+			return true;
+		}
+
+		public override XPathNavigator Current {
+			get { return _current; }
+		}
+
+		public override bool RequireSorting {
+			// It always does not need to be sorted.
+			get { return false; }
+		}
+	}
+
 	internal class SlashIterator : BaseIterator
 	{
 		private BaseIterator _iterLeft;
@@ -1056,7 +1109,7 @@ namespace System.Xml.XPath
 			get { return _iter.ReverseAxis; }
 		}
 
-		public override bool RequireSorting { get { return _iter.RequireSorting || _pred.RequireSorting; } }
+		public override bool RequireSorting { get { return _iter.RequireSorting; } }
 	}
 
 	internal class ListIterator : BaseIterator