5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
9 // (C) 2003 Atsushi Enomoto
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Collections.Specialized;
37 using System.Xml.Schema;
38 using System.Xml.XPath;
41 using QName = System.Xml.XmlQualifiedName;
43 namespace Mono.Xml.Xsl
45 internal class ExprKeyContainer : Expression
48 public ExprKeyContainer (Expression expr)
53 public Expression BodyExpression {
57 public override object Evaluate (BaseIterator iter)
59 return expr.Evaluate (iter);
62 internal override XPathNodeType EvaluatedNodeType {
\r
63 get { return expr.EvaluatedNodeType; }
\r
66 public override XPathResultType ReturnType {
\r
67 get { return expr.ReturnType; }
\r
70 public override bool RequireSorting {
78 CompiledExpression usePattern;
79 CompiledExpression matchPattern;
81 Hashtable mappedDocuments;
83 public XslKey (Compiler c)
85 this.name = c.ParseQNameAttribute ("name");
87 c.KeyCompilationMode = true;
88 usePattern = c.CompileExpression (c.GetAttribute ("use"));
89 if (usePattern == null)
90 usePattern = c.CompileExpression (".");
92 c.AssertAttribute ("match");
93 string matchString = c.GetAttribute ("match");
94 this.matchPattern = c.CompileExpression (matchString, true);
95 c.KeyCompilationMode = false;
98 public QName Name { get { return name; }}
99 internal CompiledExpression UsePattern { get { return usePattern; }}
100 internal CompiledExpression MatchPattern { get { return matchPattern; }}
102 internal void ClearKeyTable ()
108 if (mappedDocuments != null) {
109 mappedDocuments.Clear ();
110 mappedDocuments = null;
114 internal void CollectTable (XPathNavigator doc)
116 XPathNavigator nav = doc.Clone ();
118 CollectRelativeMatchNodes (nav);
121 private void CollectAbsoluteMatchNodes (XPathNavigator nav)
123 XPathNodeIterator iter = nav.Select (MatchPattern);
124 while (iter.MoveNext ())
125 CollectIndex (iter.Current);
128 private void CollectRelativeMatchNodes (XPathNavigator nav)
131 if (nav.NodeType != XPathNodeType.Root)
132 while (!nav.MoveToNext ())
133 if (!nav.MoveToParent ())
138 if (nav.Matches (MatchPattern))
140 } while (nav.MoveToFirstChild ());
141 } while (nav.MoveToNext ());
142 } while (nav.MoveToParent ());
145 private void CollectIndex (XPathNavigator nav)
147 XPathNavigator target = nav.Clone ();
148 XPathNodeIterator iter;
149 switch (UsePattern.ReturnType) {
150 case XPathResultType.NodeSet:
151 iter = nav.Select (UsePattern);
152 while (iter.MoveNext ())
153 AddIndex (iter.Current.Value, target);
155 case XPathResultType.Any:
156 object o = nav.Evaluate (UsePattern);
157 iter = o as XPathNodeIterator;
159 while (iter.MoveNext ())
160 AddIndex (iter.Current.Value, target);
163 AddIndex (nav.EvaluateString (UsePattern, null, null), target);
166 string key = nav.EvaluateString (UsePattern, null, null);
167 AddIndex (key, target);
172 private void AddIndex (string key, XPathNavigator target)
174 ArrayList al = map [key] as ArrayList;
176 al = new ArrayList ();
182 public bool Matches (XPathNavigator nav, XmlNamespaceManager nsmgr, string value)
185 mappedDocuments = new Hashtable ();
186 map = new Hashtable ();
188 if (mappedDocuments [nav.BaseURI] == null) {
189 mappedDocuments.Add (nav.BaseURI, nav.BaseURI);
190 MatchPattern.SetContext (nsmgr);
191 UsePattern.SetContext (nsmgr);
193 MatchPattern.SetContext (null);
194 UsePattern.SetContext (null);
197 ArrayList al = map [value] as ArrayList;
200 for (int i = 0; i < al.Count; i++)
201 if (((XPathNavigator) al [i]).IsSamePosition (nav))