1 package net.sf.saxon.style; 2 3 import net.sf.saxon.Err; 4 import net.sf.saxon.PreparedStylesheet; 5 import net.sf.saxon.Configuration; 6 import net.sf.saxon.event.LocationProvider; 7 import net.sf.saxon.expr.*; 8 import net.sf.saxon.instruct.*; 9 import net.sf.saxon.om.*; 10 import net.sf.saxon.pattern.*; 11 import net.sf.saxon.sort.SortKeyDefinition; 12 import net.sf.saxon.trace.InstructionInfo; 13 import net.sf.saxon.trace.Location; 14 import net.sf.saxon.trans.DynamicError; 15 import net.sf.saxon.trans.SaxonErrorCode; 16 import net.sf.saxon.trans.StaticError; 17 import net.sf.saxon.trans.XPathException; 18 import net.sf.saxon.tree.ElementWithAttributes; 19 import net.sf.saxon.type.*; 20 import net.sf.saxon.value.*; 21 import org.xml.sax.Locator ; 22 23 import javax.xml.transform.SourceLocator ; 24 import javax.xml.transform.TransformerConfigurationException ; 25 import javax.xml.transform.TransformerException ; 26 import java.math.BigDecimal ; 27 import java.util.ArrayList ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.StringTokenizer ; 31 32 38 39 public abstract class StyleElement extends ElementWithAttributes 40 implements Locator , Container, InstructionInfo { 41 42 protected short[] extensionNamespaces = null; private short[] excludedNamespaces = null; protected BigDecimal version = null; 45 protected StaticContext staticContext = null; 46 protected StaticError validationError = null; 47 protected int reportingCircumstances = REPORT_ALWAYS; 48 protected String defaultXPathNamespace = null; 49 protected String defaultCollationName = null; 50 private int lineNumber; private boolean explaining = false; 53 private int objectNameCode = -1; 55 private XSLStylesheet containingStylesheet; 57 58 60 public static final int REPORT_ALWAYS = 1; 61 public static final int REPORT_UNLESS_FORWARDS_COMPATIBLE = 2; 62 public static final int REPORT_IF_INSTANTIATED = 3; 63 64 67 68 public StyleElement() { 69 } 70 71 public Executable getExecutable() { 72 return getPrincipalStylesheet().getExecutable(); 73 } 74 75 78 79 public LocationProvider getLocationProvider() { 80 return getExecutable().getLocationMap(); 81 } 82 83 87 88 public NamePool getTargetNamePool() { 89 return getPrincipalStylesheet().getTargetNamePool(); 90 } 91 92 97 98 public StaticContext getStaticContext() { 99 if (staticContext == null) { 100 staticContext = new ExpressionContext(this); 101 } 102 return staticContext; 103 } 104 105 public int getLineNumber() { 106 return lineNumber; 107 } 108 109 public void setLineNumber(int lineNumber) { 110 this.lineNumber = lineNumber; 111 } 112 113 116 117 protected boolean isExplaining() { 118 return explaining; 119 } 120 121 127 128 public void substituteFor(StyleElement temp) { 129 this.parent = temp.parent; 130 this.attributeList = temp.attributeList; 131 this.namespaceList = temp.namespaceList; 132 this.nameCode = temp.nameCode; 133 this.sequence = temp.sequence; 134 this.extensionNamespaces = temp.extensionNamespaces; 135 this.excludedNamespaces = temp.excludedNamespaces; 136 this.version = temp.version; 137 this.root = temp.root; 138 this.staticContext = temp.staticContext; 139 this.validationError = temp.validationError; 140 this.reportingCircumstances = temp.reportingCircumstances; 141 this.lineNumber = temp.lineNumber; 142 } 143 144 147 148 protected void setValidationError(TransformerException reason, 149 int circumstances) { 150 validationError = StaticError.makeStaticError(reason); 151 reportingCircumstances = circumstances; 152 } 153 154 157 158 public boolean isInstruction() { 159 return false; 160 } 161 162 171 172 protected ItemType getReturnedItemType() { 173 return AnyItemType.getInstance(); 174 } 175 176 181 182 protected ItemType getCommonChildItemType() { 183 ItemType t = NoNodeTest.getInstance(); 184 AxisIterator children = iterateAxis(Axis.CHILD); 185 while (true) { 186 NodeInfo next = (NodeInfo)children.next(); 187 if (next == null) { 188 return t; 189 } 190 if (next instanceof StyleElement) { 191 ItemType ret = ((StyleElement)next).getReturnedItemType(); 192 if (ret != null) { 193 t = Type.getCommonSuperType(t, ret); 194 } 195 } else { 196 t = Type.getCommonSuperType(t, NodeKindTest.TEXT); 197 } 198 if (t == AnyItemType.getInstance()) { 199 return t; } 201 } 202 } 203 204 208 209 public void markTailCalls() { 210 } 212 213 216 217 public boolean mayContainSequenceConstructor() { 218 return false; 219 } 220 221 225 226 public boolean mayContainFallback() { 227 return mayContainSequenceConstructor(); 228 } 229 230 233 234 public XSLStylesheet getContainingStylesheet() { 235 if (containingStylesheet == null) { 236 if (this instanceof XSLStylesheet) { 237 containingStylesheet = (XSLStylesheet)this; 238 } else { 239 containingStylesheet = ((StyleElement)getParent()).getContainingStylesheet(); 240 } 241 } 242 return containingStylesheet; 243 } 244 245 248 249 public int getPrecedence() { 250 return getContainingStylesheet().getPrecedence(); 251 } 252 253 263 264 277 288 289 public final int makeNameCode(String qname) 290 throws XPathException, NamespaceException { 291 292 NamePool namePool = getTargetNamePool(); 293 String [] parts; 294 try { 295 parts = Name.getQNameParts(qname); 296 } catch (QNameException err) { 297 StaticError e2 = new StaticError(err.getMessage()); 298 e2.setErrorCode("XTSE0020"); 299 throw e2; 300 } 301 String prefix = parts[0]; 302 if ("".equals(prefix)) { 303 return namePool.allocate(prefix, (short)0, qname); 304 305 } else { 306 307 String uri = getURIForPrefix(prefix, false); 308 if (uri == null) { 309 throw new NamespaceException(prefix); 310 } 311 if (NamespaceConstant.isReserved(uri)) { 312 StaticError err = new StaticError("Namespace prefix " + prefix + " refers to a reserved namespace"); 313 err.setErrorCode("XTSE0080"); 314 throw err; 315 } 316 return namePool.allocate(prefix, uri, parts[1]); 317 } 318 319 } 320 321 325 326 public SavedNamespaceContext makeNamespaceContext() { 327 return new SavedNamespaceContext(getInScopeNamespaceCodes(), getNamePool()); 328 } 329 330 333 334 public void processAllAttributes() throws XPathException { 335 staticContext = new ExpressionContext(this); 336 processAttributes(); 337 AxisIterator kids = iterateAxis(Axis.CHILD); 338 while (true) { 339 NodeInfo child = (NodeInfo)kids.next(); 340 if (child == null) { 341 return; 342 } 343 if (child instanceof StyleElement) { 344 ((StyleElement)child).processAllAttributes(); 345 if (((StyleElement)child).explaining) { 346 explaining = true; 349 } 350 } 351 } 352 } 353 354 358 359 public String getAttributeValue(String clarkName) { 360 int fp = getNamePool().allocateClarkName(clarkName); 361 return getAttributeValue(fp); 362 } 363 364 368 369 public final void processAttributes() throws XPathException { 370 try { 371 prepareAttributes(); 372 } catch (XPathException err) { 373 if (forwardsCompatibleModeIsEnabled()) { 374 setValidationError(err, REPORT_IF_INSTANTIATED); 375 } else { 376 compileError(err); 377 } 378 } 379 } 380 381 386 387 protected void checkUnknownAttribute(int nc) throws XPathException { 388 389 String attributeURI = getNamePool().getURI(nc); 390 String elementURI = getURI(); 391 String clarkName = getNamePool().getClarkName(nc); 392 393 if (clarkName.equals(StandardNames.SAXON_EXPLAIN)) { 394 explaining = "yes".equals(getAttributeValue(nc & 0xfffff)); 395 } 396 397 if (forwardsCompatibleModeIsEnabled()) { 398 return; 400 } 401 402 404 if (isInstruction() && 405 clarkName.startsWith('{' + NamespaceConstant.XSLT) && 406 !(elementURI.equals(NamespaceConstant.XSLT)) && 407 (clarkName.endsWith("}default-collation") || 408 clarkName.endsWith("}xpath-default-namespace") || 409 clarkName.endsWith("}extension-element-prefixes") || 410 clarkName.endsWith("}exclude-result-prefixes") || 411 clarkName.endsWith("}version") || 412 clarkName.endsWith("}use-when"))) { 413 return; 414 } 415 416 418 if (elementURI.equals(NamespaceConstant.XSLT) && 419 (clarkName == StandardNames.DEFAULT_COLLATION || 420 clarkName == StandardNames.XPATH_DEFAULT_NAMESPACE || 421 clarkName == StandardNames.EXTENSION_ELEMENT_PREFIXES || 422 clarkName == StandardNames.EXCLUDE_RESULT_PREFIXES || 423 clarkName == StandardNames.VERSION || 424 clarkName == StandardNames.USE_WHEN)) { 425 return; 426 } 427 428 if ("".equals(attributeURI) || NamespaceConstant.XSLT.equals(attributeURI)) { 429 compileError("Attribute " + Err.wrap(getNamePool().getDisplayName(nc), Err.ATTRIBUTE) + 430 " is not allowed on element " + Err.wrap(getDisplayName(), Err.ELEMENT), "XTSE0010"); 431 } 432 } 433 434 435 440 441 public abstract void prepareAttributes() throws XPathException; 442 443 447 448 protected StyleElement getLastChildInstruction() { 449 StyleElement last = null; 450 AxisIterator kids = iterateAxis(Axis.CHILD); 451 while (true) { 452 NodeInfo child = (NodeInfo)kids.next(); 453 if (child == null) { 454 return last; 455 } 456 if (child instanceof StyleElement) { 457 last = (StyleElement)child; 458 } else { 459 last = null; 460 } 461 } 462 } 463 464 467 468 public Expression makeExpression(String expression) 469 throws XPathException { 470 try { 471 Expression exp = ExpressionTool.make(expression, 472 staticContext, 473 0, Token.EOF, 474 getLineNumber()); 475 return exp; 476 } catch (XPathException err) { 477 err.setLocator(this); 478 if (!forwardsCompatibleModeIsEnabled()) { 479 compileError(err); 480 } else if (err.isTypeError()) { 481 compileError(err); 482 } 483 ErrorExpression erexp = new ErrorExpression(err); 484 erexp.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 485 erexp.setParentExpression(this); 486 return erexp; 487 } 488 } 489 490 493 494 public Pattern makePattern(String pattern) 495 throws XPathException { 496 try { 497 return Pattern.make(pattern, staticContext, getPrincipalStylesheet().getExecutable()); 498 } catch (XPathException err) { 499 if (forwardsCompatibleModeIsEnabled()) { 500 compileWarning("Invalid pattern, ignored because in forwards-compatibility mode. " + 501 err.getMessage(), err.getErrorCodeLocalPart()); 502 return new NodeTestPattern(NoNodeTest.getInstance()); 503 } else { 504 compileError(err); 505 return new NodeTestPattern(AnyNodeTest.getInstance()); 506 } 507 } 508 } 509 510 513 514 public Expression makeAttributeValueTemplate(String expression) 515 throws XPathException { 516 try { 517 return AttributeValueTemplate.make(expression, getLineNumber(), staticContext); 518 } catch (XPathException err) { 519 compileError(err); 520 return new StringValue(expression); 521 } 522 } 523 524 527 528 public SequenceType makeSequenceType(String sequenceType) 529 throws XPathException { 530 getStaticContext(); 531 try { 532 ExpressionParser parser = new ExpressionParser(); 533 return parser.parseSequenceType(sequenceType, staticContext); 534 } catch (XPathException err) { 535 compileError(err); 536 return SequenceType.ANY_SEQUENCE; 538 } 539 } 540 541 546 547 protected void processExtensionElementAttribute(String nc) 548 throws XPathException { 549 String ext = getAttributeValue(nc); 550 if (ext != null) { 551 int count = 0; 553 StringTokenizer st1 = new StringTokenizer (ext); 554 while (st1.hasMoreTokens()) { 555 st1.nextToken(); 556 count++; 557 } 558 extensionNamespaces = new short[count]; 559 count = 0; 560 StringTokenizer st2 = new StringTokenizer (ext); 561 while (st2.hasMoreTokens()) { 562 String s = st2.nextToken(); 563 if ("#default".equals(s)) { 564 s = ""; 565 } 566 try { 567 short uriCode = getURICodeForPrefix(s); 568 extensionNamespaces[count++] = uriCode; 569 } catch (NamespaceException err) { 570 extensionNamespaces = null; 571 compileError(err.getMessage(), "XT0280"); 572 } 573 } 574 } 575 } 576 577 582 583 protected void processExcludedNamespaces(String nc) 584 throws XPathException { 585 String ext = getAttributeValue(nc); 586 if (ext != null) { 587 if ("#all".equals(ext.trim())) { 588 int[] codes = getInScopeNamespaceCodes(); 589 excludedNamespaces = new short[codes.length]; 590 for (int i = 0; i < codes.length; i++) { 591 excludedNamespaces[i] = (short)(codes[i] & 0xffff); 592 } 593 } else { 594 int count = 0; 596 StringTokenizer st1 = new StringTokenizer (ext); 597 while (st1.hasMoreTokens()) { 598 st1.nextToken(); 599 count++; 600 } 601 excludedNamespaces = new short[count]; 602 count = 0; 603 StringTokenizer st2 = new StringTokenizer (ext); 604 while (st2.hasMoreTokens()) { 605 String s = st2.nextToken(); 606 if ("#default".equals(s)) { 607 s = ""; 608 } else if ("#all".equals(s)) { 609 compileError("In exclude-result-prefixes, cannot mix #all with other values", "XTSE0020"); 610 } 611 try { 612 short uriCode = getURICodeForPrefix(s); 613 excludedNamespaces[count++] = uriCode; 614 } catch (NamespaceException err) { 615 excludedNamespaces = null; 616 compileError(err.getMessage(), "XTSE0280"); 617 } 618 } 619 } 620 } 621 } 622 623 628 629 protected void processVersionAttribute(String nc) throws XPathException { 630 String v = getAttributeValue(nc); 631 if (v != null) { 632 AtomicValue val = DecimalValue.makeDecimalValue(v, true); 633 if (val instanceof ValidationErrorValue) { 634 compileError("The version attribute must be a decimal literal"); 635 } 636 version = ((DecimalValue)val).getValue(); 637 } 638 } 639 640 644 645 public BigDecimal getVersion() { 646 if (version == null) { 647 NodeInfo node = getParent(); 648 if (node instanceof StyleElement) { 649 version = ((StyleElement)node).getVersion(); 650 } else { 651 version = new BigDecimal ("2.0"); } 653 } 654 return version; 655 } 656 657 660 661 public boolean forwardsCompatibleModeIsEnabled() { 662 return getVersion().compareTo(BigDecimal.valueOf(2)) > 0; 663 } 664 665 668 669 public boolean backwardsCompatibleModeIsEnabled() { 670 return getVersion().compareTo(BigDecimal.valueOf(2)) < 0; 671 } 672 673 678 679 protected void processDefaultCollationAttribute(String nc) throws XPathException { 680 String v = getAttributeValue(nc); 681 if (v != null) { 682 StringTokenizer st = new StringTokenizer (v); 683 while (st.hasMoreTokens()) { 684 String uri = st.nextToken(); 685 if (uri.equals(NamespaceConstant.CODEPOINT_COLLATION_URI)) { 686 defaultCollationName = uri; 687 return; 688 } else if (uri.startsWith("http://saxon.sf.net/")) { 689 defaultCollationName = uri; 690 return; 691 } else if (getPrincipalStylesheet().getExecutable().getNamedCollation(uri) != null) { 692 defaultCollationName = uri; 693 return; 694 } 695 } 697 compileError("No recognized collation URI found in default-collation attribute", "XTSE0125"); 698 } 699 } 700 701 704 705 protected String getDefaultCollationName() { 706 StyleElement e = this; 707 while (true) { 708 if (e.defaultCollationName != null) { 709 return e.defaultCollationName; 710 } 711 NodeInfo p = e.getParent(); 712 if (!(p instanceof StyleElement)) { 713 break; 714 } 715 e = (StyleElement)p; 716 } 717 return getPrincipalStylesheet().getDefaultCollationName(); 718 } 719 720 728 729 protected boolean definesExtensionElement(short uriCode) { 730 if (extensionNamespaces == null) { 731 return false; 732 } 733 for (int i = 0; i < extensionNamespaces.length; i++) { 734 if (extensionNamespaces[i] == uriCode) { 735 return true; 736 } 737 } 738 return false; 739 } 740 741 747 748 public boolean isExtensionNamespace(short uriCode) { 749 NodeInfo anc = this; 750 while (anc instanceof StyleElement) { 751 if (((StyleElement)anc).definesExtensionElement(uriCode)) { 752 return true; 753 } 754 anc = anc.getParent(); 755 } 756 return false; 757 } 758 759 765 766 protected boolean definesExcludedNamespace(short uriCode) { 767 if (excludedNamespaces == null) { 768 return false; 769 } 770 for (int i = 0; i < excludedNamespaces.length; i++) { 771 if (excludedNamespaces[i] == uriCode) { 772 return true; 773 } 774 } 775 return false; 776 } 777 778 785 786 public boolean isExcludedNamespace(short uriCode) { 787 if (uriCode == NamespaceConstant.XSLT_CODE) { 788 return true; 789 } 790 if (isExtensionNamespace(uriCode)) { 791 return true; 792 } 793 NodeInfo anc = this; 794 while (anc instanceof StyleElement) { 795 if (((StyleElement)anc).definesExcludedNamespace(uriCode)) { 796 return true; 797 } 798 anc = anc.getParent(); 799 } 800 return false; 801 } 802 803 808 809 protected void processDefaultXPathNamespaceAttribute(String nc) throws TransformerConfigurationException { 810 String v = getAttributeValue(nc); 811 if (v != null) { 812 defaultXPathNamespace = v; 813 } 814 } 815 816 819 820 protected short getDefaultXPathNamespace() { 821 NodeInfo anc = this; 822 while (anc instanceof StyleElement) { 823 String x = ((StyleElement)anc).defaultXPathNamespace; 824 if (x != null) { 825 return getTargetNamePool().allocateCodeForURI(x); 826 } 827 anc = anc.getParent(); 828 } 829 return NamespaceConstant.NULL_CODE; 830 } 832 833 841 842 public SchemaType getSchemaType(String typeAtt) throws XPathException { 843 try { 844 String [] parts = Name.getQNameParts(typeAtt); 845 String lname = parts[1]; 846 String uri; 847 if ("".equals(parts[0])) { 848 short uricode = getDefaultXPathNamespace(); 850 uri = getTargetNamePool().getURIFromURICode(uricode); 851 nameCode = getTargetNamePool().allocate(parts[0], uricode, lname); 852 } else { 853 uri = getURIForPrefix(parts[0], false); 854 if (uri == null) { 855 compileError("Namespace prefix for type annotation is undeclared", "XTSE0280"); 856 return null; 857 } 858 } 859 int nameCode = getTargetNamePool().allocate(parts[0], uri, lname); 860 if (uri.equals(NamespaceConstant.SCHEMA)) { 861 SchemaType t = BuiltInSchemaFactory.getSchemaType(StandardNames.getFingerprint(uri, lname)); 862 if (t == null) { 863 compileError("Unknown built-in type " + typeAtt); 864 return null; 865 } 866 return t; 867 } else if (NamespaceConstant.isXDTNamespace(uri)) { 868 ItemType t = Type.getBuiltInItemType(NamespaceConstant.XDT, lname); 869 if (t == null) { 870 if ("untyped".equals(lname)) { 871 compileError("Cannot validate a node as 'untyped'"); 872 } else { 873 compileError("Unknown built-in type " + typeAtt); 874 } 875 } 876 return (BuiltInAtomicType)t; 877 } 878 879 881 if (!getPrincipalStylesheet().isImportedSchema(uri)) { 882 compileError("There is no imported schema for the namespace of type " + typeAtt); 883 return null; 884 } 885 SchemaType stype = getConfiguration().getSchemaType(nameCode & 0xfffff); 886 if (stype == null) { 887 compileError("There is no type named " + typeAtt + " in an imported schema"); 888 } 889 return stype; 890 891 } catch (QNameException err) { 892 compileError("Invalid type name. " + err.getMessage()); 893 } 894 return null; 895 } 896 897 900 901 public int getTypeAnnotation(SchemaType schemaType) { 902 if (schemaType != null) { 903 return schemaType.getFingerprint(); 904 } else { 905 return -1; 906 } 907 } 908 909 915 916 public void validate() throws XPathException { 917 } 918 919 923 924 public void postValidate() throws XPathException { 925 } 926 927 932 933 937 public Expression typeCheck(String name, Expression exp) throws XPathException { 938 939 if (exp == null) { 940 return null; 941 } 942 943 if (exp instanceof ComputedExpression) { 945 ((ComputedExpression)exp).setParentExpression(this); 946 } 948 949 try { 950 exp = exp.typeCheck(staticContext, Type.ITEM_TYPE); 951 exp = ExpressionTool.resolveCallsToCurrentFunction(exp, getConfiguration()); 952 if (getConfiguration().getTraceListener() != null) { 960 InstructionDetails details = new InstructionDetails(); 961 details.setConstructType(Location.XPATH_IN_XSLT); 962 details.setLineNumber(getLineNumber()); 963 details.setSystemId(getSystemId()); 964 details.setProperty("attribute-name", name); 965 TraceWrapper trace = new TraceInstruction(exp, details); 966 trace.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 967 trace.setParentExpression(this); 968 exp = trace; 969 } 970 return exp; 971 } catch (DynamicError err) { 972 if (err.isTypeError()) { 975 compileError(err); 976 return exp; 977 } else { 978 ErrorExpression erexp = new ErrorExpression(err); 979 erexp.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 980 return erexp; 981 } 982 } catch (XPathException err) { 983 compileError(err); 984 ErrorExpression erexp = new ErrorExpression(err); 985 erexp.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 986 return erexp; 987 } 988 } 989 990 995 996 public void allocateSlots(Expression exp) { 997 SlotManager slotManager = getContainingSlotManager(); 998 if (slotManager == null) { 999 throw new AssertionError ("Slot manager has not been allocated"); 1000 } else { 1002 int firstSlot = slotManager.getNumberOfVariables(); 1003 int highWater = ExpressionTool.allocateSlots(exp, firstSlot, slotManager); 1004 if (highWater > firstSlot) { 1005 slotManager.setNumberOfVariables(highWater); 1006 } 1012 } 1013 } 1014 1015 1020 1021 public Pattern typeCheck(String name, Pattern pattern) throws XPathException { 1022 if (pattern == null) { 1023 return null; 1024 } 1025 try { 1026 pattern = pattern.analyze(staticContext, Type.NODE_TYPE); 1027 boolean usesCurrent = false; 1028 int current = getNamePool().allocate("", NamespaceConstant.FN, "current") & NamePool.FP_MASK; 1029 if (pattern instanceof LocationPathPattern) { 1030 Iterator sub = pattern.iterateSubExpressions(); 1031 while (sub.hasNext()) { 1032 Expression filter = (Expression)sub.next(); 1033 if (ExpressionTool.callsFunction(filter, current)) { 1034 usesCurrent = true; 1035 break; 1036 } 1037 } 1038 if (usesCurrent) { 1039 Configuration config = getConfiguration(); 1040 RangeVariableDeclaration decl = new RangeVariableDeclaration(); 1041 decl.setNameCode(config.getNamePool().allocate("saxon", NamespaceConstant.SAXON, "current" + hashCode())); 1042 decl.setVariableName("saxon:current"); 1043 decl.setRequiredType(SequenceType.SINGLE_ITEM); 1044 LetExpression let = new LetExpression(); 1045 let.setSequence(new ContextItemExpression()); 1046 let.setVariableDeclaration(decl); 1047 let.setAction(EmptySequence.getInstance()); 1048 PromotionOffer offer = new PromotionOffer(config.getOptimizer()); 1049 offer.action = PromotionOffer.REPLACE_CURRENT; 1050 offer.containingExpression = let; 1051 ((LocationPathPattern)pattern).resolveCurrent(let, offer); 1052 allocateSlots(let); 1053 decl.fixupReferences(let); 1054 } 1055 } 1056 return pattern; 1057 } catch (DynamicError err) { 1058 LocationPathPattern errpat = new LocationPathPattern(); 1062 errpat.addFilter(new ErrorExpression(err)); 1063 return errpat; 1064 } catch (XPathException err) { 1065 StaticError e2 = new StaticError("Error in " + name + " pattern", err); 1066 e2.setLocator(err.getLocator()); 1067 e2.setErrorCode(err.getErrorCodeLocalPart()); 1068 throw e2; 1069 } 1070 } 1071 1072 1076 1077 public void fixupReferences() throws XPathException { 1078 AxisIterator kids = iterateAxis(Axis.CHILD); 1079 while (true) { 1080 NodeInfo child = (NodeInfo)kids.next(); 1081 if (child == null) { 1082 return; 1083 } 1084 if (child instanceof StyleElement) { 1085 ((StyleElement)child).fixupReferences(); 1086 } 1087 } 1088 } 1089 1090 1096 1097 public SlotManager getContainingSlotManager() { 1098 NodeInfo node = this; 1099 while (true) { 1100 NodeInfo next = node.getParent(); 1101 if (next instanceof XSLStylesheet) { 1102 if (node instanceof StylesheetProcedure) { 1103 return ((StylesheetProcedure)node).getSlotManager(); 1104 } else { 1105 return null; 1106 } 1107 } 1108 node = next; 1109 } 1110 } 1111 1112 1113 1116 1117 public void validateSubtree() throws XPathException { 1118 if (validationError != null) { 1119 if (reportingCircumstances == REPORT_ALWAYS) { 1120 compileError(validationError); 1121 } else if (reportingCircumstances == REPORT_UNLESS_FORWARDS_COMPATIBLE 1122 && !forwardsCompatibleModeIsEnabled()) { 1123 compileError(validationError); 1124 } 1125 } 1126 try { 1127 validate(); 1128 } catch (XPathException err) { 1129 if (forwardsCompatibleModeIsEnabled()) { 1130 setValidationError(err, REPORT_IF_INSTANTIATED); 1131 } else { 1132 compileError(err); 1133 } 1134 } 1135 1136 validateChildren(); 1137 postValidate(); 1138 } 1139 1140 1144 1145 protected void validateChildren() throws XPathException { 1146 boolean containsInstructions = mayContainSequenceConstructor(); 1147 AxisIterator kids = iterateAxis(Axis.CHILD); 1148 StyleElement lastChild = null; 1149 while (true) { 1150 NodeInfo child = (NodeInfo)kids.next(); 1151 if (child == null) { 1152 break; 1153 } 1154 if (child instanceof StyleElement) { 1155 if (containsInstructions && !((StyleElement)child).isInstruction() 1156 && !isPermittedChild((StyleElement)child)) { 1157 ((StyleElement)child).compileError( 1158 "An " + getDisplayName() + " element must not contain an " + 1159 child.getDisplayName() + " element", "XTSE0010"); 1160 } 1161 ((StyleElement)child).validateSubtree(); 1162 lastChild = (StyleElement)child; 1163 } 1164 } 1165 if (lastChild instanceof XSLVariable && 1166 !(this instanceof XSLStylesheet)) { 1167 lastChild.compileWarning( 1168 "A variable with no following sibling instructions has no effect", 1169 SaxonErrorCode.SXWN9001); 1170 } 1171 } 1172 1173 1176 1177 protected boolean isPermittedChild(StyleElement child) { 1178 return false; 1179 } 1180 1181 1185 1186 protected XSLStylesheet getPrincipalStylesheet() { 1187 XSLStylesheet sheet = getContainingStylesheet(); 1188 while (true) { 1189 XSLStylesheet next = sheet.getImporter(); 1190 if (next == null) { 1191 return sheet; 1192 } 1193 sheet = next; 1194 } 1195 } 1196 1197 1202 1203 public PreparedStylesheet getPreparedStylesheet() { 1204 return getPrincipalStylesheet().getPreparedStylesheet(); 1205 } 1206 1207 1213 1214 public void checkWithinTemplate() throws XPathException { 1215 } 1221 1222 1229 1230 protected void checkSortComesFirst(boolean sortRequired) throws XPathException { 1231 AxisIterator kids = iterateAxis(Axis.CHILD); 1232 boolean sortFound = false; 1233 boolean nonSortFound = false; 1234 while (true) { 1235 NodeInfo child = (NodeInfo)kids.next(); 1236 if (child == null) { 1237 break; 1238 } 1239 if (child instanceof XSLSort) { 1240 if (nonSortFound) { 1241 ((XSLSort)child).compileError("Within " + getDisplayName() + 1242 ", xsl:sort elements must come before other instructions", "XTSE0010"); 1243 } 1244 sortFound = true; 1245 } else if (child.getNodeKind() == Type.TEXT) { 1246 if (!Whitespace.isWhite(child.getStringValueCS())) { 1248 nonSortFound = true; 1249 } 1250 } else { 1251 nonSortFound = true; 1252 } 1253 } 1254 if (sortRequired && !sortFound) { 1255 compileError(getDisplayName() + " must have at least one xsl:sort child", "XTSE0010"); 1256 } 1257 } 1258 1259 1265 1266 public void checkTopLevel(String errorCode) throws XPathException { 1267 if (errorCode == null) { 1268 errorCode = "XTSE0010"; 1269 } 1270 if (!(getParent() instanceof XSLStylesheet)) { 1271 compileError("Element must be used only at top level of stylesheet", errorCode); 1272 } 1273 } 1274 1275 1281 1282 public void checkEmpty() throws XPathException { 1283 if (hasChildNodes()) { 1284 compileError("Element must be empty", "XTSE0260"); 1285 } 1286 } 1287 1288 1294 1295 public void reportAbsence(String attribute) 1296 throws XPathException { 1297 compileError("Element must have a \"" + attribute + "\" attribute", "XTSE0010"); 1298 } 1299 1300 1301 1309 1310 public abstract Expression compile(Executable exec) throws XPathException; 1311 1312 1318 1319 public Expression compileSequenceConstructor(Executable exec, AxisIterator iter, boolean includeParams) 1320 throws XPathException { 1321 1322 int lineNumber = getLineNumber(); 1323 NodeInfo node = (NodeInfo)iter.next(); 1324 if (node == null) { 1325 return null; 1326 } 1327 if (node instanceof StyleElement) { 1328 lineNumber = node.getLineNumber(); } 1330 if (node.getNodeKind() == Type.TEXT) { 1331 ValueOf text = new ValueOf(StringValue.makeStringValue(node.getStringValueCS()), false, false); 1333 text.setLocationId(allocateLocationId(getSystemId(), lineNumber)); 1334 Expression tail = compileSequenceConstructor(exec, iter, includeParams); 1335 if (tail == null) { 1336 return text; 1337 } else { 1338 Block e = Block.makeBlock(text, tail); 1339 e.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 1340 return e; 1341 } 1342 1343 } else if (node instanceof XSLVariable) { 1344 Expression var = ((XSLVariable)node).compileLocalVariable(exec); 1345 if (var == null) { 1346 return compileSequenceConstructor(exec, iter, includeParams); 1348 } else { 1349 LocalVariable lv = (LocalVariable)var; 1350 Expression tail = compileSequenceConstructor(exec, iter, includeParams); 1351 if (tail == null) { 1352 return null; 1355 } else { 1356 LetExpression let = new LetExpression(); 1357 RangeVariableDeclaration rvar = new RangeVariableDeclaration(); 1358 rvar.setRequiredType(lv.getRequiredType()); 1359 rvar.setNameCode(lv.getNameCode()); 1360 rvar.setVariableName(lv.getVariableName()); 1361 rvar.setReferenceList(((XSLVariable)node).getReferenceList()); 1362 let.setVariableDeclaration(rvar); 1363 let.setSequence(lv.getSelectExpression()); 1364 let.setAction(tail); 1366 ((XSLVariable)node).fixupBinding(let); 1367 let.setLocationId(allocateLocationId(node.getSystemId(), node.getLineNumber())); 1368 if (getConfiguration().getTraceListener() != null) { 1369 TraceExpression t = new TraceExpression(let); 1370 t.setConstructType(Location.LET_EXPRESSION); 1371 t.setObjectNameCode(lv.getNameCode()); 1372 t.setSystemId(node.getSystemId()); 1373 t.setLineNumber(node.getLineNumber()); 1374 return t; 1375 } 1376 return let; 1377 } 1378 } 1379 1380 1381 } else if (node instanceof StyleElement) { 1382 StyleElement snode = (StyleElement)node; 1383 if (snode.validationError != null) { 1384 return fallbackProcessing(exec, snode); 1385 1386 } else { 1387 Expression child = snode.compile(exec); 1388 if (child instanceof ComputedExpression) { 1389 ComputedExpression childi = (ComputedExpression)child; 1390 childi.setLocationId(allocateLocationId(getSystemId(), snode.getLineNumber())); 1391 } 1392 if (child != null) { 1393 if (includeParams || !(node instanceof XSLParam)) { 1394 if (getConfiguration().getTraceListener() != null) { 1395 TraceWrapper trace = makeTraceInstruction(snode, child); 1396 child = trace; 1397 } 1398 } 1399 } 1400 Expression tail = compileSequenceConstructor(exec, iter, includeParams); 1401 if (tail == null) { 1402 return child; 1403 } else if (child == null) { 1404 return tail; 1405 } else { 1406 Block e = Block.makeBlock(child, tail); 1408 e.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 1409 return e; 1410 } 1411 } 1412 } 1413 return null; 1414 } 1415 1416 1419 1420 protected static TraceWrapper makeTraceInstruction(StyleElement source, Expression child) { 1421 if (child instanceof TraceWrapper) { 1422 return (TraceWrapper)child; 1423 } 1425 1426 TraceWrapper trace = new TraceInstruction(child, source); 1427 trace.setLocationId(source.allocateLocationId(source.getSystemId(), source.getLineNumber())); 1428 return trace; 1429 } 1430 1431 1437 1438 protected Expression fallbackProcessing(Executable exec, StyleElement instruction) 1439 throws XPathException { 1440 Expression fallback = null; 1443 AxisIterator kids = instruction.iterateAxis(Axis.CHILD); 1444 while (true) { 1445 NodeInfo child = (NodeInfo)kids.next(); 1446 if (child == null) { 1447 break; 1448 } 1449 if (child instanceof XSLFallback) { 1450 Expression b = ((XSLFallback)child).compileSequenceConstructor(exec, child.iterateAxis(Axis.CHILD), true); 1453 if (b == null) { 1454 b = EmptySequence.getInstance(); 1455 } 1456 if (fallback == null) { 1457 fallback = b; 1458 } else { 1459 fallback = Block.makeBlock(fallback, b); 1461 } 1462 } 1463 } 1464 if (fallback != null) { 1465 return fallback; 1466 } else { 1467 DeferredError deferred = new DeferredError(instruction.getNameCode(), instruction.validationError); 1468 deferred.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 1469 deferred.setParentExpression(this); 1470 instruction.validationError.setLocator(deferred); 1471 return deferred; 1472 } 1473 1474 } 1475 1476 1479 1480 public int allocateLocationId(String systemId, int lineNumber) { 1481 return getStaticContext().getLocationMap().allocateLocationId(systemId, lineNumber); 1482 } 1483 1484 1490 1491 protected SortKeyDefinition[] makeSortKeys() { 1492 1494 int numberOfSortKeys = 0; 1495 AxisIterator kids = iterateAxis(Axis.CHILD); 1496 while (true) { 1497 Item child = kids.next(); 1498 if (child == null) { 1499 break; 1500 } 1501 if (child instanceof XSLSort) { 1502 numberOfSortKeys++; 1503 } 1504 } 1505 1506 if (numberOfSortKeys > 0) { 1507 SortKeyDefinition[] keys = new SortKeyDefinition[numberOfSortKeys]; 1508 kids = iterateAxis(Axis.CHILD); 1509 int k = 0; 1510 while (true) { 1511 NodeInfo child = (NodeInfo)kids.next(); 1512 if (child == null) { 1513 break; 1514 } 1515 if (child instanceof XSLSort) { 1516 keys[k++] = ((XSLSort)child).getSortKeyDefinition(); 1517 } 1518 } 1519 return keys; 1520 1521 } else { 1522 return null; 1523 } 1524 } 1525 1526 1536 1537 protected AttributeSet[] getAttributeSets(String use, List list) 1538 throws XPathException { 1539 1540 if (list == null) { 1541 list = new ArrayList (4); 1542 } 1543 1544 XSLStylesheet stylesheet = getPrincipalStylesheet(); 1545 List toplevel = stylesheet.getTopLevel(); 1546 1547 StringTokenizer st = new StringTokenizer (use); 1548 while (st.hasMoreTokens()) { 1549 String asetname = st.nextToken(); 1550 int fprint; 1551 try { 1552 fprint = makeNameCode(asetname) & 0xfffff; 1553 } catch (NamespaceException err) { 1554 compileError(err.getMessage(), "XTSE0710"); 1555 fprint = -1; 1556 } catch (XPathException err) { 1557 compileError(err.getMessage(), "XTSE0710"); 1558 fprint = -1; 1559 } 1560 boolean found = false; 1561 1562 1565 for (int i = 0; i < toplevel.size(); i++) { 1566 if (toplevel.get(i) instanceof XSLAttributeSet) { 1567 XSLAttributeSet t = (XSLAttributeSet)toplevel.get(i); 1568 if (t.getAttributeSetFingerprint() == fprint) { 1569 list.add(t); 1570 found = true; 1571 } 1572 } 1573 } 1574 1575 if (!found) { 1576 compileError("No attribute-set exists named " + asetname, "XTSE0710"); 1577 } 1578 } 1579 1580 AttributeSet[] array = new AttributeSet[list.size()]; 1581 for (int i = 0; i < list.size(); i++) { 1582 XSLAttributeSet aset = (XSLAttributeSet)list.get(i); 1583 aset.incrementReferenceCount(); 1584 array[i] = aset.getInstruction(); 1585 } 1586 return array; 1587 } 1588 1589 1597 1598 protected WithParam[] getWithParamInstructions(Executable exec, boolean tunnel, Instruction caller) 1599 throws XPathException { 1600 int count = 0; 1601 AxisIterator kids = iterateAxis(Axis.CHILD); 1602 while (true) { 1603 NodeInfo child = (NodeInfo)kids.next(); 1604 if (child == null) { 1605 break; 1606 } 1607 if (child instanceof XSLWithParam) { 1608 XSLWithParam wp = (XSLWithParam)child; 1609 if (wp.isTunnelParam() == tunnel) { 1610 count++; 1611 } 1612 } 1613 } 1614 WithParam[] array = new WithParam[count]; 1615 count = 0; 1616 kids = iterateAxis(Axis.CHILD); 1617 while (true) { 1618 NodeInfo child = (NodeInfo)kids.next(); 1619 if (child == null) { 1620 return array; 1621 } 1622 if (child instanceof XSLWithParam) { 1623 XSLWithParam wp = (XSLWithParam)child; 1624 if (wp.isTunnelParam() == tunnel) { 1625 WithParam p = (WithParam)wp.compile(exec); 1626 p.setParentExpression(caller); 1627 array[count++] = p; 1628 } 1629 1630 } 1631 } 1632 } 1633 1634 1644 1645 public String reportInvalidAttribute(String message, String errorCode) throws XPathException { 1646 if (forwardsCompatibleModeIsEnabled()) { 1650 String m = message + " (attribute value ignored because in forwards-compatible mode)"; 1651 compileWarning(m, errorCode); 1652 } else { 1653 compileError(message, errorCode); 1654 } 1655 return null; 1656 } 1657 1658 1661 1662 protected void compileError(TransformerException error) 1663 throws XPathException { 1664 1665 if (error.getLocator() == null || error.getLocator() instanceof ExpressionLocation) { 1668 error.setLocator(this); 1669 } 1670 PreparedStylesheet pss = getPreparedStylesheet(); 1671 try { 1672 if (pss == null) { 1673 throw error; 1675 } else { 1676 pss.reportError(error); 1677 } 1678 } catch (TransformerException err2) { 1679 if (err2.getLocator() == null) { 1680 err2.setLocator(this); 1681 } 1682 throw StaticError.makeStaticError(err2); 1683 } 1684 } 1685 1686 protected void compileError(String message) 1687 throws XPathException { 1688 StaticError tce = new StaticError(message); 1689 tce.setLocator(this); 1690 compileError(tce); 1691 } 1692 1693 1701 1702 protected void compileError(String message, String errorCode) throws XPathException { 1703 StaticError tce = new StaticError(message); 1704 tce.setErrorCode(errorCode); 1705 tce.setLocator(this); 1706 compileError(tce); 1707 } 1708 1709 protected void undeclaredNamespaceError(String prefix, String errorCode) throws XPathException { 1710 if (errorCode==null) { 1711 errorCode = "XTSE0280"; 1712 } 1713 compileError("Undeclared namespace prefix " + Err.wrap(prefix), errorCode); 1714 } 1715 1716 protected void compileWarning(String message, String errorCode) 1717 throws XPathException { 1718 StaticError tce = new StaticError(message); 1719 tce.setErrorCode(errorCode); 1720 tce.setLocator(this); 1721 PreparedStylesheet pss = getPreparedStylesheet(); 1722 if (pss != null) { 1723 pss.reportWarning(tce); 1724 } 1725 } 1726 1727 1730 1731 protected void issueWarning(TransformerException error) { 1732 if (error.getLocator() == null) { 1733 error.setLocator(this); 1734 } 1735 PreparedStylesheet pss = getPreparedStylesheet(); 1736 if (pss != null) { 1737 pss.reportWarning(error); 1739 } 1740 } 1741 1742 protected void issueWarning(String message, SourceLocator locator) { 1743 TransformerConfigurationException tce = 1744 new TransformerConfigurationException (message); 1745 if (locator == null) { 1746 tce.setLocator(this); 1747 } else { 1748 tce.setLocator(locator); 1749 } 1750 issueWarning(tce); 1751 } 1752 1753 1756 1757 public boolean isTopLevel() { 1758 return (getParent() instanceof XSLStylesheet); 1759 } 1760 1761 1769 1770 public XSLVariableDeclaration bindVariable(int fingerprint) throws StaticError { 1771 XSLVariableDeclaration binding = getVariableBinding(fingerprint); 1772 if (binding == null) { 1773 StaticError err = new StaticError("Variable " + getTargetNamePool().getDisplayName(fingerprint) + 1774 " has not been declared"); 1775 err.setErrorCode("XPST0008"); 1776 throw err; 1777 } 1778 return binding; 1779 } 1780 1781 1787 1788 private XSLVariableDeclaration getVariableBinding(int fprint) { 1789 NodeInfo curr = this; 1790 NodeInfo prev = this; 1791 1792 if (!isTopLevel()) { 1794 AxisIterator preceding = curr.iterateAxis(Axis.PRECEDING_SIBLING); 1795 while (true) { 1796 curr = (NodeInfo)preceding.next(); 1797 while (curr == null) { 1798 curr = prev.getParent(); 1799 while (curr instanceof XSLFallback) { 1800 curr = curr.getParent(); 1802 } 1803 prev = curr; 1804 if (curr.getParent() instanceof XSLStylesheet) { 1805 break; } 1807 preceding = curr.iterateAxis(Axis.PRECEDING_SIBLING); 1808 curr = (NodeInfo)preceding.next(); 1809 } 1810 if (curr.getParent() instanceof XSLStylesheet) { 1811 break; 1812 } 1813 if (curr instanceof XSLVariableDeclaration) { 1814 XSLVariableDeclaration var = (XSLVariableDeclaration)curr; 1815 if (var.getVariableFingerprint() == fprint) { 1816 return var; 1817 } 1818 } 1819 } 1820 } 1821 1822 1825 XSLStylesheet root = getPrincipalStylesheet(); 1826 XSLVariableDeclaration var = root.getGlobalVariable(fprint); 1827 return var; 1828 } 1829 1830 1835 1836 1837 1838 1847 1848 public XSLFunction getStylesheetFunction(int fingerprint, int arity) { 1849 1850 1852 XSLStylesheet root = getPrincipalStylesheet(); 1853 List toplevel = root.getTopLevel(); 1854 for (int i = toplevel.size() - 1; i >= 0; i--) { 1855 Object child = toplevel.get(i); 1856 if (child instanceof XSLFunction && 1857 ((XSLFunction)child).getFunctionFingerprint() == fingerprint && 1858 (arity == -1 || ((XSLFunction)child).getNumberOfArguments() == arity)) { 1859 XSLFunction func = (XSLFunction)child; 1860 return func; 1861 } 1862 } 1863 return null; 1864 } 1865 1866 1870 1871 public int getConstructType() { 1872 return getFingerprint(); 1873 } 1874 1875 1880 1881 public int getObjectNameCode() { 1882 return objectNameCode; 1883 } 1884 1885 1890 1891 public int getObjectFingerprint() { 1892 return (objectNameCode == -1 ? -1 : objectNameCode & 0xfffff); 1893 } 1894 1895 1898 1899 public void setObjectNameCode(int nameCode) { 1900 objectNameCode = nameCode; 1901 } 1902 1903 1906 1907 public NamespaceResolver getNamespaceResolver() { 1908 return makeNamespaceContext(); 1909 } 1910 1911 1920 1921 public Object getProperty(String name) { 1922 return getAttributeValue(name); 1923 } 1924 1925 1930 1931 public Iterator getProperties() { 1932 NamePool pool = getNamePool(); 1933 List list = new ArrayList (10); 1934 AxisIterator it = iterateAxis(Axis.ATTRIBUTE); 1935 while (true) { 1936 NodeInfo a = (NodeInfo)it.next(); 1937 if (a == null) { 1938 break; 1939 } 1940 list.add(pool.getClarkName(a.getNameCode())); 1941 } 1942 return list.iterator(); 1943 } 1944 1945 public String getSystemId(int locationId) { 1946 return getSystemId(); 1947 } 1948 1949 public int getLineNumber(int locationId) { 1950 return getLineNumber(); 1951 } 1952} 1953 1954 | Popular Tags |