1 package net.sf.saxon.style; 2 import net.sf.saxon.Configuration; 3 import net.sf.saxon.Err; 4 import net.sf.saxon.expr.Expression; 5 import net.sf.saxon.expr.ExpressionTool; 6 import net.sf.saxon.expr.ErrorExpression; 7 import net.sf.saxon.instruct.Attribute; 8 import net.sf.saxon.instruct.Executable; 9 import net.sf.saxon.instruct.FixedAttribute; 10 import net.sf.saxon.om.*; 11 import net.sf.saxon.trans.XPathException; 12 import net.sf.saxon.trans.DynamicError; 13 import net.sf.saxon.type.SchemaType; 14 import net.sf.saxon.type.SimpleType; 15 import net.sf.saxon.value.StringValue; 16 17 20 21 public final class XSLAttribute extends XSLStringConstructor { 22 23 private Expression attributeName; 24 private Expression separator; 25 private Expression namespace = null; 26 private int validationAction = Validation.PRESERVE; 27 private SimpleType schemaType; 28 29 public void prepareAttributes() throws XPathException { 30 31 AttributeCollection atts = getAttributeList(); 32 33 String nameAtt = null; 34 String namespaceAtt = null; 35 String selectAtt = null; 36 String separatorAtt = null; 37 String validationAtt = null; 38 String typeAtt = null; 39 40 for (int a=0; a<atts.getLength(); a++) { 41 int nc = atts.getNameCode(a); 42 String f = getNamePool().getClarkName(nc); 43 if (f==StandardNames.NAME) { 44 nameAtt = atts.getValue(a).trim(); 45 } else if (f==StandardNames.NAMESPACE) { 46 namespaceAtt = atts.getValue(a).trim(); 47 } else if (f==StandardNames.SELECT) { 48 selectAtt = atts.getValue(a); 49 } else if (f==StandardNames.SEPARATOR) { 50 separatorAtt = atts.getValue(a); 51 } else if (f==StandardNames.VALIDATION) { 52 validationAtt = atts.getValue(a).trim(); 53 } else if (f==StandardNames.TYPE) { 54 typeAtt = atts.getValue(a).trim(); 55 } else { 56 checkUnknownAttribute(nc); 57 } 58 } 59 60 if (nameAtt==null) { 61 reportAbsence("name"); 62 return; 63 } 64 attributeName = makeAttributeValueTemplate(nameAtt); 65 if (attributeName instanceof StringValue) { 66 if (!Name.isQName(((StringValue)attributeName).getStringValue())) { 67 invalidAttributeName("Attribute name " + Err.wrap(nameAtt) + " is not a valid QName"); 68 } 69 if (nameAtt.equals("xmlns")) { 70 if (namespace==null) { 71 invalidAttributeName("Invalid attribute name: xmlns"); 72 } 73 } 74 if (nameAtt.startsWith("xmlns:")) { 75 if (namespaceAtt == null) { 76 invalidAttributeName("Invalid attribute name: " + Err.wrap(nameAtt)); 77 } else { 78 nameAtt = nameAtt.substring(6); 80 attributeName = new StringValue(nameAtt); 81 } 82 } 83 } 84 85 86 if (namespaceAtt!=null) { 87 namespace = makeAttributeValueTemplate(namespaceAtt); 88 } 89 90 if (selectAtt!=null) { 91 select = makeExpression(selectAtt); 92 } 93 94 if (separatorAtt == null) { 95 if (selectAtt == null) { 96 separator = StringValue.EMPTY_STRING; 97 } else { 98 separator = StringValue.SINGLE_SPACE; 99 } 100 } else { 101 separator = makeAttributeValueTemplate(separatorAtt); 102 } 103 104 if (validationAtt!=null) { 105 validationAction = Validation.getCode(validationAtt); 106 if (validationAction != Validation.STRIP && !getConfiguration().isSchemaAware(Configuration.XSLT)) { 107 reportInvalidAttribute("To perform validation, a schema-aware XSLT processor is needed", "XTSE1660"); 108 validationAction = getContainingStylesheet().getDefaultValidation(); 109 } 110 if (validationAction == Validation.INVALID) { 111 reportInvalidAttribute("Invalid value of validation attribute", "XTSE0020"); 112 validationAction = getContainingStylesheet().getDefaultValidation(); 113 } 114 } else { 115 validationAction = getContainingStylesheet().getDefaultValidation(); 116 } 117 118 if (typeAtt!=null) { 119 if (!getConfiguration().isSchemaAware(Configuration.XSLT)) { 120 reportInvalidAttribute( 121 "The @type attribute is available only with a schema-aware XSLT processor", "XTSE1660"); 122 } else { 123 SchemaType type = getSchemaType(typeAtt); 124 if (type == null) { 125 reportInvalidAttribute("Unknown attribute type " + typeAtt, "XTSE1520"); 126 } else { 127 if (type.isSimpleType()) { 128 schemaType = (SimpleType)type; 129 } else { 130 reportInvalidAttribute("Type annotation for attributes must be a simple type", "XTSE1530"); 131 type = null; 132 } 133 } 134 } 135 } 136 137 if (typeAtt != null && validationAtt != null) { 138 reportInvalidAttribute("The validation and type attributes are mutually exclusive", "XTSE1505"); 139 validationAction = getContainingStylesheet().getDefaultValidation(); 140 schemaType = null; 141 } 142 } 143 144 private void invalidAttributeName(String message) throws XPathException { 145 if (forwardsCompatibleModeIsEnabled()) { 146 DynamicError err = new DynamicError(message); 147 err.setErrorCode("XTDE0850"); 148 err.setLocator(this); 149 attributeName = new ErrorExpression(err); 150 } else { 151 compileError(message, "XTDE0850"); 152 attributeName = new StringValue("saxon-error-attribute"); 154 } 155 } 156 157 public void validate() throws XPathException { 158 if (!(getParent() instanceof XSLAttributeSet)) { 159 checkWithinTemplate(); 160 } 161 if (schemaType != null) { 162 if (schemaType.isNamespaceSensitive()) { 163 compileError("Validation at attribute level must not specify a " + 164 "namespace-sensitive type (xs:QName or xs:NOTATION)", "XTSE1545"); 165 } 166 } 167 attributeName = typeCheck("name", attributeName); 168 namespace = typeCheck("namespace", namespace); 169 select = typeCheck("select", select); 170 separator = typeCheck("separator", separator); 171 super.validate(); 172 } 173 174 public Expression compile(Executable exec) throws XPathException { 175 NamespaceResolver nsContext = null; 176 177 int annotation = getTypeAnnotation(schemaType); 178 179 181 if (attributeName instanceof StringValue) { 182 String qName = ((StringValue)attributeName).getStringValue().trim(); 183 String [] parts; 184 try { 185 parts = Name.getQNameParts(qName); 186 } catch (QNameException e) { 187 return null; 189 } 190 191 192 if (namespace==null) { 193 String nsuri = ""; 194 if (!parts[0].equals("")) { 195 nsuri = getURIForPrefix(parts[0], false); 196 if (nsuri == null) { 197 undeclaredNamespaceError(parts[0], "XTSE0280"); 198 return null; 199 } 200 } 201 int nameCode = getTargetNamePool().allocate(parts[0], nsuri, parts[1]); 202 FixedAttribute inst = new FixedAttribute(nameCode, 203 validationAction, 204 schemaType, 205 annotation); 206 inst.setParentExpression(this); compileContent(exec, inst, separator); 208 ExpressionTool.makeParentReferences(inst); 210 return inst; 211 } else if (namespace instanceof StringValue) { 212 String nsuri = ((StringValue)namespace).getStringValue(); 213 if (nsuri.equals("")) { 214 parts[0] = ""; 215 } else if (parts[0].equals("")) { 216 AxisIterator iter = iterateAxis(Axis.NAMESPACE); 219 while (true) { 220 NodeInfo ns = (NodeInfo)iter.next(); 221 if (ns == null) { 222 break; 223 } 224 if (ns.getStringValue().equals(nsuri)) { 225 parts[0] = ns.getLocalPart(); 226 break; 227 } 228 } 229 if (parts[0].equals("")) { 231 String p = getTargetNamePool().suggestPrefixForURI( 232 ((StringValue)namespace).getStringValue()); 233 if (p != null) { 234 parts[0] = p; 235 } 236 } 237 if (parts[0].equals("")) { 240 parts[0] = "ns0"; 241 } 242 } 243 int nameCode = getTargetNamePool().allocate(parts[0], nsuri, parts[1]); 244 FixedAttribute inst = new FixedAttribute(nameCode, 245 validationAction, 246 schemaType, 247 annotation); 248 compileContent(exec, inst, separator); 249 ExpressionTool.makeParentReferences(inst); 251 return inst; 252 } 253 } else { 254 257 if (namespace==null) { 258 nsContext = makeNamespaceContext(); 259 } 260 } 261 262 Attribute inst = new Attribute( attributeName, 263 namespace, 264 nsContext, 265 validationAction, 266 schemaType, 267 annotation, 268 false); 269 compileContent(exec, inst, separator); 270 return inst; 271 } 272 273 } 274 275 | Popular Tags |