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;
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)
64 foreach (ExprSingle expr in Content)
65 expr.Serialize (iter);
68 internal IXmlNamespaceResolver GetNSResolver (XPathSequence iter)
70 // FIXME: IXmlNamespaceResolver must be constructed
71 // considering 1)static context and 2)in-scope element
78 internal class XmlAttrConstructorList : CollectionBase
80 public XmlAttrConstructorList ()
84 public void Add (XmlAttrConstructor item)
89 public void Insert (int pos, XmlAttrConstructor item)
91 List.Insert (pos, item);
95 internal class XmlElemConstructor : XmlConstructorExpr
97 XmlQualifiedName name;
98 ExprSequence nameExpr;
100 public XmlElemConstructor (XmlQualifiedName name, ExprSequence content)
106 public XmlElemConstructor (ExprSequence name, ExprSequence content)
109 this.name = XmlQualifiedName.Empty;
110 this.nameExpr = name;
113 public XmlQualifiedName Name {
116 public ExprSequence NameExpr {
117 get { return nameExpr; }
120 internal override void CheckReference (XQueryASTCompiler compiler)
122 if (nameExpr != null)
123 nameExpr.CheckReference (compiler);
125 Content.CheckReference (compiler);
128 #region CompileAndEvaluate
129 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
131 if (NameExpr != null)
132 for (int i = 0; i < NameExpr.Count; i++)
133 NameExpr [i] = NameExpr [i].Compile (compiler);
135 for (int i = 0; i < Content.Count; i++)
136 Content [i] = Content [i].Compile (compiler);
140 // FIXME: can be optimized by checking all items in Expr
141 public override SequenceType StaticType {
142 get { return SequenceType.Element; }
145 public override void Serialize (XPathSequence iter)
147 XmlQualifiedName name = EvaluateName (iter);
148 XmlWriter w = iter.Context.Writer;
149 w.WriteStartElement (iter.Context.LookupPrefix (name.Namespace), name.Name, name.Namespace);
150 SerializeContent (iter);
151 w.WriteEndElement ();
154 public override XPathSequence Evaluate (XPathSequence iter)
156 XmlQualifiedName name = EvaluateName (iter);
158 XPathDocument doc = new XPathDocument ();
159 XmlWriter w = iter.Context.Writer;
161 iter.Context.Writer = doc.CreateWriter ();
163 iter.Context.Writer.Close ();
165 iter.Context.Writer = w;
167 XPathNavigator nav = doc.CreateNavigator ();
168 nav.MoveToFirstChild ();
169 return new SingleItemIterator (nav, iter);
172 private XmlQualifiedName EvaluateName (XPathSequence iter)
174 XmlQualifiedName name = Name;
175 if (NameExpr != null) {
176 XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
177 IXmlNamespaceResolver res = iter.Context.NSResolver;
179 switch (value.XmlType.TypeCode) {
180 case XmlTypeCode.QName:
181 name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
183 case XmlTypeCode.String:
185 name = XmlQualifiedName.Parse (value.Value, res);
186 } catch (ArgumentException ex) {
187 // FIXME: add more info
188 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));
192 // FIXME: add more info
193 throw new XmlQueryException ("A name of an element constructor must be resolved to either a QName or string.");
201 internal class XmlAttrConstructor : XmlConstructorExpr
203 XmlQualifiedName name;
204 ExprSequence nameExpr;
206 public XmlAttrConstructor (XmlQualifiedName name, ExprSequence content)
212 public XmlAttrConstructor (ExprSequence name, ExprSequence content)
215 this.nameExpr = name;
218 internal override void CheckReference (XQueryASTCompiler compiler)
220 if (nameExpr != null)
221 nameExpr.CheckReference (compiler);
223 Content.CheckReference (compiler);
226 #region CompileAndEvaluate
227 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
229 if (NameExpr != null)
230 for (int i = 0; i < NameExpr.Count; i++)
231 NameExpr [i] = NameExpr [i].Compile (compiler);
233 for (int i = 0; i < Content.Count; i++)
234 Content [i] = Content [i].Compile (compiler);
238 public XmlQualifiedName Name {
239 get { throw new NotImplementedException (); }
241 public ExprSequence NameExpr {
242 get { throw new NotImplementedException (); }
245 // FIXME: can be optimized by checking all items in Expr
246 public override SequenceType StaticType {
247 get { return SequenceType.Attribute; }
250 public override void Serialize (XPathSequence iter)
252 XmlQualifiedName name = EvaluateName (iter);
253 XmlWriter w = iter.Context.Writer;
254 w.WriteStartAttribute (GetNSResolver (iter).LookupPrefix (name.Namespace), name.Name, name.Namespace);
255 SerializeContent (iter);
256 w.WriteEndAttribute ();
259 public override XPathSequence Evaluate (XPathSequence iter)
261 XmlQualifiedName name = EvaluateName (iter);
263 XPathDocument doc = new XPathDocument ();
264 XmlWriter w = iter.Context.Writer;
266 iter.Context.Writer = doc.CreateEditor ().CreateAttributes ();
267 // FIXME: maybe container element is required?
269 iter.Context.Writer.Close ();
271 iter.Context.Writer = w;
273 XPathNavigator nav = doc.CreateNavigator ();
274 nav.MoveToFirstAttribute ();
275 return new SingleItemIterator (nav, iter);
278 private XmlQualifiedName EvaluateName (XPathSequence iter)
280 XmlQualifiedName name = Name;
281 if (NameExpr != null) {
282 XPathAtomicValue value = Atomize (new ExprSequenceIterator (iter, NameExpr));
283 IXmlNamespaceResolver res = GetNSResolver (iter);
285 switch (value.XmlType.TypeCode) {
286 case XmlTypeCode.QName:
287 name = (XmlQualifiedName) value.ValueAs (typeof (XmlQualifiedName), res);
289 case XmlTypeCode.String:
291 // nonprefixed attribute name == element's local namespace
292 if (value.Value.IndexOf (':') < 0)
293 name = new XmlQualifiedName (value.Value);
295 name = XmlQualifiedName.Parse (value.Value, res);
296 } catch (ArgumentException ex) {
297 // FIXME: add more info
298 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));
302 // FIXME: add more info
303 throw new XmlQueryException ("A name of an attribute constructor must be resolved to either a QName or string.");
311 internal class XmlNSConstructor : XmlConstructorExpr
313 public XmlNSConstructor (string prefix, ExprSequence content)
318 internal override void CheckReference (XQueryASTCompiler compiler)
320 Content.CheckReference (compiler);
323 #region CompileAndEvaluate
324 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
327 for (int i = 0; i < Content.Count; i++)
328 Content [i] = Content [i].Compile (compiler);
332 // FIXME: can be optimized by checking all items in Expr
333 public override SequenceType StaticType {
334 get { return SequenceType.Namespace; }
337 public override void Serialize (XPathSequence iter)
340 throw new NotImplementedException ();
343 public override XPathSequence Evaluate (XPathSequence iter)
346 throw new NotImplementedException ();
351 internal class XmlDocConstructor : XmlConstructorExpr
353 public XmlDocConstructor (ExprSequence content)
358 internal override void CheckReference (XQueryASTCompiler compiler)
361 Content.CheckReference (compiler);
364 #region CompileAndEvaluate
365 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
368 for (int i = 0; i < Content.Count; i++)
369 Content [i] = Content [i].Compile (compiler);
373 // FIXME: can be optimized by checking all items in Expr
374 public override SequenceType StaticType {
375 get { return SequenceType.Document; }
378 public override void Serialize (XPathSequence iter)
380 XmlWriter w = iter.Context.Writer;
381 w.WriteStartDocument ();
382 SerializeContent (iter);
383 w.WriteEndDocument ();
386 public override XPathSequence Evaluate (XPathSequence iter)
388 throw new NotImplementedException ();
393 internal class XmlTextConstructor : XmlConstructorExpr
395 public XmlTextConstructor (string text)
400 public XmlTextConstructor (ExprSequence content)
405 internal override void CheckReference (XQueryASTCompiler compiler)
408 Content.CheckReference (compiler);
411 #region CompileAndEvaluate
412 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
415 for (int i = 0; i < Content.Count; i++)
416 Content [i] = Content [i].Compile (compiler);
420 // FIXME: can be optimized by checking all items in Expr
421 public override SequenceType StaticType {
422 get { return SequenceType.Text; }
425 public override void Serialize (XPathSequence iter)
427 iter.Context.Writer.WriteString (Atomize (new ExprSequenceIterator (iter, Content)).Value);
430 public override XPathSequence Evaluate (XPathSequence iter)
432 throw new NotImplementedException ();
437 internal class XmlCommentConstructor : XmlConstructorExpr
439 string contentLiteral;
441 public XmlCommentConstructor (string content)
444 this.contentLiteral = content;
447 public XmlCommentConstructor (ExprSequence content)
452 internal override void CheckReference (XQueryASTCompiler compiler)
455 Content.CheckReference (compiler);
458 #region CompileAndEvaluate
459 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
462 for (int i = 0; i < Content.Count; i++)
463 Content [i] = Content [i].Compile (compiler);
467 // FIXME: can be optimized by checking all items in Expr
468 public override SequenceType StaticType {
469 get { return SequenceType.Comment; }
472 public override void Serialize (XPathSequence iter)
474 iter.Context.Writer.WriteComment (Atomize (new ExprSequenceIterator (iter, Content)).Value);
477 public override XPathSequence Evaluate (XPathSequence iter)
479 throw new NotImplementedException ();
484 internal class XmlPIConstructor : XmlConstructorExpr
487 ExprSequence nameExpr;
489 string contentLiteral;
491 public XmlPIConstructor (string name, string content)
495 this.contentLiteral = content;
498 public XmlPIConstructor (string name, ExprSequence content)
504 public XmlPIConstructor (ExprSequence name, ExprSequence content)
507 this.nameExpr = name;
510 internal override void CheckReference (XQueryASTCompiler compiler)
512 if (nameExpr != null)
513 nameExpr.CheckReference (compiler);
515 Content.CheckReference (compiler);
518 #region CompileAndEvaluate
519 internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
521 if (NameExpr != null)
522 for (int i = 0; i < NameExpr.Count; i++)
523 NameExpr [i] = NameExpr [i].Compile (compiler);
525 for (int i = 0; i < Content.Count; i++)
526 Content [i] = Content [i].Compile (compiler);
531 get { throw new NotImplementedException (); }
533 public ExprSequence NameExpr {
534 get { throw new NotImplementedException (); }
537 // FIXME: can be optimized by checking all items in Expr
538 public override SequenceType StaticType {
539 get { return SequenceType.XmlPI; }
542 public override void Serialize (XPathSequence iter)
544 iter.Context.Writer.WriteProcessingInstruction (
546 Atomize (new ExprSequenceIterator (iter, Content)).Value);
549 public override XPathSequence Evaluate (XPathSequence iter)
551 throw new NotImplementedException ();
554 private string GetName (XPathSequence iter)
556 if (Name != String.Empty)
558 return Atomize (new ExprSequenceIterator (iter, NameExpr)).Value;