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.
30 using System.Collections;
32 using System.Xml.Query;
33 using System.Xml.Schema;
34 using System.Xml.XPath;
35 using Mono.Xml.XPath2;
38 namespace Mono.Xml.XQuery
40 internal abstract class XmlConstructorExpr : ExprSingle
42 public XmlConstructorExpr (ExprSequence content)
44 this.content = content;
49 public ExprSequence Content {
50 get { return content; }
53 #region CompileAndEvaluate
54 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
57 for (int i = 0; i < Content.Count; i++)
58 Content [i] = Content [i].Compile (compiler);
62 public void SerializeContent (XPathSequence iter)
65 foreach (ExprSingle expr in Content)
66 expr.Serialize (iter);
69 internal IXmlNamespaceResolver GetNSResolver (XPathSequence iter)
71 // FIXME: IXmlNamespaceResolver must be constructed
72 // considering 1)static context and 2)in-scope element
77 public XPathSequence EvaluateNode (XPathSequence iter)
79 return EvaluateNode (iter, XPathNodeType.All);
82 public XPathSequence EvaluateNode (XPathSequence iter, XPathNodeType moveAfterCreation)
84 XmlDocument doc = new XmlDocument ();
85 XmlWriter w = iter.Context.Writer;
87 iter.Context.Writer = doc.CreateNavigator ().AppendChild ();
89 iter.Context.Writer.Close ();
91 iter.Context.Writer = w;
93 XPathNavigator nav = doc.CreateNavigator ();
94 switch (moveAfterCreation) {
95 case XPathNodeType.Attribute:
96 nav.MoveToFirstAttribute ();
98 case XPathNodeType.Root:
101 nav.MoveToFirstChild ();
104 return new SingleItemIterator (nav, iter.Context);
109 internal class XmlAttrConstructorList : CollectionBase
111 public XmlAttrConstructorList ()
115 public void Add (XmlAttrConstructor item)
120 public void Insert (int pos, XmlAttrConstructor item)
122 List.Insert (pos, item);
126 internal class XmlElemConstructor : XmlConstructorExpr
128 XmlQualifiedName name;
129 ExprSequence nameExpr;
131 public XmlElemConstructor (XmlQualifiedName name, ExprSequence content)
137 public XmlElemConstructor (ExprSequence name, ExprSequence content)
140 this.name = XmlQualifiedName.Empty;
141 this.nameExpr = name;
144 public XmlQualifiedName Name {
147 public ExprSequence NameExpr {
148 get { return nameExpr; }
151 internal override void CheckReference (XQueryASTCompiler compiler)
153 if (nameExpr != null)
154 nameExpr.CheckReference (compiler);
156 Content.CheckReference (compiler);
159 #region CompileAndEvaluate
160 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
162 if (NameExpr != null)
163 for (int i = 0; i < NameExpr.Count; i++)
164 NameExpr [i] = NameExpr [i].Compile (compiler);
166 for (int i = 0; i < Content.Count; i++)
167 Content [i] = Content [i].Compile (compiler);
171 // FIXME: can be optimized by checking all items in Expr
172 public override SequenceType StaticType {
173 get { return SequenceType.Element; }
176 public override void Serialize (XPathSequence iter)
178 XmlQualifiedName name = EvaluateName (iter);
179 XmlWriter w = iter.Context.Writer;
180 w.WriteStartElement (iter.Context.LookupPrefix (name.Namespace), name.Name, name.Namespace);
181 SerializeContent (iter);
182 w.WriteEndElement ();
185 public override XPathSequence Evaluate (XPathSequence iter)
187 return EvaluateNode (iter);
190 private XmlQualifiedName EvaluateName (XPathSequence iter)
192 XmlQualifiedName name = Name;
193 if (NameExpr != null) {
194 XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
195 IXmlNamespaceResolver res = iter.Context.NSResolver;
197 switch (value.XmlType.TypeCode) {
198 case XmlTypeCode.QName:
199 name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
201 case XmlTypeCode.String:
203 name = InternalPool.ParseQName (value.Value, res);
204 } catch (ArgumentException ex) {
205 // FIXME: add more info
206 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));
210 // FIXME: add more info
211 throw new XmlQueryException ("A name of an element constructor must be resolved to either a QName or string.");
219 internal class XmlAttrConstructor : XmlConstructorExpr
221 XmlQualifiedName name;
222 ExprSequence nameExpr;
224 public XmlAttrConstructor (XmlQualifiedName name, ExprSequence content)
230 public XmlAttrConstructor (ExprSequence name, ExprSequence content)
233 this.nameExpr = name;
236 internal override void CheckReference (XQueryASTCompiler compiler)
238 if (nameExpr != null)
239 nameExpr.CheckReference (compiler);
241 Content.CheckReference (compiler);
244 #region CompileAndEvaluate
245 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
247 if (NameExpr != null)
248 for (int i = 0; i < NameExpr.Count; i++)
249 NameExpr [i] = NameExpr [i].Compile (compiler);
251 for (int i = 0; i < Content.Count; i++)
252 Content [i] = Content [i].Compile (compiler);
256 public XmlQualifiedName Name {
259 public ExprSequence NameExpr {
260 get { return nameExpr; }
263 // FIXME: can be optimized by checking all items in Expr
264 public override SequenceType StaticType {
265 get { return SequenceType.Attribute; }
268 public override void Serialize (XPathSequence iter)
270 XmlQualifiedName name = EvaluateName (iter);
271 XmlWriter w = iter.Context.Writer;
272 w.WriteStartAttribute (GetNSResolver (iter).LookupPrefix (name.Namespace), name.Name, name.Namespace);
273 SerializeContent (iter);
274 w.WriteEndAttribute ();
277 public override XPathSequence Evaluate (XPathSequence iter)
279 return EvaluateNode (iter, XPathNodeType.Attribute);
282 private XmlQualifiedName EvaluateName (XPathSequence iter)
284 XmlQualifiedName name = Name;
285 if (NameExpr != null) {
286 XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
287 IXmlNamespaceResolver res = GetNSResolver (iter);
289 switch (value.XmlType.TypeCode) {
290 case XmlTypeCode.QName:
291 name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
293 case XmlTypeCode.String:
295 // nonprefixed attribute name == element's local namespace
296 if (value.Value.IndexOf (':') < 0)
297 name = new XmlQualifiedName (value.Value);
299 name = InternalPool.ParseQName (value.Value, res);
300 } catch (ArgumentException ex) {
301 // FIXME: add more info
302 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));
306 // FIXME: add more info
307 throw new XmlQueryException ("A name of an attribute constructor must be resolved to either a QName or string.");
315 internal class XmlNSConstructor : XmlConstructorExpr
317 public XmlNSConstructor (string prefix, ExprSequence content)
322 internal override void CheckReference (XQueryASTCompiler compiler)
324 Content.CheckReference (compiler);
327 #region CompileAndEvaluate
328 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
331 for (int i = 0; i < Content.Count; i++)
332 Content [i] = Content [i].Compile (compiler);
336 // FIXME: can be optimized by checking all items in Expr
337 public override SequenceType StaticType {
338 get { return SequenceType.Namespace; }
341 public override void Serialize (XPathSequence iter)
344 throw new NotImplementedException ();
347 public override XPathSequence Evaluate (XPathSequence iter)
350 throw new NotImplementedException ();
355 internal class XmlDocConstructor : XmlConstructorExpr
357 public XmlDocConstructor (ExprSequence content)
362 internal override void CheckReference (XQueryASTCompiler compiler)
365 Content.CheckReference (compiler);
368 #region CompileAndEvaluate
369 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
372 for (int i = 0; i < Content.Count; i++)
373 Content [i] = Content [i].Compile (compiler);
377 // FIXME: can be optimized by checking all items in Expr
378 public override SequenceType StaticType {
379 get { return SequenceType.Document; }
382 public override void Serialize (XPathSequence iter)
384 XmlWriter w = iter.Context.Writer;
385 w.WriteStartDocument ();
386 SerializeContent (iter);
387 w.WriteEndDocument ();
390 public override XPathSequence Evaluate (XPathSequence iter)
392 return EvaluateNode (iter, XPathNodeType.Root);
397 internal class XmlTextConstructor : XmlConstructorExpr
399 public XmlTextConstructor (string text)
405 public XmlTextConstructor (ExprSequence content)
412 public string LiteralText {
416 internal override void CheckReference (XQueryASTCompiler compiler)
419 Content.CheckReference (compiler);
422 #region CompileAndEvaluate
423 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
426 for (int i = 0; i < Content.Count; i++)
427 Content [i] = Content [i].Compile (compiler);
431 public override SequenceType StaticType {
432 get { return SequenceType.Text; }
435 public override void Serialize (XPathSequence iter)
438 iter.Context.Writer.WriteString (Atomize (new ExprSequenceIterator (iter, Content)).Value);
440 iter.Context.Writer.WriteString (LiteralText);
443 public override XPathSequence Evaluate (XPathSequence iter)
445 return EvaluateNode (iter);
450 internal class XmlCommentConstructor : XmlConstructorExpr
452 string contentLiteral;
454 public XmlCommentConstructor (string content)
457 this.contentLiteral = content;
460 public XmlCommentConstructor (ExprSequence content)
465 internal override void CheckReference (XQueryASTCompiler compiler)
468 Content.CheckReference (compiler);
471 #region CompileAndEvaluate
472 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
475 for (int i = 0; i < Content.Count; i++)
476 Content [i] = Content [i].Compile (compiler);
480 // FIXME: can be optimized by checking all items in Expr
481 public override SequenceType StaticType {
482 get { return SequenceType.Comment; }
485 public override void Serialize (XPathSequence iter)
487 iter.Context.Writer.WriteComment (Atomize (new ExprSequenceIterator (iter, Content)).Value);
490 public override XPathSequence Evaluate (XPathSequence iter)
492 return EvaluateNode (iter);
497 internal class XmlPIConstructor : XmlConstructorExpr
500 ExprSequence nameExpr;
502 string contentLiteral;
504 public XmlPIConstructor (string name, string content)
508 this.contentLiteral = content;
511 public XmlPIConstructor (string name, ExprSequence content)
517 public XmlPIConstructor (ExprSequence name, ExprSequence content)
520 this.nameExpr = name;
523 internal override void CheckReference (XQueryASTCompiler compiler)
525 if (nameExpr != null)
526 nameExpr.CheckReference (compiler);
528 Content.CheckReference (compiler);
531 #region CompileAndEvaluate
532 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
534 if (NameExpr != null)
535 for (int i = 0; i < NameExpr.Count; i++)
536 NameExpr [i] = NameExpr [i].Compile (compiler);
538 for (int i = 0; i < Content.Count; i++)
539 Content [i] = Content [i].Compile (compiler);
547 public ExprSequence NameExpr {
548 get { return nameExpr; }
551 // FIXME: can be optimized by checking all items in Expr
552 public override SequenceType StaticType {
553 get { return SequenceType.XmlPI; }
556 public override void Serialize (XPathSequence iter)
558 iter.Context.Writer.WriteProcessingInstruction (
560 Atomize (new ExprSequenceIterator (iter, Content)).Value);
563 public override XPathSequence Evaluate (XPathSequence iter)
565 return EvaluateNode (iter);
568 private string GetName (XPathSequence iter)
570 if (Name != String.Empty)
572 return Atomize (new ExprSequenceIterator (iter, NameExpr)).Value;