KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > kawa > xslt > XslTranslator


1 // Copyright (c) 2002, 2003 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.kawa.xslt;
5 import gnu.lists.*;
6 import gnu.math.*;
7 import gnu.bytecode.*;
8 import gnu.expr.*;
9 import gnu.text.*;
10 import gnu.mapping.*;
11 import java.util.Stack JavaDoc;
12 import gnu.xml.*;
13 import gnu.kawa.xml.*;
14 import gnu.xquery.lang.*;
15 import gnu.kawa.functions.AppendValues;
16
17 /** Translate an XSLT stylesheet to a Kawa Expression tree. */
18
19 public class XslTranslator extends Lexer implements Consumer
20 {
21   boolean inTemplate;
22   Declaration consumerDecl;
23   StringBuffer JavaDoc nesting = new StringBuffer JavaDoc(100);
24   ModuleExp mexp;
25   Compilation comp;
26
27   /** We seen a beginAttribute but not the closing endAttribute. */
28   boolean inAttribute;
29   /** The 'attribute type' from the most recent beginAttribute. */
30   Object JavaDoc attributeType;
31   /** Buffer to acumulate the value of the current attribute. */
32   StringBuffer JavaDoc attributeValue = new StringBuffer JavaDoc(100);
33
34   XSLT interpreter;
35   XMLParser parser;
36
37   /** Non-null if we're inside an xsl:template. */
38   LambdaExp templateLambda;
39
40   XslTranslator(InPort inp, gnu.text.SourceMessages messages,
41         XSLT interpreter)
42   {
43     super(inp, messages);
44     this.interpreter = interpreter;
45     parser = new XMLParser(inp, messages, this);
46   }
47
48   static final String JavaDoc XSL_TRANSFORM_URI
49   = "http://www.w3.org/1999/XSL/Transform";
50
51   public String JavaDoc popMatchingAttribute(String JavaDoc ns, String JavaDoc name, int start)
52   {
53     int size = comp.exprStack.size();
54     for (int i = start; i < size; i++)
55       {
56     Object JavaDoc el = comp.exprStack.elementAt(start);
57     if (! (el instanceof ApplyExp))
58       return null;
59     ApplyExp aexp = (ApplyExp) el;
60     Expression function = aexp.getFunction();
61     if (aexp.getFunction() != MakeAttribute.makeAttributeExp)
62       return null;
63     Expression[] args = aexp.getArgs();
64     if (args.length != 2)
65       return null;
66     Expression arg0 = args[0];
67     if (! (arg0 instanceof QuoteExp))
68       return null;
69     Object JavaDoc tag = ((QuoteExp) arg0).getValue();
70     if (! (tag instanceof Symbol))
71       return null;
72     Symbol stag = (Symbol) tag;
73     if (stag.getLocalPart() == name && stag.getNamespaceURI() == ns)
74       {
75         comp.exprStack.removeElementAt(i);
76         return (String JavaDoc) ((QuoteExp) args[1]).getValue();
77       }
78       }
79     return null;
80   }
81
82   Expression popTemplateBody(int start)
83   {
84     // should strip off attributes?
85
int i = comp.exprStack.size() - start;
86     Expression exp;
87     Expression[] args = new Expression[i];
88     while (--i >= 0)
89       args[i] = (Expression) comp.exprStack.pop();
90     return new ApplyExp(AppendValues.appendValues, args);
91   }
92
93   public static String JavaDoc isXslTag (Object JavaDoc type)
94   {
95     if (type instanceof QuoteExp)
96       type = ((QuoteExp) type).getValue();
97     if (! (type instanceof Symbol))
98       return null;
99     Symbol qname = (Symbol) type;
100     if (qname.getNamespaceURI() != XSL_TRANSFORM_URI)
101       return null;
102     return qname.getLocalName();
103   }
104
105   void append(Expression expr)
106   {
107     // FIXME
108
}
109
110   public void beginGroup(Object JavaDoc type)
111   {
112     String JavaDoc xslTag = isXslTag(type);
113     if (xslTag == "template")
114       {
115     if (templateLambda != null)
116       error("nested xsl:template");
117     templateLambda = new LambdaExp();
118     //templateLambda.setFile(getName());
119
//templateLambda.setLine(declLine, declColumn);
120
}
121     if (type instanceof XName)
122       {
123     // This gets rid of namespace "nodes". That's not really right.
124
// We do want to get rid of xmlns:xsl, though, at least. FIXME.
125
XName xn = (XName) type;
126     type = Symbol.make(xn.getNamespaceURI(), xn.getLocalPart(),
127                            xn.getPrefix());
128       }
129     nesting.append((char) comp.exprStack.size());
130     push(type);
131   }
132
133   public void beginAttribute(Object JavaDoc attrType)
134   {
135     if (inAttribute)
136       error('f', "internal error - attribute inside attribute");
137     attributeType = attrType;
138     attributeValue.setLength(0);
139     nesting.append((char) comp.exprStack.size());
140     inAttribute = true;
141   }
142
143   public void endAttribute()
144   {
145     Expression[] args = new Expression[2];
146     args[0] = new QuoteExp(attributeType);
147     args[1] = new QuoteExp(attributeValue.toString());
148     push(new ApplyExp(MakeAttribute.makeAttributeExp, args));
149     nesting.setLength(nesting.length()-1);
150     inAttribute = false;
151   }
152
153   public void endGroup()
154   {
155     int nlen = nesting.length()-1;
156     int start = nesting.charAt(nlen);
157     nesting.setLength(nlen);
158     Expression startTag = (Expression) comp.exprStack.elementAt(start);
159     String JavaDoc xslTag = isXslTag(startTag);
160     if (xslTag == "value-of")
161       {
162     String JavaDoc select = popMatchingAttribute("", "select", start + 1);
163     if (select != null)
164       {
165         Expression exp = interpreter.parseXPath(select, getMessages());
166         exp = new ApplyExp(ClassType.make("gnu.xml.TextUtils")
167                                .getDeclaredMethod("stringValue", 1),
168                                new Expression[] { exp });
169         comp.exprStack.pop();
170         push(exp);
171         return;
172       }
173       }
174     else if (xslTag == "apply-templates")
175       {
176     String JavaDoc select = popMatchingAttribute("", "select", start + 1);
177     String JavaDoc mode = popMatchingAttribute("", "mode", start + 1);
178     Expression[] args
179       = { new QuoteExp(select), resolveQNameExpression(mode) };
180     comp.exprStack.pop();
181     push(new ApplyExp(new QuoteExp(applyTemplatesProc), args));
182       }
183     else if (xslTag == "if")
184       {
185     String JavaDoc select = popMatchingAttribute("", "test", start + 1);
186     Expression test = interpreter.parseXPath(select, getMessages());
187     test = XQParser.booleanValue(test);
188     Expression clause = popTemplateBody(start+1);
189     comp.exprStack.pop();
190     push(new IfExp(test, clause, QuoteExp.voidExp));
191       }
192     else if (xslTag == "stylesheet" || xslTag == "transform")
193       {
194     push(new ApplyExp(new QuoteExp(runStylesheetProc),
195               Expression.noExpressions));
196     Expression body = popTemplateBody(start+1);
197     push(body);
198     mexp.body = body;
199       }
200     else if (xslTag == "template")
201       {
202     String JavaDoc match = popMatchingAttribute("", "match", start + 1);
203     String JavaDoc name = popMatchingAttribute("", "name", start + 1);
204     String JavaDoc priority = popMatchingAttribute("", "priority", start + 1);
205     String JavaDoc mode = popMatchingAttribute("", "mode", start + 1);
206     templateLambda.body = popTemplateBody(start+1);
207     comp.exprStack.pop();
208     Expression[] args = new Expression[5];
209     double prio = 0.0; // FIXME
210
args[0] = resolveQNameExpression(name);
211     args[1] = new QuoteExp(match);
212     args[2] = new QuoteExp(DFloNum.make(prio));
213     args[3] = resolveQNameExpression(mode);
214     args[4] = templateLambda;
215     push(new ApplyExp(new QuoteExp(defineTemplateProc), args));
216     templateLambda = null;
217       }
218     else
219       {
220     Expression[] args = new Expression[comp.exprStack.size() - start];
221     for (int i = args.length; --i >= 0; )
222       args[i] = (Expression) comp.exprStack.pop();
223     // FIXME does not preserve namespace attributes.
224
Expression exp = new ApplyExp(MakeElement.makeElement, args);
225     push(exp);
226     mexp.body = exp;
227       }
228   }
229
230   public void write (int v)
231   {
232     if (inAttribute)
233       {
234         /* #ifdef JAVA5 */
235         // attributeValue.appendCodePoint(v);
236
/* #else */
237         attributeValue.append((char) v);
238         /* #endif */
239       }
240     else
241       {
242         String JavaDoc str;
243         if (v < 0x10000)
244           str = String.valueOf(v);
245         else
246           { // Use surrogates.
247
char[] c2 = { (char) (((v - 0x10000) >> 10) + 0xD800),
248                           (char) ((v & 0x3FF) + 0xDC00) };
249             str = new String JavaDoc(c2);
250           }
251         push(str);
252       }
253   }
254
255   /* #ifdef JAVA5 */
256   // public Consumer append (char v)
257
// {
258
// if (inAttribute)
259
// attributeValue.append(v);
260
// else
261
// push(String.valueOf(v));
262
// return this;
263
// }
264

265   // public Consumer append (CharSequence csq)
266
// {
267
// if (inAttribute)
268
// attributeValue.append(csq);
269
// else
270
// push(csq.toString());
271
// return this;
272
// }
273

274   // public Consumer append (CharSequence csq, int start, int end)
275
// {
276
// return append(csq.subSequence(start, end));
277
// }
278
/* #else */
279   public Consumer append (String JavaDoc str)
280   {
281     if (inAttribute)
282       attributeValue.append(str);
283     else
284       push(str);
285     return this;
286   }
287   /* #endif */
288
289   void push(Expression exp)
290   {
291     comp.exprStack.push(exp);
292   }
293
294   void push(Object JavaDoc value)
295   {
296     push(new QuoteExp(value));
297   }
298
299   public void writeBoolean(boolean v)
300   {
301     if (inAttribute)
302       attributeValue.append(v);
303     else
304       push(v ? QuoteExp.trueExp : QuoteExp.falseExp);
305   }
306
307   public void writeFloat(float v)
308   {
309     if (inAttribute)
310       attributeValue.append(v);
311     else
312       push(DFloNum.make(v));
313   }
314
315   public void writeDouble(double v)
316   {
317     if (inAttribute)
318       attributeValue.append(v);
319     else
320       push(DFloNum.make(v));
321   }
322
323   public void writeInt(int v)
324   {
325     if (inAttribute)
326       attributeValue.append(v);
327     else
328       push(IntNum.make(v));
329   }
330
331   public void writeLong(long v)
332   {
333     if (inAttribute)
334       attributeValue.append(v);
335     else
336       push(IntNum.make(v));
337   }
338
339   public void beginDocument()
340   {
341     
342   }
343
344   public void beginDocument(ModuleExp mexp)
345   {
346     this.mexp = mexp;
347     beginDocument();
348   }
349
350   public void endDocument()
351   {
352   }
353
354   public void writeObject(Object JavaDoc v)
355   {
356     if (inAttribute)
357       attributeValue.append(v);
358     else
359       push(v);
360   }
361
362   public void write(char[] buf, int off, int len)
363   {
364     if (inAttribute)
365       attributeValue.append(buf, off, len);
366     else
367       push(new String JavaDoc(buf, off, len));
368   }
369
370   public void write (String JavaDoc str)
371   {
372     if (inAttribute)
373       attributeValue.append(str);
374     else
375       push(str);
376   }
377
378   /* #ifdef use:java.lang.CharSequence */
379   public void write (CharSequence JavaDoc str, int start, int length)
380   {
381     write(str.subSequence(start, length).toString());
382   }
383   /* #else */
384   // public void write (String str, int start, int length)
385
// {
386
// write(str.substring(start, length));
387
// }
388
/* #endif */
389
390   public boolean ignoring()
391   {
392     return false;
393   }
394
395   public Expression getExpression()
396   {
397     return (Expression) comp.exprStack.pop();
398   }
399
400   public void error (char kind, String JavaDoc message)
401   {
402     getMessages().error(kind, message);
403   }
404
405   /*
406   public void fatal(String message) throws SyntaxException
407   {
408     getMessages().error('f', message);
409     throw new SyntaxException(getMessages());
410   }
411   */

412
413   Expression resolveQNameExpression(String JavaDoc name)
414   {
415     if (name == null)
416       return QuoteExp.nullExp;
417     else
418       return new QuoteExp(Symbol.make(null, name)); // FIXME
419
}
420
421   public void parse (Compilation comp)
422   {
423     this.comp = comp;
424     if (comp.exprStack == null)
425       comp.exprStack = new Stack JavaDoc();
426     ModuleExp mexp = comp.pushNewModule(this);
427     comp.mustCompileHere();
428     beginDocument(mexp);
429     parser.parse();
430     endDocument();
431     comp.pop(mexp);
432   }
433
434   static final ClassType typeXSLT
435     = gnu.bytecode.ClassType.make("gnu.kawa.xslt.XSLT");
436   static final ClassType typeTemplateTable
437     = gnu.bytecode.ClassType.make("gnu.kawa.xslt.TemplateTable");
438   static final Method defineTemplateMethod
439     = typeXSLT.getDeclaredMethod("defineTemplate", 5);
440   static final Method runStylesheetMethod
441     = typeXSLT.getDeclaredMethod("runStylesheet", 0);
442   static final PrimProcedure defineTemplateProc
443     = new PrimProcedure(defineTemplateMethod);
444   static final PrimProcedure runStylesheetProc
445     = new PrimProcedure(runStylesheetMethod);
446   static final Method applyTemplatesMethod
447     = typeXSLT.getDeclaredMethod("applyTemplates", 2);
448   static final PrimProcedure applyTemplatesProc
449     = new PrimProcedure(applyTemplatesMethod);
450 }
451
Popular Tags