1 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 ; 12 import gnu.xml.*; 13 import gnu.kawa.xml.*; 14 import gnu.xquery.lang.*; 15 import gnu.kawa.functions.AppendValues; 16 17 18 19 public class XslTranslator extends Lexer implements Consumer 20 { 21 boolean inTemplate; 22 Declaration consumerDecl; 23 StringBuffer nesting = new StringBuffer (100); 24 ModuleExp mexp; 25 Compilation comp; 26 27 28 boolean inAttribute; 29 30 Object attributeType; 31 32 StringBuffer attributeValue = new StringBuffer (100); 33 34 XSLT interpreter; 35 XMLParser parser; 36 37 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 XSL_TRANSFORM_URI 49 = "http://www.w3.org/1999/XSL/Transform"; 50 51 public String popMatchingAttribute(String ns, String name, int start) 52 { 53 int size = comp.exprStack.size(); 54 for (int i = start; i < size; i++) 55 { 56 Object 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 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 ) ((QuoteExp) args[1]).getValue(); 77 } 78 } 79 return null; 80 } 81 82 Expression popTemplateBody(int start) 83 { 84 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 isXslTag (Object 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 } 109 110 public void beginGroup(Object type) 111 { 112 String xslTag = isXslTag(type); 113 if (xslTag == "template") 114 { 115 if (templateLambda != null) 116 error("nested xsl:template"); 117 templateLambda = new LambdaExp(); 118 } 121 if (type instanceof XName) 122 { 123 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 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 xslTag = isXslTag(startTag); 160 if (xslTag == "value-of") 161 { 162 String 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 select = popMatchingAttribute("", "select", start + 1); 177 String 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 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 match = popMatchingAttribute("", "match", start + 1); 203 String name = popMatchingAttribute("", "name", start + 1); 204 String priority = popMatchingAttribute("", "priority", start + 1); 205 String 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; 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 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 235 237 attributeValue.append((char) v); 238 239 } 240 else 241 { 242 String str; 243 if (v < 0x10000) 244 str = String.valueOf(v); 245 else 246 { char[] c2 = { (char) (((v - 0x10000) >> 10) + 0xD800), 248 (char) ((v & 0x3FF) + 0xDC00) }; 249 str = new String (c2); 250 } 251 push(str); 252 } 253 } 254 255 256 265 274 279 public Consumer append (String str) 280 { 281 if (inAttribute) 282 attributeValue.append(str); 283 else 284 push(str); 285 return this; 286 } 287 288 289 void push(Expression exp) 290 { 291 comp.exprStack.push(exp); 292 } 293 294 void push(Object 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 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 (buf, off, len)); 368 } 369 370 public void write (String str) 371 { 372 if (inAttribute) 373 attributeValue.append(str); 374 else 375 push(str); 376 } 377 378 379 public void write (CharSequence str, int start, int length) 380 { 381 write(str.subSequence(start, length).toString()); 382 } 383 384 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 message) 401 { 402 getMessages().error(kind, message); 403 } 404 405 412 413 Expression resolveQNameExpression(String name) 414 { 415 if (name == null) 416 return QuoteExp.nullExp; 417 else 418 return new QuoteExp(Symbol.make(null, name)); } 420 421 public void parse (Compilation comp) 422 { 423 this.comp = comp; 424 if (comp.exprStack == null) 425 comp.exprStack = new Stack (); 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 |