1 package net.sf.saxon.style; 2 import net.sf.saxon.Err; 3 import net.sf.saxon.expr.*; 4 import net.sf.saxon.instruct.Executable; 5 import net.sf.saxon.instruct.SlotManager; 6 import net.sf.saxon.om.AttributeCollection; 7 import net.sf.saxon.om.Axis; 8 import net.sf.saxon.om.NamespaceException; 9 import net.sf.saxon.pattern.Pattern; 10 import net.sf.saxon.trans.KeyDefinition; 11 import net.sf.saxon.trans.KeyManager; 12 import net.sf.saxon.trans.XPathException; 13 import net.sf.saxon.type.Type; 14 import net.sf.saxon.value.SequenceType; 15 16 import javax.xml.transform.TransformerConfigurationException ; 17 import java.text.Collator ; 18 import java.util.Comparator ; 19 20 23 24 public class XSLKey extends StyleElement implements StylesheetProcedure { 25 26 private Pattern match; 27 private Expression use; 28 private String collationName; 29 SlotManager stackFrameMap; 30 35 36 public boolean mayContainSequenceConstructor() { 37 return true; 38 } 39 40 43 44 public SlotManager getSlotManager() { 45 return stackFrameMap; 46 } 47 48 public void prepareAttributes() throws XPathException { 49 50 String nameAtt = null; 51 String matchAtt = null; 52 String useAtt = null; 53 54 AttributeCollection atts = getAttributeList(); 55 56 for (int a=0; a<atts.getLength(); a++) { 57 int nc = atts.getNameCode(a); 58 String f = getNamePool().getClarkName(nc); 59 if (f==StandardNames.NAME) { 60 nameAtt = atts.getValue(a).trim(); 61 } else if (f==StandardNames.USE) { 62 useAtt = atts.getValue(a); 63 } else if (f==StandardNames.MATCH) { 64 matchAtt = atts.getValue(a); 65 } else if (f==StandardNames.COLLATION) { 66 collationName = atts.getValue(a).trim(); 67 } else { 68 checkUnknownAttribute(nc); 69 } 70 } 71 72 if (nameAtt==null) { 73 reportAbsence("name"); 74 return; 75 } 76 try { 77 setObjectNameCode(makeNameCode(nameAtt.trim())); 78 } catch (NamespaceException err) { 79 compileError(err.getMessage(), "XTSE0280"); 80 } catch (XPathException err) { 81 compileError(err); 82 } 83 84 if (matchAtt==null) { 85 reportAbsence("match"); 86 matchAtt = "*"; 87 } 88 match = makePattern(matchAtt); 89 90 if (useAtt!=null) { 91 use = makeExpression(useAtt); 92 } 93 } 94 95 public void validate() throws XPathException { 96 97 stackFrameMap = getConfiguration().makeSlotManager(); 98 checkTopLevel(null); 99 if (use!=null) { 100 if (hasChildNodes()) { 102 compileError("An xsl:key element with a @use attribute must be empty", "XTSE1205"); 103 } 104 try { 105 RoleLocator role = 106 new RoleLocator(RoleLocator.INSTRUCTION, "xsl:key/use", 0, null); 107 role.setSourceLocator(new ExpressionLocation(this)); 108 use = TypeChecker.staticTypeCheck( 109 use, 110 SequenceType.makeSequenceType(Type.ANY_ATOMIC_TYPE, StaticProperty.ALLOWS_ZERO_OR_MORE), 111 false, role, getStaticContext()); 112 } catch (XPathException err) { 113 compileError(err); 114 } 115 } else { 116 if (!hasChildNodes()) { 117 compileError("An xsl:key element must either have a @use attribute or have content", "XTSE1205"); 118 } 119 } 120 use = typeCheck("use", use); 121 match = typeCheck("match", match); 122 123 if (use != null) { 125 use = use.typeCheck(getStaticContext(), match.getNodeTest()); 126 } 127 128 } 129 130 public Expression compile(Executable exec) throws XPathException { 131 132 Collator collator = null; 133 if (collationName != null) { 134 Comparator comp = getPrincipalStylesheet().findCollation(collationName); 135 if (comp==null) { 136 compileError("The collation name " + Err.wrap(collationName) + " is not recognized", "XTSE1210"); 137 } 138 if (!(comp instanceof Collator )) { 139 compileError("The collation used for xsl:key must be a java.text.Collator", "XTSE1210"); 140 } 141 collator = (Collator )comp; 142 } 143 144 if (use==null) { 145 Expression body = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true); 146 try { 147 use = new Atomizer(body.simplify(getStaticContext()), 148 getStaticContext().getConfiguration()); 149 } catch (XPathException e) { 150 compileError(e); 151 } 152 153 try { 154 RoleLocator role = 155 new RoleLocator(RoleLocator.INSTRUCTION, "xsl:key/use", 0, null); 156 role.setSourceLocator(new ExpressionLocation(this)); 157 use = TypeChecker.staticTypeCheck( 158 use, 159 SequenceType.makeSequenceType(Type.ANY_ATOMIC_TYPE, StaticProperty.ALLOWS_ZERO_OR_MORE), 160 false, role, getStaticContext()); 161 use = use.typeCheck(getStaticContext(), match.getNodeTest()); 163 164 } catch (XPathException err) { 165 compileError(err); 166 } 167 } 168 169 allocateSlots(use); 170 171 172 KeyManager km = getPrincipalStylesheet().getKeyManager(); 173 KeyDefinition keydef = new KeyDefinition(match, use, collationName, collator); 174 keydef.setStackFrameMap(stackFrameMap); 175 keydef.setLocation(getSystemId(), getLineNumber()); 176 keydef.setExecutable(getExecutable()); 177 keydef.setBackwardsCompatible(backwardsCompatibleModeIsEnabled()); 178 try { 179 km.addKeyDefinition(getObjectFingerprint(), keydef); 180 } catch (TransformerConfigurationException err) { 181 compileError(err); 182 } 183 return null; 184 } 185 186 } 187 | Popular Tags |