5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
9 // (C) 2003 Atsushi Enomoto
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.Collections
;
36 using System
.Xml
.XPath
;
40 using QName
= System
.Xml
.XmlQualifiedName
;
42 namespace Mono
.Xml
.Xsl
.Operations
{
44 internal class XslVariableInformation
47 XPathExpression
select;
50 public XslVariableInformation (Compiler c
)
52 c
.AssertAttribute ("name");
53 c
.Input
.MoveToFirstAttribute ();
55 if (c
.Input
.NamespaceURI
!= String
.Empty
)
57 switch (c
.Input
.LocalName
) {
62 throw new XsltCompileException ("Invalid attribute " + c
.Input
.Name
, null, c
.Input
);
64 } while (c
.Input
.MoveToNextAttribute ());
65 c
.Input
.MoveToParent ();
67 name
= c
.ParseQNameAttribute ("name");
69 XmlConvert
.VerifyName (name
.Name
);
70 } catch (XmlException ex
) {
71 throw new XsltCompileException ("Variable name is not qualified name.", ex
, c
.Input
);
74 string sel
= c
.GetAttribute ("select");
75 if (sel
!= null && sel
!= "" ) {
76 select = c
.CompileExpression (c
.GetAttribute ("select"));
78 } else if (c
.Input
.MoveToFirstChild ()) {
79 content
= c
.CompileTemplateContent ();
80 c
.Input
.MoveToParent ();
84 public object Evaluate (XslTransformProcessor p
)
87 object o
= p
.Evaluate (select);
88 // To resolve variable references correctly, we
89 // have to collect all the target nodes here.
90 // (otherwise, variables might be resolved with
91 // different level of variable stack in
92 // XslTransformProcessor).
93 if (o
is XPathNodeIterator
) {
94 ArrayList al
= new ArrayList ();
95 XPathNodeIterator iter
= (XPathNodeIterator
) o
;
96 while (iter
.MoveNext ())
97 al
.Add (iter
.Current
);
98 o
= new ListIterator (al
, p
.XPathContext
, false);
101 } else if (content
!= null) {
102 // XmlNodeWriter w = new XmlNodeWriter (false);
103 DTMXPathDocumentWriter w
= new DTMXPathDocumentWriter (p
.CurrentNode
.NameTable
, 200);
104 Outputter outputter
= new GenericOutputter(w
, p
.Outputs
, null, true);
105 p
.PushOutput (outputter
);
106 content
.Evaluate (p
);
108 // return w.Document.CreateNavigator ().SelectChildren (XPathNodeType.All);
109 // return w.CreateDocument ().CreateNavigator ().SelectChildren (XPathNodeType.All);
110 // return w.Document.CreateNavigator ();
111 return w
.CreateDocument ().CreateNavigator ();
117 public QName Name { get { return name; }}
120 internal abstract class XslGeneralVariable
: XslCompiledElement
, IXsltContextVariable
{
121 protected XslVariableInformation
var;
123 public XslGeneralVariable (Compiler c
) : base (c
) {}
125 protected override void Compile (Compiler c
)
127 this.var = new XslVariableInformation (c
);
130 public override abstract void Evaluate (XslTransformProcessor p
);
131 protected abstract object GetValue (XslTransformProcessor p
);
134 public object Evaluate (XsltContext xsltContext
)
136 object value = GetValue (((XsltCompiledContext
)xsltContext
).Processor
);
138 if (value is XPathNodeIterator
)
139 return ((XPathNodeIterator
)value).Clone ();
144 public QName Name {get {return var.Name;}}
145 public XPathResultType VariableType { get {return XPathResultType.Any;}}
146 public abstract bool IsLocal { get; }
147 public abstract bool IsParam { get; }
150 internal class XslGlobalVariable
: XslGeneralVariable
{
151 public XslGlobalVariable (Compiler c
) : base (c
) {}
152 static object busyObject
= new Object ();
155 public override void Evaluate (XslTransformProcessor p
)
157 Hashtable varInfo
= p
.globalVariableTable
;
159 if (varInfo
.Contains (this)) {
160 if (varInfo
[this] == busyObject
)
161 throw new XsltException ("Circular dependency was detected.", null, p
.CurrentNode
);
165 varInfo
[this] = busyObject
;
166 varInfo
[this] = var.Evaluate (p
);
170 protected override object GetValue (XslTransformProcessor p
)
173 return p
.globalVariableTable
[this];
176 public override bool IsLocal { get { return false; }}
177 public override bool IsParam { get { return false; }}
180 internal class XslGlobalParam
: XslGlobalVariable
{
184 public XslGlobalParam (Compiler c
) : base (c
) {}
186 public void Override (XslTransformProcessor p
, object paramVal
)
188 Debug
.Assert (!p
.globalVariableTable
.Contains (this), "Shouldn't have been evaluated by this point");
190 p
.globalVariableTable
[this] = paramVal
;
193 public override bool IsParam { get { return true; }}
196 internal class XslLocalVariable
: XslGeneralVariable
{
199 public XslLocalVariable (Compiler c
) : base (c
)
201 slot
= c
.AddVariable (this);
204 public override void Evaluate (XslTransformProcessor p
)
206 p
.SetStackItem (slot
, var.Evaluate (p
));
209 protected override object GetValue (XslTransformProcessor p
)
211 return p
.GetStackItem (slot
);
214 public bool IsEvaluated (XslTransformProcessor p
)
216 return p
.GetStackItem (slot
) != null;
219 public override bool IsLocal { get { return true; }}
220 public override bool IsParam { get { return false; }}
223 internal class XslLocalParam
: XslLocalVariable
{
227 public XslLocalParam (Compiler c
) : base (c
) {}
229 public override void Evaluate (XslTransformProcessor p
)
231 if (p
.GetStackItem (slot
) != null)
232 return; // evaluated already
237 public void Override (XslTransformProcessor p
, object paramVal
)
239 p
.SetStackItem (slot
, paramVal
);
242 public override bool IsParam { get { return true; }}
245 internal class XPathVariableBinding
: Expression
{
246 XslGeneralVariable v
;
247 public XPathVariableBinding (XslGeneralVariable v
)
251 public override String
ToString () { return "$" + v.Name.ToString (); }
252 public override XPathResultType ReturnType { get { return XPathResultType.Any; }}
253 public override XPathResultType
GetReturnType (BaseIterator iter
)
255 return XPathResultType
.Any
;
258 public override object Evaluate (BaseIterator iter
)
260 return v
.Evaluate (iter
.NamespaceManager
as XsltContext
);