Here comes managed XSLT! WOOOOOHOOOOOO!
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl.Operations / XslAvt.cs
1 //
2 // XslAvt.cs
3 //
4 // Author:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //
7 // (C) 2003 Ben Maurer
8 //
9
10 using System;
11 using System.Collections;
12 using System.IO;
13 using System.Text;
14 using System.Xml;
15 using System.Xml.XPath;
16 using System.Xml.Xsl;
17
18 namespace Mono.Xml.Xsl.Operations {
19         // Represents an Attribute Value Template in XSL.
20         public class XslAvt {
21                 
22                 string simpleString;
23                 ArrayList avtParts;
24                 
25                 public XslAvt (string str, Compiler comp) {
26                         if (str.IndexOf ("{") == -1 && str.IndexOf ("}") == -1) {
27                                 // That was easy ;-).
28                                 simpleString = str;
29                                 return;
30                         }
31                         avtParts = new ArrayList ();
32                         StringBuilder sb = new StringBuilder ();
33                         StringReader r = new StringReader (str);
34                         
35                         
36                         
37                         while (r.Peek () != -1) {
38                                 char c = (char)r.Read ();
39                                 switch (c) {                                    
40                                 case '{':
41                                         if ((char)r.Peek () == '{') {
42                                                 // {{ == escaped {
43                                                 sb.Append ((char)r.Read ());
44                                                 break;
45                                         }
46                                         
47                                         if (sb.Length != 0) {
48                                                 // Ok, we have already found a text
49                                                 // part, lets save that.
50                                                 avtParts.Add (new SimpleAvtPart (sb.ToString ()));
51                                                 sb.Length = 0;
52                                         }
53                                         
54                                         while ((c = (char)r.Read ()) != '}') {
55                                                 switch (c) {
56                                                 case '\'': case '"': {
57                                                         // We are inside a quote
58                                                         char unq = c;
59                                                         sb.Append (c);
60                                                         while ((c = (char)r.Read ()) != unq) {
61                                                                 sb.Append (c);
62                                                                 if (r.Peek () == -1) throw new Exception ("unexpected end of AVT");
63                                                         }
64                                                                 
65                                                         
66                                                         sb.Append (c);
67                                                         break;
68                                                 } // ' or "
69                                                 default:
70                                                         sb.Append (c);
71                                                         break;
72                                                 }
73                                                 if (r.Peek () == -1) throw new Exception ("unexpected end of AVT");
74                                         }
75                                         
76                                                 
77                                         avtParts.Add (new XPathAvtPart (comp.CompileExpression (sb.ToString ())));
78                                         sb.Length = 0;
79                                         break;
80                                 case '}':
81                                         c = (char)r.Read ();
82                                         if (c != '}')
83                                                 throw new Exception ("Braces must be escaped");
84                                         goto default;
85                                 default:
86                                         sb.Append (c);
87                                         break;
88                                 }
89                         }
90                         if (sb.Length != 0) {
91                                 // Ok, we have already found a text
92                                 // part, lets save that.
93                                 avtParts.Add (new SimpleAvtPart (sb.ToString ()));
94                                 sb.Length = 0;
95                         }
96                 }
97                 
98                 public static string AttemptPreCalc (ref XslAvt avt)
99                 {
100                         if (avt.simpleString != null) {
101                                 string s = avt.simpleString;
102                                 avt = null;
103                                 return s;
104                         }
105                         return null;
106                 }
107                 
108                 public string Evaluate (XslTransformProcessor p)
109                 {
110                         if (simpleString != null) return simpleString;
111                                 
112                         StringBuilder sb = new StringBuilder ();
113                         
114                         foreach (AvtPart part in avtParts)
115                                 sb.Append (part.Evaluate (p));
116                                 
117                         return sb.ToString ();
118                 }
119                 
120                 // Represents part of an AVT
121                 abstract class AvtPart {
122                         public abstract string Evaluate (XslTransformProcessor p);
123                 }
124                 
125                 sealed class SimpleAvtPart : AvtPart {
126                         string val;
127                         public SimpleAvtPart (string val)
128                         {
129                                 this.val = val;
130                         }
131                         
132                         public override string Evaluate (XslTransformProcessor p)
133                         {
134                                 return val;
135                         }
136                 }
137                 
138                 sealed class XPathAvtPart : AvtPart {
139                         XPathExpression expr;
140                         
141                         public XPathAvtPart (XPathExpression expr)
142                         {
143                                 this.expr = expr;
144                         }
145                         
146                         public override string Evaluate (XslTransformProcessor p)
147                         {
148                                 return p.XPToString (p.Evaluate (expr));
149                         }
150                 }
151         }
152 }