2003-08-04 Ben Maurer <bmaurer@users.sourceforge.net>
[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 == null) return null;
101                         if (avt.simpleString != null) {
102                                 string s = avt.simpleString;
103                                 avt = null;
104                                 return s;
105                         }
106                         return null;
107                 }
108                 
109                 public string Evaluate (XslTransformProcessor p)
110                 {
111                         if (simpleString != null) return simpleString;
112                                 
113                         StringBuilder sb = new StringBuilder ();
114                         
115                         foreach (AvtPart part in avtParts)
116                                 sb.Append (part.Evaluate (p));
117                                 
118                         return sb.ToString ();
119                 }
120                 
121                 // Represents part of an AVT
122                 abstract class AvtPart {
123                         public abstract string Evaluate (XslTransformProcessor p);
124                 }
125                 
126                 sealed class SimpleAvtPart : AvtPart {
127                         string val;
128                         public SimpleAvtPart (string val)
129                         {
130                                 this.val = val;
131                         }
132                         
133                         public override string Evaluate (XslTransformProcessor p)
134                         {
135                                 return val;
136                         }
137                 }
138                 
139                 sealed class XPathAvtPart : AvtPart {
140                         XPathExpression expr;
141                         
142                         public XPathAvtPart (XPathExpression expr)
143                         {
144                                 this.expr = expr;
145                         }
146                         
147                         public override string Evaluate (XslTransformProcessor p)
148                         {
149                                 return p.EvaluateString (expr);
150                         }
151                 }
152         }
153 }