1 28 29 package com.caucho.xsl; 30 31 import com.caucho.java.JavaWriter; 32 import com.caucho.java.LineMap; 33 import com.caucho.log.Log; 34 import com.caucho.util.CharBuffer; 35 import com.caucho.util.CharScanner; 36 import com.caucho.util.IntArray; 37 import com.caucho.util.IntMap; 38 import com.caucho.util.L10N; 39 import com.caucho.util.StringCharCursor; 40 import com.caucho.vfs.Path; 41 import com.caucho.vfs.ReadStream; 42 import com.caucho.xml.CauchoDocument; 43 import com.caucho.xml.QAbstractNode; 44 import com.caucho.xml.QElement; 45 import com.caucho.xml.QName; 46 import com.caucho.xml.Xml; 47 import com.caucho.xml.XmlChar; 48 import com.caucho.xpath.Expr; 49 import com.caucho.xpath.NamespaceContext; 50 import com.caucho.xpath.XPath; 51 import com.caucho.xpath.pattern.AbstractPattern; 52 import com.caucho.xpath.pattern.UnionPattern; 53 import com.caucho.xsl.fun.FormatNumberFun; 54 import com.caucho.xsl.fun.KeyFun; 55 import com.caucho.xsl.java.XslAttributeSet; 56 import com.caucho.xsl.java.XslNode; 57 import com.caucho.xsl.java.XslStylesheet; 58 import com.caucho.xsl.java.XslTemplate; 59 60 import org.w3c.dom.Attr ; 61 import org.w3c.dom.Document ; 62 import org.w3c.dom.DocumentType ; 63 import org.w3c.dom.Element ; 64 import org.w3c.dom.Node ; 65 import org.w3c.dom.Text ; 66 67 import java.io.FileNotFoundException ; 68 import java.io.IOException ; 69 import java.text.DecimalFormatSymbols ; 70 import java.util.ArrayList ; 71 import java.util.HashMap ; 72 import java.util.Iterator ; 73 import java.util.logging.Level ; 74 import java.util.logging.Logger ; 75 76 81 abstract class Generator { 82 private static final Logger log = Log.open(Generator.class); 83 protected static final L10N L = new L10N(Generator.class); 84 85 public static final String XSLNS = "http://www.w3.org/1999/XSL/Transform"; 86 public static final String XTPNS = "http://www.caucho.com/XTP/1.0"; 87 88 private static final int STYLESHEET = 0; 89 private static final int OUTPUT = STYLESHEET + 1; 90 private static final int IMPORT = OUTPUT + 1; 91 private static final int INCLUDE = IMPORT + 1; 92 private static final int TEMPLATE = INCLUDE + 1; 93 private static final int STRIP_SPACE = TEMPLATE + 1; 94 private static final int PRESERVE_SPACE = STRIP_SPACE + 1; 95 private static final int KEY = PRESERVE_SPACE + 1; 96 private static final int LOCALE = KEY + 1; 97 private static final int ATTRIBUTE_SET = LOCALE + 1; 98 private static final int NAMESPACE_ALIAS = ATTRIBUTE_SET + 1; 99 100 private static final int APPLY_TEMPLATES = NAMESPACE_ALIAS + 1; 101 private static final int APPLY_IMPORTS = APPLY_TEMPLATES + 1; 102 private static final int CALL_TEMPLATE = APPLY_IMPORTS + 1; 103 private static final int PARAM = CALL_TEMPLATE + 1; 104 private static final int VARIABLE = PARAM + 1; 105 private static final int VALUE_OF = VARIABLE + 1; 106 private static final int COPY_OF = VALUE_OF + 1; 107 private static final int FOR_EACH = COPY_OF + 1; 108 private static final int IF = FOR_EACH + 1; 109 private static final int CHOOSE = IF + 1; 110 111 private static final int TEXT = CHOOSE + 1; 112 private static final int XSL_TEXT = TEXT + 1; 113 private static final int NUMBER = XSL_TEXT + 1; 114 private static final int COPY = NUMBER + 1; 115 private static final int COPY_ELEMENT = COPY + 1; 116 private static final int ELEMENT = COPY_ELEMENT + 1; 117 private static final int ATTRIBUTE = ELEMENT + 1; 118 private static final int PI = ATTRIBUTE + 1; 119 private static final int COMMENT = PI + 1; 120 121 private static final int MESSAGE = COMMENT + 1; 122 123 private static final int EXPRESSION = MESSAGE + 1; 124 private static final int SCRIPTLET = EXPRESSION + 1; 125 private static final int DECLARATION = SCRIPTLET + 1; 126 private static final int DIRECTIVE_CACHE = DECLARATION + 1; 127 private static final int DIRECTIVE_PAGE = DIRECTIVE_CACHE + 1; 128 private static final int WHILE = DIRECTIVE_PAGE + 1; 129 130 private static final int ASSIGN = WHILE + 1; 131 private static final int IGNORE = ASSIGN + 1; 132 133 private static final int RESULT_DOCUMENT = IGNORE + 1; 135 136 private static IntMap _tags; 137 private static IntMap _xtpTags; 138 private String _version = "1.0"; 139 140 String _xslName; 141 Path _topContext; 143 Path _baseURL; 145 Path _context; 146 CharBuffer _text; 147 HashMap <String ,String > _names = new HashMap <String ,String >(); 148 int _loopDepth; 149 Path _workPath; 150 int _uniqueId; 151 152 protected HashMap <String ,String > _preserve = new HashMap <String ,String >(); 153 protected HashMap <String ,String > _strip = new HashMap <String ,String >(); 154 155 HashMap <String ,XslAttributeSet> _attributeSets = 156 new HashMap <String ,XslAttributeSet>(); 157 158 protected HashMap <String ,String []> _namespaceAliases = 159 new HashMap <String ,String []>(); 160 protected HashMap <String ,String > _excludedNamespaces = 161 new HashMap <String ,String >(); 162 protected KeyFun _keyFun; 163 protected FormatNumberFun _formatNumberFun; 164 165 protected NamespaceContext _namespace; 166 protected ArrayList _globalActions = new ArrayList (); 167 protected ArrayList <String > _globalParameters = 168 new ArrayList <String >(); 169 170 protected Document _doc; 171 protected CauchoDocument _qDoc; 172 173 protected Path _path; 174 175 boolean _lineContent; 176 int _lineWs; 177 String _systemId; 178 String _filename; 179 int _line; 180 protected LineMap _lineMap; 181 private ArrayList _frags; 182 protected int _destLine = 1; 183 boolean _defaultCacheable = true; 184 boolean _isCacheable; 185 protected String _encoding; 186 187 HashMap <String ,ArrayList <Template>> _templates = new HashMap <String ,ArrayList <Template>>(); 188 int _minImportance; int _importance; 190 int _templateCount; 191 private IntArray _vars = new IntArray(); 192 private ArrayList <XslNode> _inits = new ArrayList <XslNode>(); 193 protected ArrayList <Path> _depends = new ArrayList <Path>(); 194 protected ArrayList <String > _cacheDepends = new ArrayList <String >(); 195 196 private boolean _isCauchoXsl; 197 protected boolean _isRawText; 198 protected String _errorPage; 199 boolean _hasSession; 200 protected AbstractPattern _nodeListContext; 201 private boolean _isTop; 202 private ClassLoader _loader; 203 204 protected boolean _isSpecial; 205 protected boolean _isStyleScript; 206 207 HashMap <String ,String > _outputAttributes = new HashMap <String ,String >(); 208 HashMap <String ,String > _macros; 209 HashMap <String ,Document> _files; 210 211 protected AbstractStylesheetFactory _xslGenerator; 212 213 protected ArrayList <String > _imports = new ArrayList <String >(); 214 215 Generator(AbstractStylesheetFactory xslGenerator) 216 { 217 _xslGenerator = xslGenerator; 218 219 _workPath = xslGenerator.getWorkPath(); 220 221 Path path = xslGenerator.getStylePath(); 222 223 _context = path; 224 _topContext = _context; 225 _loader = xslGenerator.getClassLoader(); 226 if (_loader == null) 227 _loader = Thread.currentThread().getContextClassLoader(); 228 229 _text = new CharBuffer(); 230 _frags = new ArrayList (); 231 _macros = new HashMap <String ,String >(); 232 233 _keyFun = new KeyFun(); 234 _formatNumberFun = new FormatNumberFun(); 235 } 236 237 void init(String filename) 238 { 239 _lineMap = new LineMap(filename); 240 } 241 242 public void setErrorPage(String errorPage) 243 { 244 _errorPage = errorPage; 245 } 246 247 public void setStyleScript(boolean stylescript) 248 { 249 _isStyleScript = stylescript; 250 } 251 252 255 public void addImport(String pkg) 256 { 257 if (! _imports.contains(pkg)) 258 _imports.add(pkg); 259 } 260 261 public void setContentType(String type) 262 { 263 } 265 266 void setPath(Path path) 267 { 268 _path = path; 269 _context = path; 270 } 271 272 void setWorkPath(Path path) 273 { 274 _workPath = path; 275 } 276 277 public int getMinImportance() 278 { 279 return _minImportance; 280 } 281 282 public int getMaxImportance() 283 { 284 return _importance; 285 } 286 287 public NamespaceContext getNamespace() 288 { 289 return _namespace; 290 } 291 292 public AbstractPattern getNodeListContext() 293 { 294 return _nodeListContext; 295 } 296 297 public void addLocale(String name, DecimalFormatSymbols format) 298 { 299 _formatNumberFun.addLocale(name, format); 300 } 301 302 305 public int uniqueId() 306 { 307 return _uniqueId++; 308 } 309 310 315 public StylesheetImpl generate(Node node) throws Exception 316 { 317 Document xsl = node.getOwnerDocument(); 318 if (xsl == null) 319 xsl = (Document) node; 320 321 DocumentType dtd = xsl.getDoctype(); 322 323 if (dtd != null) { 324 _context = _path.lookup(xsl.getDoctype().getSystemId()); 325 _topContext = _context; 326 } 327 328 Element top = (Element) xsl.getDocumentElement(); 329 330 if (top == null) 331 throw error(xsl, L.l("xsl:stylesheet must be top element.")); 332 333 _doc = xsl; 334 if (_doc instanceof CauchoDocument) 335 _qDoc = (CauchoDocument) _doc; 336 337 QElement qTop = null; 338 if (top instanceof QElement) 339 qTop = (QElement) top; 340 341 345 346 _isTop = true; 347 _files = new HashMap <String ,Document>(); 348 scanFiles(top); 349 350 if (_qDoc != null) { 351 ArrayList depends = (ArrayList ) _qDoc.getProperty(CauchoDocument.DEPENDS); 352 for (int i = 0; depends != null && i < depends.size(); i++) { 353 Path path = (Path) depends.get(i); 354 addDepend(path); 355 } 356 } 357 else { 358 addDepend(_path); 359 } 360 361 if ("stylesheet".equals(getXslLocal(top)) || 362 "transform".equals(getXslLocal(top))) { 363 generateStylesheet(top, true); 364 } 365 else { 366 printHeader(); 368 boolean oldCacheable = _isCacheable; 369 boolean oldDefaultCacheable = _defaultCacheable; 370 _isCacheable = true; 371 372 XslNode literal = createChild(top); 373 374 XslTemplate template = new XslTemplate(); 375 template.setGenerator((JavaGenerator) this); 376 template.addAttribute(new QName("match"), "/"); 377 template.addChild(literal); 378 379 template.generateDeclaration(getOut()); 380 381 template.generate(getOut()); 382 383 385 _isCacheable = oldCacheable; 386 _defaultCacheable = oldDefaultCacheable; 387 } 388 389 addNamespace(top); 390 StylesheetImpl stylesheet = completeGenerate(_inits, _globalActions); 391 392 return stylesheet; 393 } 394 395 private static CharScanner commaDelimScanner = new CharScanner(" \t\n\r,"); 396 397 402 private void scanFiles(Element top) 403 throws XslParseException, IOException 404 { 405 _isCauchoXsl = ! top.getAttribute("xsl-caucho").equals(""); 406 407 Iterator iter; 408 try { 409 iter = XPath.select("//xtp:directive.page/@*", top); 410 } catch (Exception e) { 411 throw new XslParseException(e); 412 } 413 while (iter.hasNext()) { 414 Attr attr = (Attr ) iter.next(); 415 String name = attr.getNodeName(); 416 String value = attr.getNodeValue(); 417 418 if (name.equals("import")) { 419 StringCharCursor cursor = new StringCharCursor(value); 420 CharBuffer cb = new CharBuffer(); 421 while (cursor.current() != cursor.DONE) { 422 char ch; 423 commaDelimScanner.skip(cursor); 424 425 cb.clear(); 426 ch = commaDelimScanner.scan(cursor, cb); 427 428 if (cb.length() != 0) { 429 addImport(cb.toString()); 430 } 431 else if (ch != cursor.DONE) 432 throw new IOException (L.l("illegal `import' directive")); 433 } 434 } 435 } 436 437 try { 438 iter = XPath.select("//xsl:import|xsl:include", top); 439 } catch (Exception e) { 440 throw new XslParseException(e); 441 } 442 while (iter.hasNext()) { 443 Element elt = (Element) iter.next(); 444 String href = elt.getAttribute("href"); 445 446 ReadStream rs; 447 448 try { 449 rs = _xslGenerator.openPath(href, _context.getURL()); 450 } catch (Exception e) { 451 throw new XslParseException(e); 452 } 453 454 Path path = rs.getPath(); 455 456 Document xsl = readXsl(rs); 457 Element subtop = xsl.getDocumentElement(); 458 459 if (subtop == null) 460 throw error(elt, L.l("xsl:import file {0} is empty", path.getFullPath())); 461 462 Path oldContext = _context; 463 464 Path virtualPath = _context.getParent().lookup(href); 465 _context = virtualPath; 466 467 _files.put(virtualPath.getPath(), xsl); 468 469 scanFiles(subtop); 470 _context = oldContext; 471 } 472 } 473 474 public void addImportList(String value) 475 throws XslParseException 476 { 477 StringCharCursor cursor = new StringCharCursor(value); 478 CharBuffer cb = new CharBuffer(); 479 while (cursor.current() != cursor.DONE) { 480 char ch; 481 commaDelimScanner.skip(cursor); 482 483 cb.clear(); 484 ch = commaDelimScanner.scan(cursor, cb); 485 486 if (cb.length() != 0) { 487 addImport(cb.toString()); 488 } 489 else if (ch != cursor.DONE) 490 throw error(L.l("illegal `import' directive")); 491 } 492 } 493 494 501 Document readXsl(Path path) 502 throws IOException , XslParseException 503 { 504 return readXsl(path.openRead()); 505 } 506 507 514 Document readXsl(ReadStream file) 515 throws IOException , XslParseException 516 { 517 try { 518 addDepend(file.getPath()); 519 520 if (_isStyleScript) { 521 XslParser parser = new XslParser(); 522 523 return parser.parse(file); 524 } 525 else 526 return new Xml().parseDocument(file); 527 } catch (org.xml.sax.SAXException e) { 528 throw new XslParseException(e); 529 } finally { 530 file.close(); 531 } 532 } 533 534 537 private void generateStylesheet(Element elt, boolean isTop) 538 throws Exception 539 { 540 QElement element = (QElement) elt; 541 _isCauchoXsl = ! element.getAttribute("xsl-caucho").equals(""); 542 543 String systemId = element.getBaseURI(); 544 Path oldContext = _context; 545 546 if (systemId != null) 547 _context = _context.lookup(systemId); 548 549 XslNode stylesheet = createChild(element); 550 551 addNamespace(element); 552 553 if (isTop) 554 printHeader(); 555 556 stylesheet.generateDeclaration(getOut()); 557 558 stylesheet.generate(getOut()); 559 560 _context = oldContext; 561 562 609 } 610 611 abstract protected JavaWriter getOut(); 612 613 abstract protected XslNode createChild(Node child) 614 throws Exception ; 615 616 abstract protected XslNode createChild(XslNode parent, Node child) 617 throws Exception ; 618 619 private void addGlobalAction(Element elt) 620 { 621 _globalActions.add(elt); 622 } 623 624 628 private void excludeNamespaces(Element element) 629 throws Exception 630 { 631 if (! (element instanceof QElement)) 632 return; 633 634 QElement elt = (QElement) element; 635 String excludeNamespace; 636 excludeNamespace = element.getAttribute("exclude-result-prefixes"); 637 if (! excludeNamespace.equals("")) { 638 for (String prefix : excludeNamespace.split("[,\\s]+")) { 639 640 String ns = elt.getNamespace(prefix); 641 if (ns == null) 642 throw error(elt, L.l("`{0}' must be a namespace prefix", 643 prefix)); 644 _excludedNamespaces.put(ns, ""); 645 } 646 } 647 } 648 649 public void addExcludedNamespace(String ns) 650 { 651 _excludedNamespaces.put(ns, ""); 652 } 653 654 public void addInit(XslNode node) 655 { 656 _inits.add(node); 657 } 658 659 public void addGlobalParameter(String param) 660 { 661 _globalParameters.add(param); 662 } 663 664 668 private void addCacheDepends(String attr) 669 { 670 if (attr.equals("")) 671 return; 672 673 int i = 0; 674 int ch = 0; 675 int len = attr.length(); 676 for (; 677 i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ','; 678 i++) { 679 } 680 CharBuffer cb = new CharBuffer(); 681 while (i < len) { 682 cb.clear(); 683 for (; 684 i < len && ! XmlChar.isWhitespace((ch = attr.charAt(i))) && 685 ch != ','; 686 i++) { 687 cb.append((char) ch); 688 } 689 690 _cacheDepends.add(cb.toString()); 691 692 for (; 693 i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ','; 694 i++) { 695 } 696 } 697 } 698 699 private void generateCacheDepends(String attr) 700 throws Exception 701 { 702 if (attr.equals("")) 703 return; 704 705 int i = 0; 706 int ch = 0; 707 int len = attr.length(); 708 for (; 709 i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ','; 710 i++) { 711 } 712 CharBuffer cb = new CharBuffer(); 713 while (i < len) { 714 cb.clear(); 715 for (; 716 i < len && ! XmlChar.isWhitespace((ch = attr.charAt(i))) && 717 ch != ','; 718 i++) { 719 cb.append((char) ch); 720 } 721 722 printCacheDepends(cb.toString()); 723 724 for (; 725 i < len && XmlChar.isWhitespace((ch = attr.charAt(i))) || ch == ','; 726 i++) { 727 } 728 } 729 } 730 731 734 void generateTemplate(Element element) 735 throws Exception 736 { 737 String name = element.getAttribute("name"); 738 String patternString = element.getAttribute("match"); 739 String mode = element.getAttribute("mode"); 740 String priority = element.getAttribute("priority"); 741 double dPriority = 0.0/0.0; 742 743 if (! name.equals("")) 744 _macros.put(name, name); 745 746 if (name.equals("") && patternString.equals("")) 747 throw error("xsl:template expects a `name' or a `match' attribute."); 748 749 if (! priority.equals("")) { 750 try { 751 dPriority = Double.valueOf(priority).doubleValue(); 752 } catch (Exception e) { 753 throw error("xsl:template expects `priority' must be a double."); 754 } 755 } 756 757 boolean oldCacheable = _isCacheable; 758 boolean oldDefaultCacheable = _defaultCacheable; 759 AbstractPattern oldNodeListContext = _nodeListContext; 760 if (! patternString.equals("")) 761 _nodeListContext = parseMatch(patternString); 762 763 _isCacheable = true; 764 printTemplate(element, name, patternString, mode, dPriority); 765 _nodeListContext = oldNodeListContext; 766 _isCacheable = oldCacheable; 767 _defaultCacheable = oldDefaultCacheable; 768 } 769 770 public XslNode generateImport(String href) 771 throws Exception 772 { 773 Path path = lookupPath(href); 774 775 if (_files.get(path.getPath()) != null) 776 return null; 777 778 Document xsl = readFile(href, path); 779 780 if (xsl == null) 781 throw new FileNotFoundException (href); 782 783 QElement top = (QElement) xsl.getDocumentElement(); 784 if (top == null || 785 ! "stylesheet".equals(getXslLocal(top)) && 786 ! "transform".equals(getXslLocal(top))) { 787 throw error("imported stylesheet `" + href + 788 "' missing xsl:stylesheet."); 789 } 790 791 int oldMinImportance = _minImportance; 792 Path oldContext = _context; 793 Path virtualPath = _context.getParent().lookup(href); 794 _context = virtualPath; 795 _minImportance = _importance; 796 boolean oldTop = _isTop; 797 boolean oldRaw = _isRawText; 798 _isTop = false; 799 _isRawText = false; 800 801 String systemId = top.getBaseURI(); 802 803 if (systemId != null) 804 _context = _context.lookup(systemId); 805 806 XslStylesheet stylesheet = (XslStylesheet) createChild(top); 807 808 _isRawText = oldRaw; 809 _isTop = oldTop; 810 _minImportance = oldMinImportance; 811 _context = oldContext; 812 813 incrementImportance(); 814 815 return stylesheet; 816 } 817 818 822 void generateInclude(Element element) 823 throws Exception 824 { 825 String href = element.getAttribute("href"); 826 if (href.equals("")) 827 throw error("xsl:include expects `href' attribute."); 828 829 if (element.getFirstChild() != null) 830 throw error("xsl:include must be empty"); 831 } 832 833 public void generateInclude(XslNode parent, String href) 834 throws Exception 835 { 836 Path path = lookupPath(href); 837 838 if (_files.get(path.getPath()) != null) 839 return; 840 841 Document xsl = readFile(href, path); 842 843 Element top = (Element) xsl.getDocumentElement(); 844 if (top == null || 845 ! "stylesheet".equals(getXslLocal(top)) && 846 ! "transform".equals(getXslLocal(top))) { 847 throw error("imported stylesheet `" + href + 848 "' missing xsl:stylesheet."); 849 } 850 851 Path oldContext = _context; 852 _context = path; 853 854 for (Node node = top.getFirstChild(); 855 node != null; 856 node = node.getNextSibling()) { 857 XslNode child = createChild(parent, node); 858 859 if (child != null) 860 parent.addChild(child); 861 } 862 863 865 _context = oldContext; 866 } 867 868 871 private Path lookupPath(String href) 872 { 873 return _context.getParent().lookup(href); 874 } 875 876 private Document readFile(String href, Path virtualPath) 877 throws Exception 878 { 879 Document xsl = (Document) _files.get(virtualPath.getPath()); 880 881 if (xsl != null) 882 throw new IllegalStateException (L.l("'{0}' is a duplicated path", 883 virtualPath.getPath())); 884 885 ReadStream rs; 886 887 try { 888 rs = _xslGenerator.openPath(href, _context.getURL()); 889 } catch (Exception e) { 890 throw new XslParseException(e); 891 } 892 893 Path path = rs.getPath(); 894 895 xsl = readXsl(rs); 896 Element subtop = xsl.getDocumentElement(); 897 898 if (subtop == null) 899 throw error(L.l("xsl:import file {0} is empty", path.getFullPath())); 900 901 Path oldContext = _context; 902 903 _context = virtualPath; 904 905 _files.put(virtualPath.getPath(), xsl); 906 907 _context = oldContext; 908 909 return xsl; 910 } 911 912 void generateKey(Element element) 913 throws Exception 914 { 915 String name = element.getAttribute("name"); 916 if (name.equals("")) 917 throw error("xsl:key expects `name' attribute."); 918 String match = element.getAttribute("match"); 919 if (match.equals("")) 920 throw error("xsl:key expects `match' attribute."); 921 String use = element.getAttribute("use"); 922 if (use.equals("")) 923 throw error("xsl:key expects `use' attribute."); 924 925 if (element.getFirstChild() != null) 926 throw error("xsl:key must be empty"); 927 928 _keyFun.add(name, parseMatch(match), parseExpr(use)); 929 } 930 931 public void addKey(String name, AbstractPattern match, Expr use) 932 { 933 _keyFun.add(name, match, use); 934 } 935 936 void generateLocale(Element element) 937 throws Exception 938 { 939 String name = element.getAttribute("name"); 940 if (name.equals("")) 941 name = "*"; 942 943 DecimalFormatSymbols format = new DecimalFormatSymbols (); 944 945 String value = element.getAttribute("decimal-separator"); 946 if (value.length() > 0) 947 format.setDecimalSeparator(value.charAt(0)); 948 949 value = element.getAttribute("grouping-separator"); 950 if (value.length() > 0) 951 format.setGroupingSeparator(value.charAt(0)); 952 953 value = element.getAttribute("infinity"); 954 if (! value.equals("")) 955 format.setInfinity(value); 956 957 value = element.getAttribute("minus-sign"); 958 if (value.length() > 0) 959 format.setMinusSign(value.charAt(0)); 960 961 value = element.getAttribute("NaN"); 962 if (! value.equals("")) 963 format.setNaN(value); 964 965 value = element.getAttribute("percent"); 966 if (value.length() > 0) 967 format.setPercent(value.charAt(0)); 968 969 value = element.getAttribute("per-mille"); 970 if (value.length() > 0) 971 format.setPerMill(value.charAt(0)); 972 973 value = element.getAttribute("zero-digit"); 974 if (value.length() > 0) 975 format.setZeroDigit(value.charAt(0)); 976 977 value = element.getAttribute("digit"); 978 if (value.length() > 0) 979 format.setDigit(value.charAt(0)); 980 981 value = element.getAttribute("pattern-separator"); 982 if (value.length() > 0) 983 format.setPatternSeparator(value.charAt(0)); 984 985 _formatNumberFun.addLocale(name, format); 986 } 987 988 void generateNamespaceAlias(Element element) 989 throws Exception 990 { 991 if (! (element instanceof QElement)) 992 return; 993 994 QElement elt = (QElement) element; 995 String stylesheetPrefix; 996 String resultPrefix; 997 998 stylesheetPrefix = (String ) element.getAttribute("stylesheet-prefix"); 999 resultPrefix = (String ) element.getAttribute("result-prefix"); 1000 1001 if (stylesheetPrefix.equals("")) 1002 throw error(element, "xsl:namespace-alias needs `stylesheet-prefix'"); 1003 if (resultPrefix.equals("")) 1004 throw error(element, "xsl:namespace-alias needs `result-prefix'"); 1005 } 1006 1007 public void addNamespaceAlias(String stylesheetPrefix, 1008 String resultPrefix) 1009 { 1010 1027 } 1028 1029 public void addNamespaceAlias(String namespace, String []result) 1030 { 1031 _namespaceAliases.put(namespace, result); 1032 } 1033 1034 public String []getNamespaceAlias(String namespace) 1035 { 1036 return _namespaceAliases.get(namespace); 1037 } 1038 1039 1045 1064 1065 1071 1142 1143 public void addAttributeSet(String name, XslAttributeSet attributeSet) 1144 { 1145 _attributeSets.put(name, attributeSet); 1146 } 1147 1148 1154 1155 public void setDisableOutputEscaping(boolean disable) 1156 { 1157 _isRawText = disable; 1158 } 1159 1160 public boolean getDisableOutputEscaping() 1161 { 1162 return _isRawText; 1163 } 1164 1165 private void generateOutput(Element element) 1166 throws Exception 1167 { 1168 Node attr = ((QElement) element).getFirstAttribute(); 1169 1170 if (element.getFirstChild() != null) 1171 throw error("xsl:output must be empty"); 1172 1173 String disableEscaping; 1174 disableEscaping = element.getAttribute("resin:disable-output-escaping"); 1175 if (disableEscaping.equals("")) 1176 disableEscaping = element.getAttribute("disable-output-escaping"); 1177 if (disableEscaping.equals("no") || 1178 disableEscaping.equals("false")) 1179 _isRawText = false; 1180 else if (! disableEscaping.equals("")) 1181 _isRawText = true; 1182 1183 if (! _isTop) 1185 return; 1186 1187 if (_outputAttributes == null) 1188 _outputAttributes = new HashMap <String ,String >(); 1189 1190 for (; attr != null; attr = attr.getNextSibling()) { 1191 _outputAttributes.put(attr.getNodeName(), attr.getNodeValue()); 1192 } 1193 } 1194 1195 public void setOutputAttribute(String name, String value) 1196 { 1197 _outputAttributes.put(name, value); 1198 } 1199 1200 private void generatePreserveSpace(Element element) 1201 throws Exception 1202 { 1203 String elements = element.getAttribute("elements"); 1204 if (elements.equals("")) 1205 throw error("xsl:preserve-space expects `elements' attribute."); 1206 1207 if (element.getFirstChild() != null) 1208 throw error("xsl:preserve-space must be empty"); 1209 1210 int i = 0; 1211 int len = elements.length(); 1212 for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) { 1213 } 1214 CharBuffer cb = new CharBuffer(); 1215 while (i < len) { 1216 cb.clear(); 1217 1218 for (; i < len && ! XmlChar.isWhitespace(elements.charAt(i)); i++) 1219 cb.append(elements.charAt(i)); 1220 1221 _preserve.put(cb.toString(), "true"); 1222 1223 for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) { 1224 } 1225 } 1226 } 1227 1228 private void generateStripSpace(Element element) 1229 throws Exception 1230 { 1231 throw new UnsupportedOperationException (); 1232 1240 } 1241 1242 public void addStripSpace(String elements) 1243 { 1244 int i = 0; 1245 int len = elements.length(); 1246 for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) { 1247 } 1248 CharBuffer cb = new CharBuffer(); 1249 while (i < len) { 1250 cb.clear(); 1251 1252 for (; i < len && ! XmlChar.isWhitespace(elements.charAt(i)); i++) { 1253 cb.append(elements.charAt(i)); 1254 } 1255 1256 _strip.put(cb.toString(), "true"); 1257 1258 for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) { 1259 } 1260 } 1261 } 1262 1263 public void addPreserveSpace(String elements) 1264 { 1265 int i = 0; 1266 int len = elements.length(); 1267 for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) { 1268 } 1269 CharBuffer cb = new CharBuffer(); 1270 while (i < len) { 1271 cb.clear(); 1272 1273 for (; i < len && ! XmlChar.isWhitespace(elements.charAt(i)); i++) { 1274 cb.append(elements.charAt(i)); 1275 } 1276 1277 _preserve.put(cb.toString(), "true"); 1278 1279 for (; i < len && XmlChar.isWhitespace(elements.charAt(i)); i++) { 1280 } 1281 } 1282 } 1283 1284 protected void generateChildren(Node node) 1285 throws Exception 1286 { 1287 _vars.add(0); 1288 for (Node child = node.getFirstChild(); 1289 child != null; 1290 child = child.getNextSibling()) { 1291 generateChild(child); 1292 } 1293 int count = _vars.pop(); 1294 if (count > 0 && _vars.size() > 0) 1295 printPopScope(count); 1296 } 1297 1298 protected void generateChild(Node child) 1299 throws Exception 1300 { 1301 generateChildImpl(child); 1302 } 1303 1304 public void generateChildImpl(Node child) 1305 throws Exception 1306 { 1307 String nodeName = getXslLocal(child); 1308 int code = -1; 1309 if (nodeName != null) 1310 code = _tags.get(nodeName); 1311 else if ((nodeName = getXtpLocal(child)) != null) 1312 code = _xtpTags.get(nodeName); 1313 1319 1320 if (nodeName == null) { 1321 if (child.getNodeType() == child.TEXT_NODE) 1322 generateText(child); 1323 else if (child.getNodeType() == child.ELEMENT_NODE) { 1324 NamespaceContext oldNamespace = addNamespace((Element) child); 1325 printElement((Element) child); 1326 _namespace = oldNamespace; 1327 } 1328 return; 1329 } 1330 1331 if (child instanceof QElement) { 1332 NamespaceContext oldNamespace = addNamespace((QElement) child); 1333 generateChild(child, code); 1334 _namespace = oldNamespace; 1335 } 1336 else 1337 generateChild(child, code); 1338 } 1339 1340 public void generateChild(Node child, int code) 1341 throws Exception 1342 { 1343 if (child instanceof QAbstractNode) { 1344 QAbstractNode qChild = (QAbstractNode) child; 1345 setLocation(qChild.getBaseURI(), qChild.getFilename(), qChild.getLine()); 1346 } 1347 1348 switch (code) { 1349 case TEXT: 1350 generateText(child); 1351 break; 1352 1353 case XSL_TEXT: 1354 generateXslText((Element) child); 1355 break; 1356 1357 case APPLY_TEMPLATES: 1358 generateApplyTemplates((Element) child); 1359 break; 1360 1361 case APPLY_IMPORTS: 1362 generateApplyImports((Element) child); 1363 break; 1364 1365 case CALL_TEMPLATE: 1366 generateCallTemplate((Element) child); 1367 break; 1368 1369 case PARAM: 1370 generateParamVariable((Element) child); 1371 break; 1372 1373 case VARIABLE: 1374 generateVariable((Element) child); 1375 break; 1376 1377 case VALUE_OF: 1378 generateValueOf((Element) child); 1379 break; 1380 1381 case COPY_OF: 1382 generateCopyOf((Element) child); 1383 break; 1384 1385 case FOR_EACH: 1386 generateForEach((Element) child); 1387 break; 1388 1389 case IF: 1390 generateIf((Element) child); 1391 break; 1392 1393 case CHOOSE: 1394 generateChoose((Element) child); 1395 break; 1396 1397 case NUMBER: 1398 generateNumber((Element) child); 1399 break; 1400 1401 case COPY: 1402 printCopy((Element) child); 1403 break; 1404 1405 case COPY_ELEMENT: 1406 printCopyElement((Element) child); 1407 break; 1408 1409 case ELEMENT: 1410 generateElement((Element) child); 1411 break; 1412 1413 case ATTRIBUTE: 1414 generateAttribute((Element) child); 1415 break; 1416 1417 case PI: 1418 printPi((Element) child); 1419 break; 1420 1421 case COMMENT: 1422 printComment((Element) child); 1423 break; 1424 1425 case MESSAGE: 1426 printMessage((Element) child); 1427 break; 1428 1429 case EXPRESSION: 1430 if (! _defaultCacheable) 1431 _isCacheable = false; 1432 printExpression((Element) child); 1433 break; 1434 1435 case SCRIPTLET: 1436 if (! _defaultCacheable) 1437 _isCacheable = false; 1438 printScriptlet((Element) child); 1439 break; 1440 1441 case DIRECTIVE_CACHE: 1442 generateCacheDepends(((Element) child).getAttribute("file")); 1443 if (! ((Element) child).getAttribute("no-cache").equals("")) { 1444 _isCacheable = false; 1445 _defaultCacheable = false; 1446 } 1447 else 1448 _defaultCacheable = true; 1449 break; 1450 1451 case WHILE: 1452 generateWhile((Element) child); 1453 break; 1454 1455 case ASSIGN: 1456 generateAssign((Element) child); 1457 break; 1458 1459 case RESULT_DOCUMENT: 1460 generateResultDocument((Element) child); 1461 break; 1462 1463 case IGNORE: 1464 break; 1465 1466 default: 1467 if (child instanceof QElement && 1468 XSLNS.equals(((QElement) child).getNamespaceURI()) && 1469 _version != null && _version.equals("1.0")) 1470 throw error(child, "unknown XSL element `" + 1471 child.getNodeName() + "'"); 1472 else { 1473 Node subchild = child.getFirstChild(); 1474 boolean hasFallback = false; 1475 for (; subchild != null; subchild = subchild.getNextSibling()) { 1476 String local = getXslLocal(subchild); 1477 if (local != null && local.equals("fallback")) { 1478 hasFallback = true; 1479 generateChildren(subchild); 1480 } 1481 } 1482 if (! hasFallback) printError(L.l("expected xsl tag at `{0}'", 1484 child.getNodeName())); 1485 } 1486 break; 1487 } 1488 } 1489 1490 private void generateText(Node node) 1491 throws Exception 1492 { 1493 String data = node.getNodeValue(); 1494 int length = data.length(); 1495 1496 if (length == 0) 1497 return; 1498 1499 int i = 0; 1500 for (; i < length && XmlChar.isWhitespace(data.charAt(i)); i++) { 1501 } 1502 1503 if (i == length && stripNode(node)) 1504 return; 1505 1506 if (data != null && data.length() > 0 && node instanceof QAbstractNode) { 1507 setLocation(node); 1508 writeText(data); 1509 } 1510 } 1511 1512 private boolean stripNode(Node node) 1513 { 1514 for (node = node.getParentNode(); 1515 node != null; 1516 node = node.getParentNode()) { 1517 if (node instanceof Element) { 1518 Element elt = (Element) node; 1519 String space = elt.getAttribute("xml:space"); 1520 if (! space.equals("")) 1521 return ! space.equals("preserve"); 1522 } 1523 } 1524 1525 return true; 1526 } 1527 1528 void generateXslText(Element element) 1529 throws Exception 1530 { 1531 _text.clear(); 1532 for (Node child = element.getFirstChild(); 1533 child != null; 1534 child = child.getNextSibling()) { 1535 if (! (child instanceof Text )) 1536 continue; 1537 1538 String data = child.getNodeValue(); 1539 int length = data.length(); 1540 1541 _text.append(data); 1542 } 1543 1544 String disableEscaping = element.getAttribute("disable-output-escaping"); 1545 if (disableEscaping.equals("")) 1546 disableEscaping = "no"; 1547 1548 if (_text.length() <= 0) { 1549 } 1550 else if (! disableEscaping.equals("yes") && 1551 ! disableEscaping.equals("true")) 1552 writeText(_text.toString()); 1553 else { 1554 startDisableEscaping(); 1555 writeText(_text.toString()); 1556 endDisableEscaping(); 1557 } 1558 } 1559 1560 private void generateApplyTemplates(Node node) 1561 throws Exception 1562 { 1563 QElement element = (QElement) node; 1564 String select = element.getAttribute("select"); 1565 String mode = element.getAttribute("mode"); 1566 AbstractPattern selectPattern = null; 1567 if (! select.equals("")) 1568 selectPattern = parseSelect(select, node); 1569 1570 Sort []sort = generateSort(node); 1571 1572 if (sort != null && selectPattern == null) 1573 selectPattern = parseSelect("*", node); 1574 1575 pushCall(); 1576 generateArgs(element); 1577 printApplyTemplates(selectPattern, mode, sort); 1578 popCall(); 1579 } 1580 1581 private void generateApplyImports(Node node) 1582 throws Exception 1583 { 1584 QElement element = (QElement) node; 1585 String mode = element.getAttribute("mode"); 1586 1587 if (element.getFirstChild() != null) 1588 throw error(L.l("xsl:apply-imports must be empty")); 1589 1590 pushCall(); 1591 generateArgs(element); 1592 printApplyImports(mode, _minImportance, _importance); 1593 popCall(); 1594 } 1595 1596 private void generateCallTemplate(Element element) 1597 throws Exception 1598 { 1599 String name = element.getAttribute("name"); 1600 String mode = element.getAttribute("mode"); 1601 1602 if (name.equals("")) 1603 throw error(L.l("{0} expects `{1}' attribute", 1604 "xsl:call-template", "name")); 1605 1606 if (findMacro(name) == null) 1607 throw error(element, L.l("`{0}' is an unknown macro for xsl:call-template. All macros must be defined in an <xsl:template name='...'> element.", name)); 1608 1609 pushCall(); 1610 generateArgs(element); 1611 printCallTemplate(name, mode); 1612 popCall(); 1613 } 1614 1615 private Element findMacro(String name) 1616 throws Exception 1617 { 1618 Element template = findMacroInDocument(_doc, name); 1619 if (template != null) 1620 return template; 1621 1622 Iterator iter = _files.values().iterator(); 1623 while (iter.hasNext()) { 1624 Document doc = (Document) iter.next(); 1625 1626 template = findMacroInDocument(doc, name); 1627 1628 if (template != null) 1629 return template; 1630 } 1631 1632 return null; 1633 } 1634 1635 private Element findMacroInDocument(Document doc, String name) 1636 { 1637 Element elt = doc.getDocumentElement(); 1638 1639 for (Node child = elt.getFirstChild(); 1640 child != null; 1641 child = child.getNextSibling()) { 1642 if (! child.getNodeName().equals("xsl:template")) 1643 continue; 1644 1645 Element template = (Element) child; 1646 1647 if (template.getAttribute("name").equals(name)) 1648 return template; 1649 } 1650 1651 return null; 1652 } 1653 1654 private void generateMacro(Element element) 1655 throws Exception 1656 { 1657 QElement elt = (QElement) element; 1658 1659 String name = element.getNodeName(); 1660 String mode = element.getAttribute("mode"); 1661 1662 pushCall(); 1663 for (Node node = elt.getFirstAttribute(); 1664 node != null; 1665 node = node.getNextSibling()) { 1666 String argName = node.getNodeName(); 1667 String argValue = node.getNodeValue(); 1668 1669 printParam(argName, argValue, elt); 1670 } 1671 printParam("contents", elt); 1672 printCallTemplate(name, mode); 1673 popCall(); 1674 } 1675 1676 private void generateArgs(Element element) 1677 throws Exception 1678 { 1679 for (Node node = element.getFirstChild(); node != null; 1680 node = node.getNextSibling()) { 1681 String localName = getXslLocal(node); 1682 1683 if ("with-param".equals(localName)) { 1684 String key = ((Element) node).getAttribute("name"); 1685 String expr = ((Element) node).getAttribute("select"); 1686 if (key.equals("")) 1687 throw error(L.l("{0} requires `{1}' attribute", 1688 "xsl:with-param", "name")); 1689 1690 if (! expr.equals("")) 1691 printParam(key, parseExpr(expr)); 1692 else 1693 printParam(key, node); 1694 } 1695 } 1696 } 1697 1698 private void generateParamVariable(Element element) 1699 throws Exception 1700 { 1701 int i = _vars.size() - 1; 1702 _vars.set(i, _vars.get(i) + 1); 1703 1704 String name = element.getAttribute("name"); 1705 String expr = element.getAttribute("select"); 1706 if (name.equals("")) 1707 throw error(L.l("{0} expects `{1}' attribute", 1708 "xsl:param", "name")); 1709 1710 if (! expr.equals("")) 1711 printParamVariable(name, parseExpr(expr)); 1712 else 1713 printParamVariable(name, element); 1714 } 1715 1716 private void generateVariable(Element element) 1717 throws Exception 1718 { 1719 int i = _vars.size() - 1; 1720 _vars.set(i, _vars.get(i) + 1); 1721 1722 String name = element.getAttribute("name"); 1723 String expr = element.getAttribute("select"); 1724 if (name.equals("")) 1725 throw error(L.l("{0} expects `{1}' attribute.", 1726 "xsl:variable", "name")); 1727 1728 if (! expr.equals("")) 1729 printVariable(name, parseExpr(expr)); 1730 else 1731 printVariable(name, element); 1732 } 1733 1734 private void generateAssign(Element element) 1735 throws Exception 1736 { 1737 String name = element.getAttribute("name"); 1738 String expr = element.getAttribute("select"); 1739 if (name.equals("")) 1740 throw error(L.l("{0} expects `{1}' attribute.", 1741 "xtp:assign", "name")); 1742 1743 if (! expr.equals("")) 1744 printAssign(name, parseExpr(expr)); 1745 else 1746 printAssign(name, element); 1747 } 1748 1749 private void generateResultDocument(Element element) 1750 throws Exception 1751 { 1752 String href = element.getAttribute("href"); 1753 String format = element.getAttribute("format"); 1754 if (href.equals("")) 1755 throw error(L.l("{0} expects `{1}' attribute.", 1756 "xtp:result-document", "href")); 1757 1758 printResultDocument(element, href, format); 1759 } 1760 1761 private void generateValueOf(Element element) 1762 throws Exception 1763 { 1764 String select = element.getAttribute("select"); 1765 if (select.equals("")) 1766 throw error(L.l("{0} expects `{1}' attribute.", 1767 "xsl:value-of", "select")); 1768 1769 if (element.getFirstChild() != null) 1770 throw error(L.l("{0} must be empty", "xsl:value-of")); 1771 1772 String disable = element.getAttribute("disable-output-escaping"); 1773 boolean isDisabled = disable.equals("yes"); 1774 if (isDisabled) 1775 startDisableEscaping(); 1776 1777 printSelectValue(select, element); 1778 1779 if (isDisabled) 1780 endDisableEscaping(); 1781 } 1782 1783 private void generateCopyOf(Element element) 1784 throws Exception 1785 { 1786 String select = element.getAttribute("select"); 1787 if (select.equals("")) 1788 throw error(L.l("{0} expects `{1}' attribute", 1789 "xsl:copy-of", "select")); 1790 1791 if (element.getFirstChild() != null) 1792 throw error(L.l("{0} must be empty", "xsl:copy-of")); 1793 1794 printCopyOf(select, element); 1795 } 1796 1797 1800 void generateForEach(Element element) 1801 throws Exception 1802 { 1803 String select = element.getAttribute("select"); 1804 if (select.equals("")) 1805 throw error(L.l("{0} expects `{1}' attribute", 1806 "xsl:for-each", "select")); 1807 1808 Sort []sort = generateSort(element); 1809 1810 if (sort != null) 1811 printForEach(element, select, sort); 1812 else 1813 printForEach(element, select); 1814 } 1815 1816 private Sort []generateSort(Node node) 1817 throws XslParseException, IOException 1818 { 1819 ArrayList <Sort> sorts = new ArrayList <Sort>(); 1820 sort: 1821 for (Node child = node.getFirstChild(); 1822 child != null; 1823 child = child.getNextSibling()) { 1824 if (child.getNodeType() == child.TEXT_NODE) { 1825 String data = child.getNodeValue(); 1826 for (int i = 0; i < data.length(); i++) { 1827 if (! XmlChar.isWhitespace(data.charAt(i))) 1828 break sort; 1829 } 1830 continue; 1831 } 1832 else if (child.getNodeType() == child.COMMENT_NODE || 1833 child.getNodeType() == child.PROCESSING_INSTRUCTION_NODE) 1834 continue; 1835 1836 String name = getXslLocal(child); 1837 if (! "sort".equals(name)) 1838 break; 1839 1840 Element elt = (Element) child; 1841 String select = elt.getAttribute("select"); 1842 if (select.equals("")) 1843 throw error(L.l("{0} expects attribute `{1}'", 1844 "xsl:sort", "select")); 1845 1846 Expr expr = parseExpr(select); 1847 String order = elt.getAttribute("order"); 1848 Expr isAscending = null; 1849 if (order.equals("")) { 1850 isAscending = parseExpr("true()"); 1851 } 1852 else if (order.startsWith("{") && order.endsWith("}")) { 1853 order = order.substring(1, order.length() - 1); 1854 1855 isAscending = parseExpr(order + " = 'ascending'"); 1856 } 1857 else if (order.equals("ascending")) 1858 isAscending = parseExpr("true()"); 1859 else 1860 isAscending = parseExpr("false()"); 1861 1862 String dataType = elt.getAttribute("data-type"); 1863 boolean isText = true; 1864 if (dataType.equals("number")) 1865 isText = false; 1866 1867 String lang = elt.getAttribute("lang"); 1868 if (lang.equals("")) { 1869 sorts.add(Sort.create(expr, isAscending, isText)); 1870 } 1871 else { 1872 if (lang.startsWith("{") && lang.endsWith("}")) 1873 lang = lang.substring(1, lang.length() - 1); 1874 else 1875 lang = "'" + lang + "'"; 1876 1877 sorts.add(Sort.create(expr, isAscending, parseExpr(lang))); 1878 1905 } 1906 } 1907 1908 if (sorts.size() > 0) 1909 return (Sort []) sorts.toArray(new Sort[sorts.size()]); 1910 else 1911 return null; 1912 } 1913 1914 void generateIf(Element element) 1915 throws Exception 1916 { 1917 String test = (String ) element.getAttribute("test"); 1918 if (test.equals("")) 1919 throw error(L.l("{0} expects `{1}' attribute", "xsl:if", "test")); 1920 1921 printIf(element, parseExpr(test)); 1922 } 1923 1924 void generateWhile(Element element) 1925 throws Exception 1926 { 1927 String test = (String ) element.getAttribute("test"); 1928 if (test.equals("")) 1929 throw error(L.l("{0} expects `{1}' attribute", "xsl:while", "test")); 1930 1931 printWhile(element, parseExpr(test)); 1932 } 1933 1934 void generateChoose(Element element) 1935 throws Exception 1936 { 1937 boolean first = true; 1938 for (Node child = element.getFirstChild(); 1939 child != null; 1940 child = child.getNextSibling()) { 1941 if (! (child instanceof Element)) 1942 continue; 1943 1944 String name = getXslLocal(child); 1945 1946 if ("when".equals(name)) { 1947 Element elt = (Element) child; 1948 String test = elt.getAttribute("test"); 1949 if (test.equals("")) 1950 throw error(L.l("{0} expects `{1}' attribute", "xsl:when", "test")); 1951 1952 printChoose(elt, parseExpr(test), first); 1953 first = false; 1954 } 1955 else if ("otherwise".equals(name)) { 1956 printOtherwise((Element) child, first); 1957 } 1958 else 1959 throw error(L.l("xsl:choose expects `xsl:when' or `xsl:otherwise' at `{0}'", 1960 child.getNodeName())); 1961 } 1962 } 1963 1964 void generateElement(Element element) 1965 throws Exception 1966 { 1967 String name = (String ) element.getAttribute("name"); 1968 if (name.equals("")) 1969 throw error(L.l("{0} expects `{1}' attribute.", "xsl:element", "name")); 1970 Attr nsAttr = element.getAttributeNode("namespace"); 1971 1972 if (nsAttr == null) 1973 printElement(element, name); 1974 else 1975 printElement(element, name, nsAttr.getNodeValue()); 1976 } 1977 1978 void generateAttribute(Element element) 1979 throws Exception 1980 { 1981 String name = (String ) element.getAttribute("name"); 1982 if (name.equals("")) 1983 throw error(L.l("{0} expects `{1}' attribute", 1984 "xsl:attribute", "name")); 1985 Attr nsAttr = element.getAttributeNode("namespace"); 1986 1987 boolean oldSpecial = _isSpecial; 1988 _isSpecial = true; 1989 1990 if (nsAttr == null) 1991 printAttribute(element, name); 1992 else 1993 printAttribute(element, name, nsAttr.getNodeValue()); 1994 1995 _isSpecial = oldSpecial; 1996 } 1997 1998 void generateNumber(Element element) 1999 throws Exception 2000 { 2001 String value = element.getAttribute("value"); 2002 String count = element.getAttribute("count"); 2003 String from = element.getAttribute("from"); 2004 String level = element.getAttribute("level"); 2005 String format = element.getAttribute("format"); 2006 String letter = element.getAttribute("letter-value"); 2007 String separator = element.getAttribute("grouping-separator"); 2008 String lang = element.getAttribute("lang"); 2009 String size_name = element.getAttribute("grouping-size"); 2010 2011 int size = 0; 2012 for (int i = 0; i < size_name.length(); i++) { 2013 char ch = size_name.charAt(i); 2014 if (ch >= '0' && ch <= '9') 2015 size = 10 * size + ch - '0'; 2016 } 2017 2018 boolean isAlphabetic = true; 2019 if (! letter.equals("alphabetic")) 2020 isAlphabetic = false; 2021 2022 AbstractPattern countPattern = null; 2023 if (! count.equals("")) 2024 countPattern = parseMatch(count); 2025 2026 AbstractPattern fromPattern = null; 2027 if (! from.equals("")) 2028 fromPattern = parseMatch(from); 2029 2030 if (level.equals("") || level.equals("single")) 2031 level = "single"; 2032 else if (level.equals("multiple")) { 2033 } 2034 else if (level.equals("any")) { 2035 } 2036 else 2037 throw error(L.l("xsl:number can't understand level=`{0}'", 2038 level)); 2039 2040 XslNumberFormat xslFormat; 2041 xslFormat = new XslNumberFormat(format, lang, isAlphabetic, 2042 separator, size); 2043 2044 if (! value.equals("")) 2045 printNumber(parseExpr(value), xslFormat); 2046 else 2047 printNumber(level, countPattern, fromPattern, xslFormat); 2048 } 2049 2050 void printNumber(Expr expr, XslNumberFormat format) 2051 throws Exception 2052 { 2053 2054 } 2055 2056 void printNumber(String level, 2057 AbstractPattern countPattern, 2058 AbstractPattern fromPattern, 2059 XslNumberFormat format) 2060 throws Exception 2061 { 2062 2063 } 2064 2065 2068 void setLocation(Node node) 2069 throws Exception 2070 { 2071 if (node instanceof QAbstractNode) { 2072 setLocation(((QAbstractNode) node).getBaseURI(), 2073 ((QAbstractNode) node).getFilename(), 2074 ((QAbstractNode) node).getLine()); 2075 } 2076 } 2077 2078 public void setLocation(String systemId, String filename, int line) 2079 throws XslParseException, IOException 2080 { 2081 if (filename != null) { 2082 _systemId = systemId; 2083 _filename = filename; 2084 _line = line; 2085 } 2087 } 2088 2089 int getTextLength() 2090 { 2091 return _text.length(); 2092 } 2093 2094 protected void printHeader() 2095 throws XslParseException, IOException 2096 { 2097 } 2098 2099 abstract protected void startDisableEscaping() 2100 throws Exception ; 2101 2102 abstract protected void endDisableEscaping() 2103 throws Exception ; 2104 2105 abstract protected void writeText(String text) 2106 throws Exception ; 2107 2108 abstract protected void printTemplate(Element node, 2109 String name, String pattern, 2110 String mode, double priority) 2111 throws Exception ; 2112 2113 2114 2117 void printLocation(Node node) 2118 throws Exception 2119 { 2120 if (node instanceof QAbstractNode) { 2121 printLocation(((QAbstractNode) node).getBaseURI(), 2122 ((QAbstractNode) node).getFilename(), 2123 ((QAbstractNode) node).getLine()); 2124 } 2125 } 2126 2127 abstract protected void printLocation(String systemId, String filename, int line) 2128 throws Exception ; 2129 2130 abstract protected void printElement(Node node) 2131 throws Exception ; 2132 2133 abstract protected void 2134 printApplyTemplates(AbstractPattern select, String mode, Sort []sort) 2135 throws Exception ; 2136 2137 abstract protected void 2138 printApplyImports(String mode, int min, int max) 2139 throws Exception ; 2140 2141 abstract protected void 2142 printCallTemplate(String name, String mode) 2143 throws Exception ; 2144 2145 abstract protected void pushCall() 2146 throws Exception ; 2147 2148 abstract protected void popCall() 2149 throws Exception ; 2150 2151 abstract protected void printParam(String name, Object value) 2152 throws Exception ; 2153 2154 abstract protected void printParam(String name, String value, Element elt) 2155 throws Exception ; 2156 2157 abstract protected void printParamVariable(String name, Expr expr) 2158 throws Exception ; 2159 2160 abstract protected void printParamVariable(String name, Element elt) 2161 throws Exception ; 2162 2163 abstract protected void printVariable(String name, Object value) 2164 throws Exception ; 2165 2166 protected void printAssign(String name, Object value) 2167 throws Exception 2168 { 2169 printVariable(name, value); 2170 } 2171 2172 abstract protected void printPopScope(int count) 2173 throws Exception ; 2174 2175 abstract protected void printCopyOf(String select, Element element) 2176 throws Exception ; 2177 2178 abstract protected void printSelectValue(String select, Element element) 2179 throws Exception ; 2180 2181 abstract protected void printForEach(Element element, String select) 2182 throws Exception ; 2183 2184 abstract protected void printForEach(Element element, String select, 2185 Sort []sort) 2186 throws Exception ; 2187 2188 protected void printIf(Element element, Expr expr) 2189 throws Exception 2190 { 2191 } 2192 2193 protected void printChoose(Element element, Expr expr, boolean first) 2194 throws Exception 2195 { 2196 } 2197 2198 protected void printOtherwise(Element element, boolean first) 2199 throws Exception 2200 { 2201 } 2202 2203 protected void printCopy(Element element) 2204 throws Exception 2205 { 2206 } 2207 2208 protected void printCopyElement(Element element) 2209 throws Exception 2210 { 2211 } 2212 2213 protected void printElement(Element element, String name) 2214 throws Exception 2215 { 2216 } 2217 2218 protected void printElement(Element element, String name, String namespace) 2219 throws Exception 2220 { 2221 } 2222 2223 protected void printAttribute(Element node, String name) 2224 throws Exception 2225 { 2226 } 2227 2228 protected void printAttribute(Element node, String name, String namespace) 2229 throws Exception 2230 { 2231 } 2232 2233 protected void printPi(Element node) 2234 throws Exception 2235 { 2236 } 2237 2238 protected void printComment(Element node) 2239 throws Exception 2240 { 2241 } 2242 2243 protected void printError(String msg) 2244 throws Exception 2245 { 2246 } 2247 2248 protected void printMessage(Element node) 2249 throws Exception 2250 { 2251 } 2252 2253 2255 protected void printExpression(Element node) 2256 throws Exception 2257 { 2258 } 2259 2260 protected void printScriptlet(Element node) 2261 throws Exception 2262 { 2263 } 2264 2265 protected void printDeclaration(Element node) 2266 throws Exception 2267 { 2268 } 2269 2270 protected void printCacheDepends(String path) 2271 throws Exception 2272 { 2273 } 2274 2275 protected void printWhile(Element element, Expr expr) 2276 throws Exception 2277 { 2278 } 2279 2280 protected void printResultDocument(Element element, String href, 2281 String format) 2282 throws Exception 2283 { 2284 } 2285 2286 public int getImportance() 2287 { 2288 return _importance; 2289 } 2290 2291 public void setMinImportance(int importance) 2292 { 2293 _minImportance = importance; 2294 } 2295 2296 public void incrementImportance() 2297 { 2298 _importance++; 2299 } 2300 2301 2310 Template addPattern(AbstractPattern pattern, String mode, double priority, 2311 String function, int funId) 2312 { 2313 if (pattern instanceof UnionPattern) { 2314 UnionPattern union = (UnionPattern) pattern; 2315 addPattern(union.getLeft(), mode, priority, function, funId); 2316 return addPattern(union.getRight(), mode, priority, function, funId); 2317 } 2318 2319 if (Double.isNaN(priority)) 2320 priority = pattern.getPriority(); 2321 2322 if (log.isLoggable(Level.FINER)) 2323 log.finer("add " + pattern.getNodeName() + " " + pattern + " fun:" + 2324 function + " mode:" + mode + " priority:" + priority); 2325 2326 Template template = new Template(pattern, mode, 2327 _minImportance, _importance, 2328 priority, _templateCount++, 2329 function, funId); 2330 2331 addTemplate(pattern.getNodeName(), template); 2332 2333 return template; 2334 } 2335 2336 private void addTemplate(String nodeName, Template template) 2337 { 2338 ArrayList <Template> templateList = _templates.get(nodeName); 2339 2340 if (templateList == null) { 2341 templateList = new ArrayList <Template>(); 2342 _templates.put(nodeName, templateList); 2343 } 2344 2345 for (int i = templateList.size() - 1; i >= 0; i--) { 2346 Template item = templateList.get(i); 2347 2348 if (template.compareTo(item) <= 0) { 2349 templateList.add(i + 1, template); 2350 return; 2351 } 2352 } 2353 2354 templateList.add(0, template); 2355 } 2356 2357 public AbstractPattern parseMatch(String pattern) 2358 throws XslParseException, IOException 2359 { 2360 if (true) 2361 throw new RuntimeException (); 2362 try { 2363 return XPath.parseMatch(pattern, _namespace).getPattern(); 2364 } catch (Exception e) { 2365 throw error(L.l("{0} in pattern `{1}'", 2366 e.toString(), pattern)); 2367 } 2368 } 2369 2370 public AbstractPattern parseSelect(String pattern) 2371 throws IOException , XslParseException 2372 { 2373 if (true) 2374 throw new RuntimeException (); 2375 2376 try { 2377 return XPath.parseSelect(pattern, _namespace).getPattern(); 2378 } catch (Exception e) { 2379 throw error(e); 2380 } 2381 } 2382 2383 protected AbstractPattern parseSelect(String pattern, Node node) 2384 throws IOException , XslParseException 2385 { 2386 if (true) 2387 throw new UnsupportedOperationException (); 2388 try { 2389 return XPath.parseSelect(pattern, _namespace).getPattern(); 2390 } catch (Exception e) { 2391 throw error(node, e); 2392 } 2393 } 2394 2395 public Expr parseExpr(String pattern) 2396 throws XslParseException 2397 { 2398 if (true) 2399 throw new UnsupportedOperationException (); 2400 try { 2401 return XPath.parseExpr(pattern, _namespace, _nodeListContext); 2402 } catch (Exception e) { 2403 throw error(e); 2404 } 2405 } 2406 2407 XslParseException error(Exception e) 2408 { 2409 if (e.getMessage() != null) 2410 return error(e.getMessage()); 2411 else { 2412 log.log(Level.WARNING, e.toString(), e); 2413 2414 return error(e.toString()); 2415 } 2416 } 2417 2418 XslParseException error(Node node, Exception e) 2419 { 2420 if (e.getMessage() != null) 2421 return error(node, e.getMessage()); 2422 else { 2423 log.log(Level.WARNING, e.toString(), e); 2424 2425 return error(e.toString()); 2426 } 2427 } 2428 2429 XslParseException error(String message) 2430 { 2431 return new XslParseException(_filename + ":" + _line + ": " + message); 2432 } 2433 2434 2441 XslParseException error(Node node, String message) 2442 { 2443 if (! (node instanceof QAbstractNode)) 2444 return error(message); 2445 2446 QAbstractNode qnode = (QAbstractNode) node; 2447 2448 String filename = qnode.getFilename(); 2449 int line = qnode.getLine(); 2450 2451 if (filename != null) 2452 return new XslParseException(filename + ":" + 2453 line + ": " + 2454 message); 2455 else 2456 return error(message); 2457 } 2458 2459 2466 protected String getXslLocal(Node node) 2467 { 2468 if (! (node instanceof Element)) 2469 return null; 2470 2471 QElement elt = (QElement) node; 2472 2473 String ns = elt.getNamespaceURI(); 2474 String prefix = elt.getPrefix(); 2475 2476 if (ns == null || ns.equals("")) { 2477 return (elt.getNodeName().startsWith("xsl:") ? 2478 elt.getNodeName().substring(4) : 2479 null); 2480 } 2481 else if (ns.startsWith(XSLNS) && 2482 (ns.length() == XSLNS.length() || ns.charAt(XSLNS.length()) == '/')) 2483 return elt.getLocalName(); 2484 else 2485 return null; 2486 } 2487 2488 protected String getXtpLocal(Node node) 2489 { 2490 if (! (node instanceof Element)) 2491 return null; 2492 2493 QElement elt = (QElement) node; 2494 2495 String ns = elt.getNamespaceURI(); 2496 String prefix = elt.getPrefix(); 2497 2498 if (ns == null || ns.equals("")) { 2499 return (elt.getNodeName().startsWith("xtp:") ? 2500 elt.getNodeName().substring(4) : 2501 null); 2502 } 2503 else if (ns.startsWith(XTPNS)) 2504 return elt.getLocalName(); 2505 else 2506 return null; 2507 } 2508 2509 2512 private Expr parseExpr(Node node, String expr) 2513 throws Exception 2514 { 2515 try { 2516 return XPath.parseExpr(expr, _namespace, _nodeListContext); 2517 } catch (Exception e) { 2518 throw error(node, e.getMessage()); 2519 } 2520 } 2521 2522 2531 protected NamespaceContext addNamespace(Element elt) 2532 { 2533 NamespaceContext oldNamespace = _namespace; 2534 2535 Node attr = ((QElement) elt).getFirstAttribute(); 2536 for (; attr != null; attr = attr.getNextSibling()) { 2537 String name = attr.getNodeName(); 2538 2539 if (name.startsWith("xmlns:")) 2540 name = name.substring(6); 2541 else if (name.equals("xmlns")) 2542 name = ""; 2543 else 2544 continue; 2545 2546 2548 String url = attr.getNodeValue(); 2549 if (url.equals(XSLNS) || url.equals(XTPNS)) 2550 continue; 2551 2552 if (url.startsWith("quote:")) 2553 url = url.substring(6); 2554 2555 _namespace = new NamespaceContext(_namespace, name, url); 2556 } 2557 2558 return oldNamespace; 2559 } 2560 2561 void addDepend(Path depend) 2562 { 2563 if (depend != null) 2564 _depends.add(depend); 2565 } 2566 2567 abstract protected StylesheetImpl completeGenerate(ArrayList <XslNode> inits, 2568 ArrayList globals) 2569 throws Exception ; 2570 2571 2574 public void close() 2575 throws IOException , XslParseException 2576 { 2577 } 2578 2579 static { 2580 _tags = new IntMap(); 2581 _tags.put("stylesheet", STYLESHEET); 2582 _tags.put("transform", STYLESHEET); 2583 _tags.put("output", OUTPUT); 2584 _tags.put("template", TEMPLATE); 2585 _tags.put("preserve-space", PRESERVE_SPACE); 2586 _tags.put("strip-space", STRIP_SPACE); 2587 _tags.put("import", IMPORT); 2588 _tags.put("include", INCLUDE); 2589 _tags.put("key", KEY); 2590 _tags.put("decimal-format", LOCALE); 2591 _tags.put("attribute-set", ATTRIBUTE_SET); 2592 _tags.put("namespace-alias", NAMESPACE_ALIAS); 2593 2594 _tags.put("apply-templates", APPLY_TEMPLATES); 2595 _tags.put("apply-imports", APPLY_IMPORTS); 2596 _tags.put("call-template", CALL_TEMPLATE); 2597 _tags.put("param", PARAM); 2598 _tags.put("variable", VARIABLE); 2599 _tags.put("for-each", FOR_EACH); 2600 _tags.put("if", IF); 2601 _tags.put("choose", CHOOSE); 2602 2603 _tags.put("value-of", VALUE_OF); 2604 _tags.put("copy-of", COPY_OF); 2605 _tags.put("text", XSL_TEXT); 2606 _tags.put("#text", TEXT); 2607 _tags.put("number", NUMBER); 2608 _tags.put("copy", COPY); 2609 _tags.put("element", ELEMENT); 2610 _tags.put("attribute", ATTRIBUTE); 2611 _tags.put("pi", PI); 2612 _tags.put("processing-instruction", PI); 2613 _tags.put("comment", COMMENT); 2614 2615 _tags.put("message", MESSAGE); 2616 2617 _tags.put("sort", IGNORE); 2618 _tags.put("fallback", IGNORE); 2619 _tags.put("result-document", RESULT_DOCUMENT); 2621 2622 _xtpTags = new IntMap(); 2623 _xtpTags.put("expression", EXPRESSION); 2624 _xtpTags.put("expr", EXPRESSION); 2625 _xtpTags.put("eval", EXPRESSION); 2626 _xtpTags.put("scriptlet", SCRIPTLET); 2627 _xtpTags.put("script", SCRIPTLET); 2628 _xtpTags.put("decl", DECLARATION); 2629 _xtpTags.put("declaration", DECLARATION); 2630 _xtpTags.put("directive.cache", DIRECTIVE_CACHE); 2631 _xtpTags.put("while", WHILE); 2632 _xtpTags.put("assign", ASSIGN); 2633 } 2634} 2635 | Popular Tags |