1 package com.icl.saxon.style; 2 import com.icl.saxon.tree.AttributeCollection; 3 import com.icl.saxon.*; 4 import com.icl.saxon.om.*; 5 import com.icl.saxon.tree.ElementWithAttributes; 6 import com.icl.saxon.tree.DocumentImpl; 7 import com.icl.saxon.tree.NodeImpl; 8 import com.icl.saxon.expr.*; 9 import com.icl.saxon.pattern.Pattern; 10 import com.icl.saxon.pattern.NoNodeTest; 11 import com.icl.saxon.output.*; 12 import com.icl.saxon.trace.*; 14 import org.xml.sax.*; 15 import org.w3c.dom.Node ; 16 17 import java.util.*; 18 import java.io.*; 19 import java.text.*; 20 21 import javax.xml.transform.stream.StreamResult ; 22 import javax.xml.transform.TransformerException ; 23 import javax.xml.transform.TransformerConfigurationException ; 24 25 31 32 public abstract class StyleElement extends ElementWithAttributes 33 implements Locator { 34 35 protected Vector attributeSets = null; 36 protected short[] extensionNamespaces = null; private short[] excludedNamespaces = null; protected String version = null; 39 protected StaticContext staticContext = null; 40 protected TransformerConfigurationException validationError = null; 41 protected int reportingCircumstances = REPORT_ALWAYS; 42 43 45 public final static int REPORT_ALWAYS = 1; 46 public final static int REPORT_UNLESS_FORWARDS_COMPATIBLE = 2; 47 public final static int REPORT_IF_INSTANTIATED = 3; 48 49 52 53 public StyleElement() {} 54 55 61 62 public void substituteFor(StyleElement temp) { 63 this.parent = temp.parent; 64 this.attributeList = temp.attributeList; 65 this.namespaceList = temp.namespaceList; 66 this.nameCode = temp.nameCode; 67 this.sequence = temp.sequence; 68 this.attributeSets = temp.attributeSets; 69 this.extensionNamespaces = temp.extensionNamespaces; 70 this.excludedNamespaces = temp.excludedNamespaces; 71 this.version = temp.version; 72 this.root = temp.root; 73 this.staticContext = temp.staticContext; 74 this.validationError = temp.validationError; 75 this.reportingCircumstances = temp.reportingCircumstances; 76 } 77 78 81 82 protected void setValidationError(TransformerException reason, 83 int circumstances) { 84 if (reason instanceof TransformerConfigurationException ) { 85 validationError = (TransformerConfigurationException )reason; 86 } else { 87 validationError = new TransformerConfigurationException (reason); 88 } 89 reportingCircumstances = circumstances; 90 } 91 92 95 96 public boolean isInstruction() { 97 return false; 98 } 99 100 106 107 public boolean doesPostProcessing() { 108 return true; 109 } 110 111 114 115 public boolean mayContainTemplateBody() { 116 return false; 117 } 118 119 122 123 public XSLStyleSheet getContainingStyleSheet() { 124 NodeImpl next = this; 125 while (!(next instanceof XSLStyleSheet)) { 126 next = (NodeImpl)next.getParent(); 127 } 128 return (XSLStyleSheet)next; 129 } 130 131 134 135 public int getPrecedence() { 136 return getContainingStyleSheet().getPrecedence(); 137 } 138 139 142 143 public final StandardNames getStandardNames() { 144 DocumentImpl root = (DocumentImpl)getDocumentRoot(); 145 return ((StyleNodeFactory)root.getNodeFactory()).getStandardNames(); 146 } 147 148 151 152 public void processAllAttributes() throws TransformerConfigurationException { 153 staticContext = new ExpressionContext(this); 154 processAttributes(); 155 NodeImpl child = (NodeImpl)getFirstChild(); 156 while (child != null) { 157 if (child instanceof StyleElement) { 158 ((StyleElement)child).processAllAttributes(); 159 } 160 child = (NodeImpl)child.getNextSibling(); 161 } 162 } 163 164 168 169 public final void processAttributes() throws TransformerConfigurationException { 170 try { 171 prepareAttributes(); 172 } catch (TransformerConfigurationException err) { 173 if (forwardsCompatibleModeIsEnabled()) { 174 setValidationError(err, REPORT_UNLESS_FORWARDS_COMPATIBLE); 176 } else { 177 compileError(err); 178 } 179 } 180 } 181 182 186 187 protected void checkUnknownAttribute(int nc) throws TransformerConfigurationException { 188 if (forwardsCompatibleModeIsEnabled()) { 189 return; 191 } 192 String attributeURI = getNamePool().getURI(nc); 193 String elementURI = getURI(); 194 int attributeFingerprint = nc & 0xfffff; 195 StandardNames sn = getStandardNames(); 196 197 199 if (isInstruction() && 200 attributeURI.equals(Namespace.XSLT) && 201 !(elementURI.equals(Namespace.XSLT)) && 202 (attributeFingerprint == sn.XSL_EXTENSION_ELEMENT_PREFIXES || 203 attributeFingerprint == sn.XSL_EXCLUDE_RESULT_PREFIXES || 204 attributeFingerprint == sn.XSL_VERSION)) { 205 return; 206 } 207 208 if (attributeURI.equals("") || attributeURI.equals(Namespace.XSLT)) { 209 compileError("Attribute " + getNamePool().getDisplayName(nc) + 210 " is not allowed on this element"); 211 } 212 } 213 214 215 220 221 public abstract void prepareAttributes() throws TransformerConfigurationException ; 222 223 226 227 public Expression makeExpression(String expression) 228 throws TransformerConfigurationException { 229 try { 230 return Expression.make(expression, staticContext); 231 } catch(XPathException err) { 232 compileError(err); 233 return new ErrorExpression(err); 234 } 235 } 236 237 240 241 public Pattern makePattern(String pattern) 242 throws TransformerConfigurationException { 243 try { 244 return Pattern.make(pattern, staticContext); 245 } catch(XPathException err) { 246 compileError(err); 247 return NoNodeTest.getInstance(); 248 } 249 } 250 251 254 255 public Expression makeAttributeValueTemplate(String expression) 256 throws TransformerConfigurationException { 257 try { 258 return AttributeValueTemplate.make(expression, staticContext); 259 } catch(XPathException err) { 260 compileError(err); 261 return new StringValue(expression); 262 } 263 } 264 265 269 270 protected void processExtensionElementAttribute(int nc) 271 throws TransformerConfigurationException { 272 String ext = getAttributeValue(nc & 0xfffff); 273 if (ext!=null) { 274 int count = 0; 276 StringTokenizer st1 = new StringTokenizer(ext); 277 while (st1.hasMoreTokens()) { 278 String s = st1.nextToken(); 279 count++; 280 } 281 extensionNamespaces = new short[count]; 282 count = 0; 283 StringTokenizer st2 = new StringTokenizer(ext); 284 while (st2.hasMoreTokens()) { 285 String s = st2.nextToken(); 286 if (s.equals("#default")) { 287 s = ""; 288 } 289 try { 290 short uriCode = getURICodeForPrefix(s); 291 extensionNamespaces[count++] = uriCode; 292 } catch (NamespaceException err) { 293 extensionNamespaces = null; 294 compileError(err.getMessage()); 295 } 296 } 297 } 298 } 299 300 304 305 protected void processExcludedNamespaces(int nc) 306 throws TransformerConfigurationException { 307 String ext = getAttributeValue(nc & 0xfffff); 308 if (ext!=null) { 309 int count = 0; 311 StringTokenizer st1 = new StringTokenizer(ext); 312 while (st1.hasMoreTokens()) { 313 String s = st1.nextToken(); 314 count++; 315 } 316 excludedNamespaces = new short[count]; 317 count = 0; 318 StringTokenizer st2 = new StringTokenizer(ext); 319 while (st2.hasMoreTokens()) { 320 String s = st2.nextToken(); 321 if (s.equals("#default")) { 322 s = ""; 323 } 324 try { 325 short uriCode = getURICodeForPrefix(s); 326 excludedNamespaces[count++] = uriCode; 327 } catch (NamespaceException err) { 328 excludedNamespaces = null; 329 compileError(err.getMessage()); 330 } 331 } 332 } 333 } 334 335 339 340 protected void processVersionAttribute(int nc) { 341 version = getAttributeValue(nc & 0xfffff); 342 } 343 344 347 348 public String getVersion() { 349 if (version==null) { 350 NodeInfo node = (NodeInfo)getParentNode(); 351 if (node instanceof StyleElement) { 352 version = ((StyleElement)node).getVersion(); 353 } else { 354 version = "1.0"; } 356 } 357 return version; 358 } 359 360 363 364 public boolean forwardsCompatibleModeIsEnabled() { 365 return !(getVersion().equals("1.0")); 366 } 367 368 375 376 protected boolean definesExtensionElement(short uriCode) { 377 if (extensionNamespaces==null) { 378 return false; 379 } 380 for (int i=0; i<extensionNamespaces.length; i++) { 381 if (extensionNamespaces[i] == uriCode) { 382 return true; 383 } 384 } 385 return false; 386 } 387 388 393 394 public boolean isExtensionNamespace(short uriCode) { 395 NodeImpl anc = this; 396 while (anc instanceof StyleElement) { 397 if (((StyleElement)anc).definesExtensionElement(uriCode)) { 398 return true; 399 } 400 anc = (NodeImpl)anc.getParent(); 401 } 402 return false; 403 } 404 405 410 411 protected boolean definesExcludedNamespace(short uriCode) { 412 if (excludedNamespaces==null) { 413 return false; 414 } 415 for (int i=0; i<excludedNamespaces.length; i++) { 416 if (excludedNamespaces[i] == uriCode) { 417 return true; 418 } 419 } 420 return false; 421 } 422 423 429 430 public boolean isExcludedNamespace(short uriCode) { 431 if (uriCode==Namespace.XSLT_CODE) return true; 432 if (isExtensionNamespace(uriCode)) return true; 433 NodeImpl anc = this; 434 while (anc instanceof StyleElement) { 435 if (((StyleElement)anc).definesExcludedNamespace(uriCode)) { 436 return true; 437 } 438 anc = (NodeImpl)anc.getParent(); 439 } 440 return false; 441 } 442 443 449 450 public void validate() throws TransformerConfigurationException {} 451 452 457 458 public void preprocess() throws TransformerConfigurationException {} 459 460 463 464 public void validateSubtree() throws TransformerConfigurationException { 465 if (validationError!=null) { 466 if (reportingCircumstances == REPORT_ALWAYS) { 467 compileError(validationError); 468 } else if (reportingCircumstances == REPORT_UNLESS_FORWARDS_COMPATIBLE 469 && !forwardsCompatibleModeIsEnabled()) { 470 compileError(validationError); 471 } 472 } else { 473 try { 474 validate(); 475 } catch (TransformerConfigurationException err) { 476 if (forwardsCompatibleModeIsEnabled()) { 477 setValidationError(err, REPORT_IF_INSTANTIATED); 478 } else { 479 compileError(err); 480 } 481 } 482 483 validateChildren(); 484 } 485 } 486 487 protected void validateChildren() throws TransformerConfigurationException { 488 NodeImpl child = (NodeImpl)getFirstChild(); 489 while (child != null) { 490 if (child instanceof StyleElement) { 491 ((StyleElement)child).validateSubtree(); 492 } 493 child = (NodeImpl)child.getNextSibling(); 494 } 495 } 496 497 501 502 protected XSLStyleSheet getPrincipalStyleSheet() { 503 XSLStyleSheet sheet = getContainingStyleSheet(); 504 while (true) { 505 XSLStyleSheet next = sheet.getImporter(); 506 if (next==null) return sheet; 507 sheet = next; 508 } 509 } 510 511 515 516 public PreparedStyleSheet getPreparedStyleSheet() { 517 return getPrincipalStyleSheet().getPreparedStyleSheet(); 518 } 519 520 524 525 public void checkWithinTemplate() throws TransformerConfigurationException { 526 StyleElement parent = (StyleElement)getParentNode(); 527 if (!parent.mayContainTemplateBody()) { 528 compileError("Element must only be used within a template body"); 529 } 530 } 531 532 536 537 public void checkTopLevel() throws TransformerConfigurationException { 538 if (!(getParentNode() instanceof XSLStyleSheet)) { 539 compileError("Element must only be used at top level of stylesheet"); 540 } 541 } 542 543 547 548 public void checkNotTopLevel() throws TransformerConfigurationException { 549 if (getParentNode() instanceof XSLStyleSheet) { 550 compileError("Element must not be used at top level of stylesheet"); 551 } 552 } 553 554 558 559 public void checkEmpty() throws TransformerConfigurationException { 560 if (getFirstChild()!=null) { 561 compileError("Element must be empty"); 562 } 563 } 564 565 569 570 public void reportAbsence(String attribute) 571 throws TransformerConfigurationException { 572 compileError("Element must have a \"" + attribute + "\" attribute"); 573 } 574 575 581 582 public abstract void process(Context context) throws TransformerException ; 583 584 589 590 public void processChildren(Context context) throws TransformerException { 591 592 if (context.getController().isTracing()) { TraceListener listener = context.getController().getTraceListener(); 594 595 NodeImpl node = (NodeImpl)getFirstChild(); 596 while (node!=null) { 597 598 listener.enter(node, context); 599 600 if (node.getNodeType() == NodeInfo.TEXT) { 601 node.copy(context.getOutputter()); 602 } else if (node instanceof StyleElement) { 603 StyleElement snode = (StyleElement)node; 604 if (snode.validationError != null) { 605 fallbackProcessing(snode, context); 606 } else { 607 try { 608 context.setStaticContext(snode.staticContext); 609 snode.process(context); 610 } catch (TransformerException err) { 611 throw snode.styleError(err); 612 } 613 } 614 } 615 616 listener.leave(node, context); 617 node = (NodeImpl)node.getNextSibling(); 618 } 619 620 } else { 621 622 NodeImpl node = (NodeImpl)getFirstChild(); 623 while (node!=null) { 624 625 if (node.getNodeType() == NodeInfo.TEXT) { 626 node.copy(context.getOutputter()); 627 } else if (node instanceof StyleElement) { 628 StyleElement snode = (StyleElement)node; 629 if (snode.validationError != null) { 630 fallbackProcessing(snode, context); 631 } else { 632 try { 633 context.setStaticContext(snode.staticContext); 634 snode.process(context); 635 } catch (TransformerException err) { 636 throw snode.styleError(err); 637 } 638 } 639 } 640 node = (NodeImpl)node.getNextSibling(); 641 } 642 643 } 644 } 645 646 648 private void processX(Context context) throws TransformerException { 649 System.err.println("Processing " + context.getCurrentNodeInfo() + " using " + this); 650 process(context); 651 } 652 653 656 657 protected void fallbackProcessing(StyleElement instruction, Context context) throws TransformerException { 658 XSLFallback fallback = null; 660 Node child = instruction.getFirstChild(); 661 while (child!=null) { 662 if (child instanceof XSLFallback) { 663 fallback = (XSLFallback)child; 664 break; 665 } 666 child = child.getNextSibling(); 667 } 668 669 if (fallback==null) { 670 throw instruction.styleError(instruction.validationError); 671 } 672 673 boolean tracing = context.getController().isTracing(); 674 675 while (child!=null) { 676 if (child instanceof XSLFallback) { 677 XSLFallback f = (XSLFallback)child; 678 679 if (tracing) { 680 TraceListener listener = context.getController().getTraceListener(); 681 listener.enter(f, context); 682 f.process(context); 683 listener.leave(f, context); 684 } else { 685 f.process(context); 686 } 687 } 688 child = child.getNextSibling(); 689 } 690 691 692 } 693 694 698 699 protected Expression handleSortKeys(Expression select) { 700 702 int numberOfSortKeys = 0; 703 Node child = getFirstChild(); 704 705 while(child!=null) { 706 if (child instanceof XSLSort) { 707 numberOfSortKeys++; 708 } 709 child = child.getNextSibling(); 710 } 711 712 if (numberOfSortKeys > 0) { 713 SortedSelection sortExpression = new SortedSelection(select, numberOfSortKeys); 714 child = getFirstChild(); 715 716 int k=0; 717 while(child!=null) { 718 if (child instanceof XSLSort) { 719 sortExpression.setSortKey( 720 ((XSLSort)child).getSortKeyDefinition(), 721 k++); 722 } 723 child = child.getNextSibling(); 724 } 725 return sortExpression; 726 727 } else { 728 return new NodeListExpression(select); } 730 } 731 732 737 738 protected void findAttributeSets(String use) 739 throws TransformerConfigurationException { 740 741 attributeSets = new Vector(); 742 743 XSLStyleSheet stylesheet = getPrincipalStyleSheet(); 744 Vector toplevel = stylesheet.getTopLevel(); 745 746 StringTokenizer st = new StringTokenizer(use); 747 while (st.hasMoreTokens()) { 748 String asetname = st.nextToken(); 749 int fprint; 750 try { 751 fprint = makeNameCode(asetname, false) & 0xfffff; 752 } catch (NamespaceException err) { 753 compileError(err.getMessage()); 754 fprint = -1; 755 } 756 boolean found = false; 757 758 761 for (int i=0; i<toplevel.size(); i++) { 762 if (toplevel.elementAt(i) instanceof XSLAttributeSet) { 763 XSLAttributeSet t = (XSLAttributeSet)toplevel.elementAt(i); 764 if (t.getAttributeSetFingerprint() == fprint) { 765 attributeSets.addElement(t); 766 found = true; 767 } 768 } 769 } 770 771 if (!found) { 772 compileError("No attribute-set exists named " + asetname); 773 } 774 } 775 } 776 777 780 781 protected void processAttributeSets(Context context) 782 throws TransformerException { 783 if (attributeSets==null) return; 784 Controller c = context.getController(); 785 for (int i=0; i<attributeSets.size(); i++) { 786 XSLAttributeSet aset = (XSLAttributeSet)attributeSets.elementAt(i); 787 788 Object isBeingExpanded = c.getUserData(aset, "is-being-expanded"); 790 if (isBeingExpanded!=null) { 791 throw styleError("Circular reference to attribute set"); 792 } 793 c.setUserData(aset, "is-being-expanded", "is-being-expanded"); 794 aset.expand(context); 795 c.setUserData(aset, "is-being-expanded", null); 796 } 797 } 798 799 802 803 protected TransformerException styleError(TransformerException error) { 804 if (error instanceof StyleException) return error; 805 if (error instanceof TerminationException) return error; 806 if (error.getLocator()==null) { 807 return new TransformerException (error.getMessage(), 808 this, 809 error.getException()); 810 } 811 return error; 812 } 813 814 protected TransformerException styleError(String message) { 815 return new TransformerException (message, this); 816 } 817 818 821 822 protected void compileError(TransformerException error) 823 throws TransformerConfigurationException { 824 if (error.getLocator()==null) { 825 error.setLocator(this); 826 } 827 PreparedStyleSheet pss = getPreparedStyleSheet(); 828 try { 829 if (pss==null) { 830 throw error; 832 } else { 833 pss.reportError(error); 834 } 835 } catch (TransformerException err2) { 836 if (err2 instanceof TransformerConfigurationException ) { 837 throw (TransformerConfigurationException )err2; 838 } 839 if (err2.getException() instanceof TransformerConfigurationException ) { 840 throw (TransformerConfigurationException )err2.getException(); 841 } 842 TransformerConfigurationException tce = new TransformerConfigurationException (error); 843 tce.setLocator(this); 844 throw tce; 845 } 846 } 847 848 protected void compileError(String message) 849 throws TransformerConfigurationException { 850 TransformerConfigurationException tce = 851 new TransformerConfigurationException (message); 852 tce.setLocator(this); 853 compileError(tce); 854 } 855 856 859 860 public boolean isTopLevel() { 861 return (getParentNode() instanceof XSLStyleSheet); 862 } 863 864 870 871 public Binding bindVariable(int fingerprint) throws XPathException { 872 Binding binding = getVariableBinding(fingerprint); 873 if (binding==null) { 874 throw new XPathException("Variable " + getNamePool().getDisplayName(fingerprint) + " has not been declared"); 875 } 876 return binding; 877 } 878 879 884 885 public Binding getVariableBinding(int fprint) { 886 NodeImpl curr = this; 887 NodeImpl prev = this; 888 889 if (!isTopLevel()) { 891 while (true) { 892 curr = (NodeImpl)curr.getPreviousSibling(); 893 while (curr==null) { 894 curr = (NodeImpl)prev.getParent(); 895 prev = curr; 896 if (curr.getParent() instanceof XSLStyleSheet) break; curr = (NodeImpl)curr.getPreviousSibling(); 898 } 899 if (curr.getParent() instanceof XSLStyleSheet) break; 900 if (curr instanceof Binding) { 901 int var = ((Binding)curr).getVariableFingerprint(); 902 if (var==fprint) { 903 return (Binding)curr; 904 } 905 } 906 } 907 } 908 909 912 XSLStyleSheet root = getPrincipalStyleSheet(); 913 Vector toplevel = root.getTopLevel(); 914 for (int i=toplevel.size()-1; i>=0; i--) { 915 Object child = toplevel.elementAt(i); 916 if (child instanceof Binding && child != this) { 917 int var = ((Binding)child).getVariableFingerprint(); 918 if (var==fprint) { 919 return (Binding)child; 920 } 921 } 922 } 923 924 return null; 925 } 926 927 932 933 public Enumeration[] getVariableNames() { Hashtable local = new Hashtable(); 935 Hashtable global = new Hashtable(); 936 937 NodeImpl curr = this; 938 NodeImpl prev = this; 939 NamePool pool = getNamePool(); 940 941 943 if (!isTopLevel()) { 944 while (true) { 945 curr = (NodeImpl)curr.getPreviousSibling(); 946 while (curr==null) { 947 curr = (NodeImpl)prev.getParent(); 948 prev = curr; 949 if (curr.getParent() instanceof XSLStyleSheet) break; curr = (NodeImpl)curr.getPreviousSibling(); 951 } 952 if (curr.getParentNode() instanceof XSLStyleSheet) break; 953 if (curr instanceof Binding) { 954 int fprint = ((Binding)curr).getVariableFingerprint(); 955 String uri = pool.getURI(fprint); 956 String lname = pool.getLocalName(fprint); 957 String varname = uri + "^" + lname; 958 if (local.get(varname)==null) { 959 local.put(varname, varname); 960 } 961 } 962 } 963 } 964 965 968 XSLStyleSheet root = getPrincipalStyleSheet(); 969 Vector toplevel = root.getTopLevel(); 970 for (int i=0; i<toplevel.size(); i++) { 971 Object child = toplevel.elementAt(i); 972 if (child instanceof Binding && child != this) { 973 int fprint = ((Binding)child).getVariableFingerprint(); 974 String uri = pool.getURI(fprint); 975 String lname = pool.getLocalName(fprint); 976 String varname = uri + "^" + lname; 977 if (local.get(varname)==null) { 978 global.put(varname, varname); 979 } 980 } 981 } 982 983 Enumeration info[] = new Enumeration[2]; 984 info[0] = global.keys(); 985 info[1] = local.keys(); 986 return info; 987 } 988 989 990 995 996 public Function getStyleSheetFunction(int fingerprint) { 997 998 1000 XSLStyleSheet root = getPrincipalStyleSheet(); 1001 Vector toplevel = root.getTopLevel(); 1002 for (int i=toplevel.size()-1; i>=0; i--) { 1003 Object child = toplevel.elementAt(i); 1004 if (child instanceof SAXONFunction && 1005 ((SAXONFunction)child).getFunctionFingerprint() == fingerprint) { 1006 StyleSheetFunctionCall fc = new StyleSheetFunctionCall(); 1007 fc.setFunction((SAXONFunction)child); 1008 return fc; 1009 } 1010 } 1011 return null; 1012 } 1013 1014 1016 1017 } 1021 1022 | Popular Tags |