fix typo
[mcs.git] / class / Mono.Xml.Ext / Mono.Xml.XPath2 / XQueryExpression.cs
blob2b1b0c01560b5b064999a98fef6491d3bdb4401b
1 //
2 // XQueryExpression.cs - abstract syntax tree for XQuery 1.0
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 //
8 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
9 //
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:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
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.
29 #if NET_2_0
30 using System;
31 using System.Collections;
32 using System.Xml;
33 using System.Xml.Query;
34 using System.Xml.Schema;
35 using System.Xml.XPath;
36 using Mono.Xml.XPath2;
37 using Mono.Xml;
39 namespace Mono.Xml.XQuery
41 internal abstract class XmlConstructorExpr : ExprSingle
43 public XmlConstructorExpr (ExprSequence content)
45 this.content = content;
48 ExprSequence content;
50 public ExprSequence Content {
51 get { return content; }
54 #region CompileAndEvaluate
55 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
57 if (Content != null)
58 for (int i = 0; i < Content.Count; i++)
59 Content [i] = Content [i].Compile (compiler);
60 return this;
63 public void SerializeContent (XPathSequence iter)
65 if (Content != null)
66 foreach (ExprSingle expr in Content)
67 expr.Serialize (iter);
70 internal IXmlNamespaceResolver GetNSResolver (XPathSequence iter)
72 // FIXME: IXmlNamespaceResolver must be constructed
73 // considering 1)static context and 2)in-scope element
74 // construction.
75 return iter.Context;
78 public XPathSequence EvaluateNode (XPathSequence iter)
80 return EvaluateNode (iter, XPathNodeType.All);
83 public XPathSequence EvaluateNode (XPathSequence iter, XPathNodeType moveAfterCreation)
85 XmlDocument doc = new XmlDocument ();
86 XmlWriter w = iter.Context.Writer;
87 try {
88 iter.Context.Writer = doc.CreateNavigator ().AppendChild ();
89 Serialize (iter);
90 iter.Context.Writer.Close ();
91 } finally {
92 iter.Context.Writer = w;
94 XPathNavigator nav = doc.CreateNavigator ();
95 switch (moveAfterCreation) {
96 case XPathNodeType.Attribute:
97 nav.MoveToFirstAttribute ();
98 break;
99 case XPathNodeType.Root:
100 break;
101 default:
102 nav.MoveToFirstChild ();
103 break;
105 return new SingleItemIterator (nav, iter.Context);
107 #endregion
110 internal class XmlAttrConstructorList : CollectionBase
112 public XmlAttrConstructorList ()
116 public void Add (XmlAttrConstructor item)
118 List.Add (item);
121 public void Insert (int pos, XmlAttrConstructor item)
123 List.Insert (pos, item);
127 internal class XmlElemConstructor : XmlConstructorExpr
129 XmlQualifiedName name;
130 ExprSequence nameExpr;
132 public XmlElemConstructor (XmlQualifiedName name, ExprSequence content)
133 : base (content)
135 this.name = name;
138 public XmlElemConstructor (ExprSequence name, ExprSequence content)
139 : base (content)
141 this.name = XmlQualifiedName.Empty;
142 this.nameExpr = name;
145 public XmlQualifiedName Name {
146 get { return name; }
148 public ExprSequence NameExpr {
149 get { return nameExpr; }
152 internal override void CheckReference (XQueryASTCompiler compiler)
154 if (nameExpr != null)
155 nameExpr.CheckReference (compiler);
156 if (Content != null)
157 Content.CheckReference (compiler);
160 #region CompileAndEvaluate
161 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
163 if (NameExpr != null)
164 for (int i = 0; i < NameExpr.Count; i++)
165 NameExpr [i] = NameExpr [i].Compile (compiler);
166 if (Content != null)
167 for (int i = 0; i < Content.Count; i++)
168 Content [i] = Content [i].Compile (compiler);
169 return this;
172 // FIXME: can be optimized by checking all items in Expr
173 public override SequenceType StaticType {
174 get { return SequenceType.Element; }
177 public override void Serialize (XPathSequence iter)
179 XmlQualifiedName name = EvaluateName (iter);
180 XmlWriter w = iter.Context.Writer;
181 w.WriteStartElement (iter.Context.LookupPrefix (name.Namespace), name.Name, name.Namespace);
182 SerializeContent (iter);
183 w.WriteEndElement ();
186 public override XPathSequence Evaluate (XPathSequence iter)
188 return EvaluateNode (iter);
191 private XmlQualifiedName EvaluateName (XPathSequence iter)
193 XmlQualifiedName name = Name;
194 if (NameExpr != null) {
195 XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
196 IXmlNamespaceResolver res = iter.Context.NSResolver;
198 switch (value.XmlType.TypeCode) {
199 case XmlTypeCode.QName:
200 name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
201 break;
202 case XmlTypeCode.String:
203 try {
204 name = InternalPool.ParseQName (value.Value, res);
205 } catch (ArgumentException ex) {
206 // FIXME: add more info
207 throw new XmlQueryException (String.Format ("The evaluation result of the name expression could not be resolved as a valid QName. Evaluation result string is '{0}'.", value.Value));
209 break;
210 default:
211 // FIXME: add more info
212 throw new XmlQueryException ("A name of an element constructor must be resolved to either a QName or string.");
215 return name;
217 #endregion
220 internal class XmlAttrConstructor : XmlConstructorExpr
222 XmlQualifiedName name;
223 ExprSequence nameExpr;
225 public XmlAttrConstructor (XmlQualifiedName name, ExprSequence content)
226 : base (content)
228 this.name = name;
231 public XmlAttrConstructor (ExprSequence name, ExprSequence content)
232 : base (content)
234 this.nameExpr = name;
237 internal override void CheckReference (XQueryASTCompiler compiler)
239 if (nameExpr != null)
240 nameExpr.CheckReference (compiler);
241 if (Content != null)
242 Content.CheckReference (compiler);
245 #region CompileAndEvaluate
246 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
248 if (NameExpr != null)
249 for (int i = 0; i < NameExpr.Count; i++)
250 NameExpr [i] = NameExpr [i].Compile (compiler);
251 if (Content != null)
252 for (int i = 0; i < Content.Count; i++)
253 Content [i] = Content [i].Compile (compiler);
254 return this;
257 public XmlQualifiedName Name {
258 get { return name; }
260 public ExprSequence NameExpr {
261 get { return nameExpr; }
264 // FIXME: can be optimized by checking all items in Expr
265 public override SequenceType StaticType {
266 get { return SequenceType.Attribute; }
269 public override void Serialize (XPathSequence iter)
271 XmlQualifiedName name = EvaluateName (iter);
272 XmlWriter w = iter.Context.Writer;
273 w.WriteStartAttribute (GetNSResolver (iter).LookupPrefix (name.Namespace), name.Name, name.Namespace);
274 SerializeContent (iter);
275 w.WriteEndAttribute ();
278 public override XPathSequence Evaluate (XPathSequence iter)
280 return EvaluateNode (iter, XPathNodeType.Attribute);
283 private XmlQualifiedName EvaluateName (XPathSequence iter)
285 XmlQualifiedName name = Name;
286 if (NameExpr != null) {
287 XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
288 IXmlNamespaceResolver res = GetNSResolver (iter);
290 switch (value.XmlType.TypeCode) {
291 case XmlTypeCode.QName:
292 name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
293 break;
294 case XmlTypeCode.String:
295 try {
296 // nonprefixed attribute name == element's local namespace
297 if (value.Value.IndexOf (':') < 0)
298 name = new XmlQualifiedName (value.Value);
299 else
300 name = InternalPool.ParseQName (value.Value, res);
301 } catch (ArgumentException ex) {
302 // FIXME: add more info
303 throw new XmlQueryException (String.Format ("The evaluation result of the name expression could not be resolved as a valid QName. Evaluation result string is '{0}'.", value.Value));
305 break;
306 default:
307 // FIXME: add more info
308 throw new XmlQueryException ("A name of an attribute constructor must be resolved to either a QName or string.");
311 return name;
313 #endregion
316 internal class XmlNSConstructor : XmlConstructorExpr
318 public XmlNSConstructor (string prefix, ExprSequence content)
319 : base (content)
323 internal override void CheckReference (XQueryASTCompiler compiler)
325 Content.CheckReference (compiler);
328 #region CompileAndEvaluate
329 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
331 if (Content != null)
332 for (int i = 0; i < Content.Count; i++)
333 Content [i] = Content [i].Compile (compiler);
334 return this;
337 // FIXME: can be optimized by checking all items in Expr
338 public override SequenceType StaticType {
339 get { return SequenceType.Namespace; }
342 public override void Serialize (XPathSequence iter)
344 // TBD
345 throw new NotImplementedException ();
348 public override XPathSequence Evaluate (XPathSequence iter)
350 // TBD
351 throw new NotImplementedException ();
353 #endregion
356 internal class XmlDocConstructor : XmlConstructorExpr
358 public XmlDocConstructor (ExprSequence content)
359 : base (content)
363 internal override void CheckReference (XQueryASTCompiler compiler)
365 if (Content != null)
366 Content.CheckReference (compiler);
369 #region CompileAndEvaluate
370 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
372 if (Content != null)
373 for (int i = 0; i < Content.Count; i++)
374 Content [i] = Content [i].Compile (compiler);
375 return this;
378 // FIXME: can be optimized by checking all items in Expr
379 public override SequenceType StaticType {
380 get { return SequenceType.Document; }
383 public override void Serialize (XPathSequence iter)
385 XmlWriter w = iter.Context.Writer;
386 w.WriteStartDocument ();
387 SerializeContent (iter);
388 w.WriteEndDocument ();
391 public override XPathSequence Evaluate (XPathSequence iter)
393 return EvaluateNode (iter, XPathNodeType.Root);
395 #endregion
398 internal class XmlTextConstructor : XmlConstructorExpr
400 public XmlTextConstructor (string text)
401 : base (null)
403 this.text = text;
406 public XmlTextConstructor (ExprSequence content)
407 : base (content)
411 string text;
413 public string LiteralText {
414 get { return text; }
417 internal override void CheckReference (XQueryASTCompiler compiler)
419 if (Content != null)
420 Content.CheckReference (compiler);
423 #region CompileAndEvaluate
424 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
426 if (Content != null)
427 for (int i = 0; i < Content.Count; i++)
428 Content [i] = Content [i].Compile (compiler);
429 return this;
432 public override SequenceType StaticType {
433 get { return SequenceType.Text; }
436 public override void Serialize (XPathSequence iter)
438 if (Content != null)
439 iter.Context.Writer.WriteString (Atomize (new ExprSequenceIterator (iter, Content)).Value);
440 else
441 iter.Context.Writer.WriteString (LiteralText);
444 public override XPathSequence Evaluate (XPathSequence iter)
446 return EvaluateNode (iter);
448 #endregion
451 internal class XmlCommentConstructor : XmlConstructorExpr
453 string contentLiteral;
455 public XmlCommentConstructor (string content)
456 : base (null)
458 this.contentLiteral = content;
461 public XmlCommentConstructor (ExprSequence content)
462 : base (content)
466 internal override void CheckReference (XQueryASTCompiler compiler)
468 if (Content != null)
469 Content.CheckReference (compiler);
472 #region CompileAndEvaluate
473 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
475 if (Content != null)
476 for (int i = 0; i < Content.Count; i++)
477 Content [i] = Content [i].Compile (compiler);
478 return this;
481 // FIXME: can be optimized by checking all items in Expr
482 public override SequenceType StaticType {
483 get { return SequenceType.Comment; }
486 public override void Serialize (XPathSequence iter)
488 iter.Context.Writer.WriteComment (Atomize (new ExprSequenceIterator (iter, Content)).Value);
491 public override XPathSequence Evaluate (XPathSequence iter)
493 return EvaluateNode (iter);
495 #endregion
498 internal class XmlPIConstructor : XmlConstructorExpr
500 string name;
501 ExprSequence nameExpr;
503 string contentLiteral;
505 public XmlPIConstructor (string name, string content)
506 : base (null)
508 this.name = name;
509 this.contentLiteral = content;
512 public XmlPIConstructor (string name, ExprSequence content)
513 : base (content)
515 this.name = name;
518 public XmlPIConstructor (ExprSequence name, ExprSequence content)
519 : base (content)
521 this.nameExpr = name;
524 internal override void CheckReference (XQueryASTCompiler compiler)
526 if (nameExpr != null)
527 nameExpr.CheckReference (compiler);
528 if (Content != null)
529 Content.CheckReference (compiler);
532 #region CompileAndEvaluate
533 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
535 if (NameExpr != null)
536 for (int i = 0; i < NameExpr.Count; i++)
537 NameExpr [i] = NameExpr [i].Compile (compiler);
538 if (Content != null)
539 for (int i = 0; i < Content.Count; i++)
540 Content [i] = Content [i].Compile (compiler);
541 return this;
544 public string Name {
545 get { return name; }
548 public ExprSequence NameExpr {
549 get { return nameExpr; }
552 // FIXME: can be optimized by checking all items in Expr
553 public override SequenceType StaticType {
554 get { return SequenceType.XmlPI; }
557 public override void Serialize (XPathSequence iter)
559 iter.Context.Writer.WriteProcessingInstruction (
560 GetName (iter),
561 Atomize (new ExprSequenceIterator (iter, Content)).Value);
564 public override XPathSequence Evaluate (XPathSequence iter)
566 return EvaluateNode (iter);
569 private string GetName (XPathSequence iter)
571 if (Name != String.Empty)
572 return Name;
573 return Atomize (new ExprSequenceIterator (iter, NameExpr)).Value;
575 #endregion
579 #endif