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
;