2 // XQueryContext.cs - XQuery/XPath2 dynamic context
5 // Atsushi Enomoto <atsushi@ximian.com>
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Globalization;
35 using System.Xml.Schema;
36 using System.Xml.XPath;
37 using System.Xml.Query;
39 namespace Mono.Xml.XPath2
41 internal class XQueryContextManager
43 XQueryStaticContext staticContext;
45 // Fixed dynamic context during evaluation
47 XmlResolver extDocResolver;
49 Stack<XQueryContext> contextStack = new Stack<XQueryContext> ();
50 XQueryContext currentContext;
51 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
53 Stack<XPathSequence> contextSequenceStack = new Stack<XPathSequence> ();
55 XmlWriter currentWriter;
56 XPathItem input; // source input item(node)
57 XPathSequence currentSequence;
58 Hashtable currentVariables = new Hashtable ();
59 XmlNamespaceManager namespaceManager;
60 Hashtable localCollationCache = new Hashtable ();
62 internal XQueryContextManager (XQueryStaticContext ctx, XPathItem input, XmlWriter writer, XmlResolver resolver, XmlArgumentList args)
65 this.staticContext = ctx;
67 currentWriter = writer;
68 this.extDocResolver = resolver;
70 currentContext = new XQueryContext (this);
72 namespaceManager = new XmlNamespaceManager (ctx.NameTable);
73 foreach (DictionaryEntry de in ctx.NSResolver.GetNamespacesInScope (XmlNamespaceScope.ExcludeXml))
74 namespaceManager.AddNamespace (de.Key.ToString (), de.Value.ToString ());
75 namespaceManager.PushScope ();
77 this.currentSequence = new SingleItemIterator (input, currentContext);
80 public bool Initialized {
81 get { return currentContext != null; }
84 public XmlResolver ExtDocResolver {
85 get { return extDocResolver; }
88 public XmlArgumentList Arguments {
92 public Hashtable LocalVariables {
93 get { return currentVariables; }
96 public XmlWriter Writer {
97 get { return currentWriter; }
98 // FIXME: might be better avoid setter as public
99 set { currentWriter = value; }
102 internal XQueryContext CurrentContext {
103 get { return currentContext; }
106 internal XQueryStaticContext StaticContext {
107 get { return staticContext; }
110 internal CultureInfo GetCulture (string collation)
112 CultureInfo ci = staticContext.GetCulture (collation);
114 ci = (CultureInfo) localCollationCache [collation];
117 ci = new CultureInfo (collation);
118 localCollationCache [collation] = ci;
122 public void PushCurrentSequence (XPathSequence sequence)
124 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
125 contextStack.Push (currentContext);
126 currentsequence = sequence;
127 currentContext = new XQueryContext (this);
129 contextSequenceStack.Push (currentSequence);
130 currentSequence = sequence;
134 public void PopCurrentSequence ()
136 #if SEEMS_CONTEXT_FOR_CURRENT_REQURED
139 currentSequence = contextSequenceStack.Pop ();
143 // FIXME: According to the spec 3.8.1, variales bindings in
144 // FLWOR is not necesarrily bound to the order of bindings.
145 // Thus, we might not have to create every XQueryContext for
146 // each variable binding (not sure for other kind of bindings).
147 public void PushVariable (XmlQualifiedName name, XPathSequence iter)
149 contextStack.Push (currentContext);
150 currentVariables.Add (name, iter);
151 currentContext = new XQueryContext (this);
154 public void PopVariable ()
159 private void PopContext ()
161 currentContext = contextStack.Pop ();
164 internal XmlNamespaceManager NSManager {
165 get { return namespaceManager; }
169 public class XQueryContext : IXmlNamespaceResolver
171 XQueryContextManager contextManager;
172 Hashtable currentVariables;
173 XPathSequence currentSequence;
175 internal XQueryContext (XQueryContextManager manager)
177 contextManager = manager;
178 if (manager.Initialized) // this condition is not filled on initial creation.
179 currentSequence = manager.CurrentContext.currentSequence;
180 currentVariables = (Hashtable) manager.LocalVariables.Clone ();
183 internal XmlWriter Writer {
184 get { return contextManager.Writer; }
185 // FIXME: might be better avoid public setter.
186 set { contextManager.Writer = value; }
189 internal XQueryStaticContext StaticContext {
190 get { return contextManager.StaticContext; }
193 internal CultureInfo DefaultCollation {
194 get { return StaticContext.DefaultCollation; }
197 internal XQueryContextManager ContextManager {
198 get { return contextManager; }
201 public XPathItem CurrentItem {
202 get { return currentSequence.Current; }
205 public XPathNavigator CurrentNode {
206 get { return CurrentItem as XPathNavigator; }
209 public XPathSequence CurrentSequence {
210 get { return currentSequence; }
213 internal CultureInfo GetCulture (string collation)
215 return contextManager.GetCulture (collation);
218 internal void PushVariable (XmlQualifiedName name, XPathSequence iter)
220 contextManager.PushVariable (name, iter);
223 internal void PopVariable ()
225 contextManager.PopVariable ();
228 internal XPathSequence ResolveVariable (XmlQualifiedName name, XPathSequence context)
230 object obj = currentVariables [name];
232 obj = contextManager.Arguments.GetParameter (name.Name, name.Namespace);
235 throw new XmlQueryException (String.Format ("Cannot resolve variable '{0}'.", name));
236 XPathSequence seq = obj as XPathSequence;
239 XPathItem item = obj as XPathItem;
241 item = new XPathAtomicValue (obj, null);
242 return new SingleItemIterator (item, context);
245 internal XPathSequence ResolveCollection (string name)
247 // FIXME: support later.
248 return new XPathEmptySequence (currentSequence);
251 public IXmlNamespaceResolver NSResolver {
252 get { return contextManager.NSManager; }
255 #region IXmlNamespaceResolver implementation
256 public XmlNameTable NameTable {
257 get { return contextManager.NSManager.NameTable; }
260 public string LookupPrefix (string ns)
262 return contextManager.NSManager.LookupPrefix (ns);
265 public string LookupPrefix (string ns, bool atomized)
267 return contextManager.NSManager.LookupPrefix (ns, atomized);
270 public string LookupNamespace (string prefix)
272 return contextManager.NSManager.LookupNamespace (prefix);
275 public string LookupNamespace (string prefix, bool atomized)
277 return contextManager.NSManager.LookupNamespace (prefix, atomized);
280 public IDictionary GetNamespacesInScope (XmlNamespaceScope scope)
282 return contextManager.NSManager.GetNamespacesInScope (scope);