From a40a00bcde3ffd7a8a449596a2653d190f6e8b94 Mon Sep 17 00:00:00 2001 From: Atsushi Eno Date: Wed, 15 Mar 2006 14:43:45 +0000 Subject: 2006-03-15 Atsushi Enomoto * XslTransformProcessor.cs, Compiler.cs : eliminate ExpressionStore. Now sorting is done inside XslSortEvaluator. * XslSortEvaluator.cs : new file. It handles current node in XSLT context. Fixed bug #77781. * Expression.cs : extracted XPathSortElement, XPathSorters and XPathSorter from CompiledExpression, and split XPathSorters.Sort() into some methods. Those changes are to make them reusable in XslSortEvaluator. * System.Xml.dll.sources : added XslSortEvaluator.cs. * knownFailures.txt : removed two xsl:sort+current() tests. svn path=/trunk/mcs/; revision=58015 --- mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog | 8 ++ mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs | 71 ++++------------ .../System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs | 97 ++++++++++++++++++++++ .../Mono.Xml.Xsl/XslTransformProcessor.cs | 7 +- 4 files changed, 121 insertions(+), 62 deletions(-) create mode 100644 mcs/class/System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs (limited to 'mcs/class/System.XML/Mono.Xml.Xsl') diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog b/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog index c7041f895a9..91022d9e95a 100644 --- a/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog +++ b/mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog @@ -1,3 +1,11 @@ +2006-03-15 Atsushi Enomoto + + * XslTransformProcessor.cs, + Compiler.cs : eliminate ExpressionStore. Now sorting is done + inside XslSortEvaluator. + * XslSortEvaluator.cs : new file. It handles current node in XSLT + context. Fixed bug #77781. + 2006-03-15 Atsushi Enomoto * XslTransformProcessor.cs : in PushNodeset() avoid Clone(). It saves diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs b/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs index 8f90d24c00e..69d418a5e08 100644 --- a/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs +++ b/mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs @@ -49,20 +49,18 @@ namespace Mono.Xml.Xsl XslStylesheet style; Hashtable globalVariables; Hashtable attrSets; - ExpressionStore exprStore; XmlNamespaceManager nsMgr; Hashtable keys; Hashtable outputs; Hashtable decimalFormats; MSXslScriptManager msScripts; - public CompiledStylesheet (XslStylesheet style, Hashtable globalVariables, Hashtable attrSets, ExpressionStore exprStore, XmlNamespaceManager nsMgr, Hashtable keys, Hashtable outputs, Hashtable decimalFormats, + public CompiledStylesheet (XslStylesheet style, Hashtable globalVariables, Hashtable attrSets, XmlNamespaceManager nsMgr, Hashtable keys, Hashtable outputs, Hashtable decimalFormats, MSXslScriptManager msScripts) { this.style = style; this.globalVariables = globalVariables; this.attrSets = attrSets; - this.exprStore = exprStore; this.nsMgr = nsMgr; this.keys = keys; this.outputs = outputs; @@ -71,7 +69,6 @@ namespace Mono.Xml.Xsl } public Hashtable Variables {get{return globalVariables;}} public XslStylesheet Style { get { return style; }} - public ExpressionStore ExpressionStore {get{return exprStore;}} public XmlNamespaceManager NamespaceManager {get{return nsMgr;}} public Hashtable Keys {get { return keys;}} public Hashtable Outputs { get { return outputs; }} @@ -118,7 +115,6 @@ namespace Mono.Xml.Xsl Hashtable globalVariables = new Hashtable (); Hashtable attrSets = new Hashtable (); - ExpressionStore exprStore = new ExpressionStore (); XmlNamespaceManager nsMgr = new XmlNamespaceManager (new NameTable ()); XmlResolver res; @@ -165,7 +161,7 @@ namespace Mono.Xml.Xsl throw new XsltCompileException ("XSLT compile error. " + x.Message, x, Input); } - return new CompiledStylesheet (rootStyle, globalVariables, attrSets, exprStore, nsMgr, keys, outputs, decimalFormats, msScripts); + return new CompiledStylesheet (rootStyle, globalVariables, attrSets, nsMgr, keys, outputs, decimalFormats, msScripts); } MSXslScriptManager msScripts = new MSXslScriptManager (); @@ -354,7 +350,6 @@ namespace Mono.Xml.Xsl Pattern p = Pattern.Compile (pattern, this); if (p == null) throw new XsltCompileException (String.Format ("Invalid pattern '{0}'", pattern), null, loc); - exprStore.AddPattern (p, this); return p; } @@ -375,8 +370,6 @@ namespace Mono.Xml.Xsl expr = new ExprKeyContainer (expr); CompiledExpression e = new CompiledExpression (expression, expr); - exprStore.AddExpression (e, this); - return e; } @@ -441,10 +434,6 @@ namespace Mono.Xml.Xsl return curVarScope.AddVariable (v); } - public void AddSort (XPathExpression e, Sort s) - { - exprStore.AddSort (e, s); - } public VariableScope CurrentVariableScope { get { return curVarScope; }} #endregion @@ -697,8 +686,11 @@ namespace Mono.Xml.Xsl order = ParseOrder (XslAvt.AttemptPreCalc (ref orderAvt)); caseOrder = ParseCaseOrder (XslAvt.AttemptPreCalc (ref caseOrderAvt)); } - - + + public bool IsContextDependent { + get { return orderAvt != null || caseOrderAvt != null || langAvt != null || dataTypeAvt != null; } + } + string ParseLang (string value) { return value; @@ -755,48 +747,15 @@ namespace Mono.Xml.Xsl dataTypeAvt == null ? dataType : ParseDataType (dataTypeAvt.Evaluate (p)) ); } - } - - internal class ExpressionStore { - Hashtable exprToSorts; - - public void AddExpression (XPathExpression e, Compiler c) - { - } - - public void AddPattern (Pattern p, Compiler c) - { - } - - public void AddSort (XPathExpression e, Sort s) - { - if (exprToSorts == null) - exprToSorts = new Hashtable (); - - if (exprToSorts.Contains (e)) - ((ArrayList)exprToSorts [e]).Add (s); - else { - ArrayList a = new ArrayList (); - a.Add (s); - exprToSorts [e] = a; - } - } - - public XPathExpression PrepForExecution (XPathExpression e, XslTransformProcessor p) - { - if (exprToSorts != null && exprToSorts.Contains (e)) - { - XPathExpression expr = e.Clone (); - foreach (Sort s in (ArrayList)exprToSorts [e]) - s.AddToExpr (expr,p); - return expr; - } - return e; - } - - public bool PatternMatches (Pattern p, XslTransformProcessor proc, XPathNavigator n) + + public XPathSorter ToXPathSorter (XslTransformProcessor p) { - return p.Matches (n, proc.XPathContext); + return new XPathSorter (expr, + orderAvt == null ? order : ParseOrder (orderAvt.Evaluate (p)), + caseOrderAvt == null ? caseOrder: ParseCaseOrder (caseOrderAvt.Evaluate (p)), + langAvt == null ? lang : ParseLang (langAvt.Evaluate (p)), + dataTypeAvt == null ? dataType : ParseDataType (dataTypeAvt.Evaluate (p)) + ); } } diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs b/mcs/class/System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs new file mode 100644 index 00000000000..482b19bb235 --- /dev/null +++ b/mcs/class/System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs @@ -0,0 +1,97 @@ +// +// XslSortEvaluator.cs +// +// Author: +// Atsushi Enomoto (atsushi@ximian.com) +// +// Copyright (C) 2006 Novell, Inc. http://www.novell.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +// +// This class handles xsl:sort to have XslTransformProcessor involved in +// the evaluation of resulting nodeset. Beyond XPathExpression.AddSort(), +// it handles current() by having . +// +using System; +using System.Collections; +using System.Xml; +using System.Xml.XPath; + +namespace Mono.Xml.Xsl +{ + class XslSortEvaluator + { + public XslSortEvaluator (XPathExpression select, Sort [] sorterTemplates) + { + this.select = select; + this.sorterTemplates = sorterTemplates; + PopulateConstantSorters (); + sortRunner = new XPathSorters (); + } + + XPathExpression select; + Sort [] sorterTemplates; + XPathSorter [] sorters; + XPathSorters sortRunner; + bool isSorterContextDependent; + + void PopulateConstantSorters () + { + sorters = new XPathSorter [sorterTemplates.Length]; + for (int i = 0; i < sorterTemplates.Length; i++) { + Sort sort = sorterTemplates [i]; + if (sort.IsContextDependent) + isSorterContextDependent = true; + else + sorters [i] = sort.ToXPathSorter (null); + } + } + + public BaseIterator SortedSelect (XslTransformProcessor p) + { + if (isSorterContextDependent) { + for (int i = 0; i < sorters.Length; i++) + if (sorterTemplates [i].IsContextDependent) + sorters [i] = sorterTemplates [i].ToXPathSorter (p); + } + BaseIterator iter = (BaseIterator) p.Select (select); + p.PushNodeset (iter); + p.PushForEachContext (); + ArrayList list = new ArrayList (iter.Count); + while (iter.MoveNext ()) { + XPathSortElement item = new XPathSortElement (); + item.Navigator = iter.Current.Clone (); + item.Values = new object [sorters.Length]; + for (int i = 0; i < sorters.Length; i++) + item.Values [i] = sorters [i].Evaluate (iter); + list.Add (item); + } + p.PopForEachContext (); + p.PopNodeset (); + + sortRunner.CopyFrom (sorters); + return sortRunner.Sort (list, iter.NamespaceManager); + } + } +} diff --git a/mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs b/mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs index d766a98bfd5..f7bb097f4d4 100644 --- a/mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs +++ b/mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs @@ -460,40 +460,35 @@ namespace Mono.Xml.Xsl { public bool Matches (Pattern p, XPathNavigator n) { - return CompiledStyle.ExpressionStore.PatternMatches (p, this, n); + return p.Matches (n, this.XPathContext); } public object Evaluate (XPathExpression expr) { - expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this); XPathNodeIterator itr = CurrentNodeset; return itr.Current.Evaluate (expr, itr, XPathContext); } public string EvaluateString (XPathExpression expr) { - expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this); XPathNodeIterator itr = CurrentNodeset; return itr.Current.EvaluateString (expr, itr, XPathContext); } public bool EvaluateBoolean (XPathExpression expr) { - expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this); XPathNodeIterator itr = CurrentNodeset; return itr.Current.EvaluateBoolean (expr, itr, XPathContext); } public double EvaluateNumber (XPathExpression expr) { - expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this); XPathNodeIterator itr = CurrentNodeset; return itr.Current.EvaluateNumber (expr, itr, XPathContext); } public XPathNodeIterator Select (XPathExpression expr) { - expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this); return CurrentNodeset.Current.Select (expr, XPathContext); } -- cgit v1.2.3