2 // XQueryExpression.cs - abstract syntax tree for XQuery 1.0
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;
33 using System.Xml.Query;
34 using System.Xml.Schema;
35 using System.Xml.XPath;
36 using Mono.Xml.XPath2;
39 namespace Mono.Xml.XQuery
41 internal abstract class XmlConstructorExpr : ExprSingle
43 public XmlConstructorExpr (ExprSequence content)
45 this.content = content;
50 public ExprSequence Content {
51 get { return content; }
54 #region CompileAndEvaluate
55 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
58 for (int i = 0; i < Content.Count; i++)
59 Content [i] = Content [i].Compile (compiler);
63 public void SerializeContent (XPathSequence iter)
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
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;
88 iter.Context.Writer = doc.CreateNavigator ().AppendChild ();
90 iter.Context.Writer.Close ();
92 iter.Context.Writer = w;
94 XPathNavigator nav = doc.CreateNavigator ();
95 switch (moveAfterCreation) {
96 case XPathNodeType.Attribute:
97 nav.MoveToFirstAttribute ();
99 case XPathNodeType.Root:
102 nav.MoveToFirstChild ();
105 return new SingleItemIterator (nav, iter.Context);
110 internal class XmlAttrConstructorList : CollectionBase
112 public XmlAttrConstructorList ()
116 public void Add (XmlAttrConstructor 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)
138 public XmlElemConstructor (ExprSequence name, ExprSequence content)
141 this.name = XmlQualifiedName.Empty;
142 this.nameExpr = name;
145 public XmlQualifiedName Name {
148 public ExprSequence NameExpr {
149 get { return nameExpr; }
152 internal override void CheckReference (XQueryASTCompiler compiler)
154 if (nameExpr != null)
155 nameExpr.CheckReference (compiler);
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);
167 for (int i = 0; i < Content.Count; i++)
168 Content [i] = Content [i].Compile (compiler);
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);
202 case XmlTypeCode.String:
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));
211 // FIXME: add more info
212 throw new XmlQueryException ("A name of an element constructor must be resolved to either a QName or string.");
220 internal class XmlAttrConstructor : XmlConstructorExpr
222 XmlQualifiedName name;
223 ExprSequence nameExpr;
225 public XmlAttrConstructor (XmlQualifiedName name, ExprSequence content)
231 public XmlAttrConstructor (ExprSequence name, ExprSequence content)
234 this.nameExpr = name;
237 internal override void CheckReference (XQueryASTCompiler compiler)
239 if (nameExpr != null)
240 nameExpr.CheckReference (compiler);
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);
252 for (int i = 0; i < Content.Count; i++)
253 Content [i] = Content [i].Compile (compiler);
257 public XmlQualifiedName 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);
294 case XmlTypeCode.String:
296 // nonprefixed attribute name == element's local namespace
297 if (value.Value.IndexOf (':') < 0)
298 name = new XmlQualifiedName (value.Value);
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));
307 // FIXME: add more info
308 throw new XmlQueryException ("A name of an attribute constructor must be resolved to either a QName or string.");
316 internal class XmlNSConstructor : XmlConstructorExpr
318 public XmlNSConstructor (string prefix, ExprSequence content)
323 internal override void CheckReference (XQueryASTCompiler compiler)
325 Content.CheckReference (compiler);
328 #region CompileAndEvaluate
329 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
332 for (int i = 0; i < Content.Count; i++)
333 Content [i] = Content [i].Compile (compiler);
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)
345 throw new NotImplementedException ();
348 public override XPathSequence Evaluate (XPathSequence iter)
351 throw new NotImplementedException ();
356 internal class XmlDocConstructor : XmlConstructorExpr
358 public XmlDocConstructor (ExprSequence content)
363 internal override void CheckReference (XQueryASTCompiler compiler)
366 Content.CheckReference (compiler);
369 #region CompileAndEvaluate
370 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
373 for (int i = 0; i < Content.Count; i++)
374 Content [i] = Content [i].Compile (compiler);
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);
398 internal class XmlTextConstructor : XmlConstructorExpr
400 public XmlTextConstructor (string text)
406 public XmlTextConstructor (ExprSequence content)
413 public string LiteralText {
417 internal override void CheckReference (XQueryASTCompiler compiler)
420 Content.CheckReference (compiler);
423 #region CompileAndEvaluate
424 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
427 for (int i = 0; i < Content.Count; i++)
428 Content [i] = Content [i].Compile (compiler);
432 public override SequenceType StaticType {
433 get { return SequenceType.Text; }
436 public override void Serialize (XPathSequence iter)
439 iter.Context.Writer.WriteString (Atomize (new ExprSequenceIterator (iter, Content)).Value);
441 iter.Context.Writer.WriteString (LiteralText);
444 public override XPathSequence Evaluate (XPathSequence iter)
446 return EvaluateNode (iter);
451 internal class XmlCommentConstructor : XmlConstructorExpr
453 string contentLiteral;
455 public XmlCommentConstructor (string content)
458 this.contentLiteral = content;
461 public XmlCommentConstructor (ExprSequence content)
466 internal override void CheckReference (XQueryASTCompiler compiler)
469 Content.CheckReference (compiler);
472 #region CompileAndEvaluate
473 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
476 for (int i = 0; i < Content.Count; i++)
477 Content [i] = Content [i].Compile (compiler);
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);
498 internal class XmlPIConstructor : XmlConstructorExpr
501 ExprSequence nameExpr;
503 string contentLiteral;
505 public XmlPIConstructor (string name, string content)
509 this.contentLiteral = content;
512 public XmlPIConstructor (string name, ExprSequence content)
518 public XmlPIConstructor (ExprSequence name, ExprSequence content)
521 this.nameExpr = name;
524 internal override void CheckReference (XQueryASTCompiler compiler)
526 if (nameExpr != null)
527 nameExpr.CheckReference (compiler);
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);
539 for (int i = 0; i < Content.Count; i++)
540 Content [i] = Content [i].Compile (compiler);
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 (
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)
573 return Atomize (new ExprSequenceIterator (iter, NameExpr)).Value;