mmidy 2002/07/10 09:06:32 Modified: java/src/org/apache/xalan/processor XSLTAttributeDef.java XSLTElementProcessor.java XSLTSchema.java java/src/org/apache/xalan/res XSLTErrorResources.java XSLTErrorResources.properties java/src/org/apache/xalan/templates AVT.java Constants.java ElemAttribute.java ElemElement.java ElemNumber.java ElemPI.java java/src/org/apache/xml/utils QName.java StringToIntTable.java java/src/org/apache/xpath/res XPATHErrorResources.java XPATHErrorResources.properties Log: Bugzilla 5013: Validation of QName attribute values. The patch will also fix the missing validation described in bugs 792 and 793 Revision Changes Path 1.23 +565 -89 xml-xalan/java/src/org/apache/xalan/processor/XSLTAttributeDef.java Index: XSLTAttributeDef.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/XSLTAttributeDef.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- XSLTAttributeDef.java 8 Jul 2002 22:05:56 -0000 1.22 +++ XSLTAttributeDef.java 10 Jul 2002 16:06:31 -0000 1.23 @@ -58,13 +58,8 @@ import org.apache.xml.utils.StringToIntTable; -import java.lang.IllegalAccessException; -import java.lang.IndexOutOfBoundsException; -import java.lang.InstantiationException; -import java.lang.NoSuchMethodException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.StringBuffer; import java.util.StringTokenizer; import java.util.Vector; @@ -77,10 +72,12 @@ import org.apache.xml.utils.QName; import org.apache.xml.utils.SystemIDResolver; import org.apache.xml.utils.StringVector; +import org.apache.xml.utils.XMLChar; import org.apache.xpath.XPath; import javax.xml.transform.TransformerException; + /** * This class defines an attribute for an element in a XSLT stylesheet, * is meant to reflect the structure defined in http://www.w3.org/TR/xslt#dtd, and the @@ -88,24 +85,32 @@ */ public class XSLTAttributeDef { - + // How to handle invalid values for this attribute + static final int FATAL = 0; + static final int ERROR = 1; + static final int WARNING = 2; + + /** * Construct an instance of XSLTAttributeDef. * * @param namespace The Namespace URI, or an empty string. * @param name The local name (without prefix), or empty string if not namespace processing. * @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, T_CHAR, - * T_PRIORITY, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST, - * T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST. + * T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST, + * T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, T_ENUM_OR_PQNAME, T_NCNAME. * @param required true if this is attribute is required by the XSLT specification. + * @param supportsAVT true if this attribute supports AVT's. + * @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING. */ - XSLTAttributeDef(String namespace, String name, int type, boolean required) + XSLTAttributeDef(String namespace, String name, int type, boolean required, boolean supportsAVT, int errorType) { - this.m_namespace = namespace; this.m_name = name; this.m_type = type; this.m_required = required; + this.m_supportsAVT = supportsAVT; + this.m_errorType = errorType; } /** @@ -114,19 +119,24 @@ * @param namespace The Namespace URI, or an empty string. * @param name The local name (without prefix), or empty string if not namespace processing. * @param type One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, - * T_CHAR, T_PRIORITY, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, - * T_SIMPLEPATTERNLIST, T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST. + * T_CHAR, T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, + * T_SIMPLEPATTERNLIST, T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, + * T_ENUM_OR_PQNAME, T_NCNAME. + * @param supportsAVT true if this attribute supports AVT's. + * @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING. * @param defaultVal The default value for this attribute. */ - XSLTAttributeDef(String namespace, String name, int type, String defaultVal) + XSLTAttributeDef(String namespace, String name, int type, boolean supportsAVT, int errorType, String defaultVal) { this.m_namespace = namespace; this.m_name = name; this.m_type = type; this.m_required = false; + this.m_supportsAVT = supportsAVT; + this.m_errorType = errorType; this.m_default = defaultVal; - } + } /** * Construct an instance of XSLTAttributeDef that uses two @@ -135,19 +145,24 @@ * @param namespace The Namespace URI, or an empty string. * @param name The local name (without prefix), or empty string if not namespace processing. * @param required true if this attribute is required by the XSLT specification. + * @param supportsAVT true if this attribute supports AVT's. + * @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME + * @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING. * @param k1 The XSLT name of the enumerated value. * @param v1 An integer representation of k1. * @param k2 The XSLT name of the enumerated value. * @param v2 An integer representation of k2. - */ - XSLTAttributeDef(String namespace, String name, boolean required, - String k1, int v1, String k2, int v2) + */ + XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT, + boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2) { this.m_namespace = namespace; this.m_name = name; - this.m_type = this.T_ENUM; + this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM; this.m_required = required; + this.m_supportsAVT = supportsAVT; + this.m_errorType = errorType; m_enums = new StringToIntTable(2); m_enums.put(k1, v1); @@ -161,6 +176,9 @@ * @param namespace The Namespace URI, or an empty string. * @param name The local name (without prefix), or empty string if not namespace processing. * @param required true if this attribute is required by the XSLT specification. + * @param supportsAVT true if this attribute supports AVT's. + * @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME + * @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING. * * @param k1 The XSLT name of the enumerated value. * @param v1 An integer representation of k1. * @param k2 The XSLT name of the enumerated value. @@ -168,14 +186,16 @@ * @param k3 The XSLT name of the enumerated value. * @param v3 An integer representation of k3. */ - XSLTAttributeDef(String namespace, String name, boolean required, - String k1, int v1, String k2, int v2, String k3, int v3) + XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT, + boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2, String k3, int v3) { this.m_namespace = namespace; this.m_name = name; - this.m_type = this.T_ENUM; + this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM; this.m_required = required; + this.m_supportsAVT = supportsAVT; + this.m_errorType = errorType; m_enums = new StringToIntTable(3); m_enums.put(k1, v1); @@ -190,7 +210,9 @@ * @param namespace The Namespace URI, or an empty string. * @param name The local name (without prefix), or empty string if not namespace processing. * @param required true if this attribute is required by the XSLT specification. - * @param k1 The XSLT name of the enumerated value. + * @param supportsAVT true if this attribute supports AVT's. + * @param prefixedQNameValAllowed If true, the type is T_ENUM_OR_PQNAME + * @param errorType the type of error to issue if validation fails. One of FATAL, ERROR, WARNING. * @param k1 The XSLT name of the enumerated value. * @param v1 An integer representation of k1. * @param k2 The XSLT name of the enumerated value. * @param v2 An integer representation of k2. @@ -199,15 +221,17 @@ * @param k4 The XSLT name of the enumerated value. * @param v4 An integer representation of k4. */ - XSLTAttributeDef(String namespace, String name, boolean required, - String k1, int v1, String k2, int v2, String k3, int v3, - String k4, int v4) + XSLTAttributeDef(String namespace, String name, boolean required, boolean supportsAVT, + boolean prefixedQNameValAllowed, int errorType, String k1, int v1, String k2, int v2, + String k3, int v3, String k4, int v4) { this.m_namespace = namespace; this.m_name = name; - this.m_type = this.T_ENUM; + this.m_type = prefixedQNameValAllowed ? this.T_ENUM_OR_PQNAME : this.T_ENUM; this.m_required = required; + this.m_supportsAVT = supportsAVT; + this.m_errorType = errorType; m_enums = new StringToIntTable(4); m_enums.put(k1, v1); @@ -236,8 +260,8 @@ // of a single character.--> T_CHAR = 6, - // <!-- Used for the type of an attribute value that is a priority. --> - T_PRIORITY = 7, + // <!-- Used for the type of an attribute value that is a number. --> + T_NUMBER = 7, // Used for boolean values T_YESNO = 8, @@ -262,11 +286,21 @@ T_STRINGLIST = 14, // Used for a list of white-space delimited strings. - T_PREFIX_URLLIST = 15; + T_PREFIX_URLLIST = 15, + + // Used for enumerated values, one of which could be a qname-but-not-ncname + T_ENUM_OR_PQNAME = 16, + + // Used for the type of an attribute value that is a NCName + T_NCNAME = 17, + + // Used for QName attributes that are always AVT. Prefix isn't resolved. + T_AVT_QNAME = 18; + /** Representation for an attribute in a foreign namespace. */ static XSLTAttributeDef m_foreignAttr = new XSLTAttributeDef("*", "*", - XSLTAttributeDef.T_CDATA, false); + XSLTAttributeDef.T_CDATA,false, false, WARNING); /** Method name that objects may implement if they wish to have forein attributes set. */ static String S_FOREIGNATTR_SETTER = "setForeignAttr"; @@ -310,8 +344,8 @@ * Get the type of this attribute value. * * @return One of T_CDATA, T_URL, T_AVT, T_PATTERN, T_EXPR, T_CHAR, - * T_PRIORITY, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST, - * T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST. + * T_NUMBER, T_YESNO, T_QNAME, T_QNAMES, T_ENUM, T_SIMPLEPATTERNLIST, + * T_NMTOKEN, T_STRINGLIST, T_PREFIX_URLLIST, T_ENUM_OR_PQNAME. */ int getType() { @@ -339,6 +373,19 @@ return m_enums.get(key); } + /** + * If this element is of type T_ENUM, this will return + * an array of strings - the values in the enumeration + * + * @return An array of the enumerated values permitted for this attribute. + * + * @throws Throws NullPointerException if m_enums is null. + */ + private String[] getEnumNames() + { + return m_enums.keys(); + } + /** * The default value for this attribute. */ @@ -380,6 +427,32 @@ } /** + * If true, this is attribute supports AVT's. + */ + private boolean m_supportsAVT; + + /** + * Get whether or not this attribute supports AVT's. + * + * @return true if this attribute supports AVT's. + */ + boolean getSupportsAVT() + { + return m_supportsAVT; + } + + int m_errorType = this.WARNING; + + /** + * Get the type of error message to use if the attribute value is invalid. + * + * @return one of XSLAttributeDef.FATAL, XSLAttributeDef.ERROR, XSLAttributeDef.WARNING + */ + int getErrorType() + { + return m_errorType; + } + /** * String that should represent the setter method which which * may be used on objects to set a value that represents this attribute */ @@ -493,11 +566,26 @@ * @param value non-null string reference. * * @return The value argument. + * + * @throws org.xml.sax.SAXException. */ Object processCDATA(StylesheetHandler handler, String uri, String name, - String rawName, String value) + String rawName, String value, ElemTemplateElement owner) + throws org.xml.sax.SAXException { - return value; + if (getSupportsAVT()) { + try + { + AVT avt = new AVT(handler, uri, name, rawName, value, owner); + return avt; + } + catch (TransformerException te) + { + throw new org.xml.sax.SAXException(te); + } + } else { + return value; + } } /** @@ -515,22 +603,38 @@ * @throws org.xml.sax.SAXException if the string is not a length of 1. */ Object processCHAR( - StylesheetHandler handler, String uri, String name, String rawName, String value) + StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner) throws org.xml.sax.SAXException { + if (getSupportsAVT()) { + try + { + AVT avt = new AVT(handler, uri, name, rawName, value, owner); + + // If an AVT wasn't used, validate the value + if ((avt.isSimple()) && (value.length() != 1)) { + handleError(handler, XSLTErrorResources.INVALID_TCHAR, new Object[] {name, value},null); + return null; + } + return avt; + } + catch (TransformerException te) + { + throw new org.xml.sax.SAXException(te); + } + } else { + if (value.length() != 1) + { + handleError(handler, XSLTErrorResources.INVALID_TCHAR, new Object[] {name, value},null); + return null; + } - if (value.length() != 1) - { - handler.error( - XSLMessages.createMessage(XSLTErrorResources.ER_ATTR_T_CHAR_ONE_CHAR, null), null); //"An XSLT attribute of type T_CHAR must be only 1 character!", null); - } - - return new Character(value.charAt(0)); + return new Character(value.charAt(0)); + } } /** - * Process an attribute string of type T_ENUM into - * a int value. + * Process an attribute string of type T_ENUM into a int value. * * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. * @param uri The Namespace URI, or an empty string. @@ -538,16 +642,126 @@ * @param rawName The qualified name (with prefix). * @param value non-null string that represents an enumerated value that is * valid for this element. + * @param owner * - * @return An Integer representation of the enumerated value. + * @return An Integer representation of the enumerated value if this attribute does not support + * AVT. Otherwise, and AVT is returned. */ Object processENUM(StylesheetHandler handler, String uri, String name, - String rawName, String value) + String rawName, String value, ElemTemplateElement owner) + throws org.xml.sax.SAXException { - int enum = this.getEnum(value); + AVT avt = null; + if (getSupportsAVT()) { + try + { + avt = new AVT(handler, uri, name, rawName, value, owner); + + // If this attribute used an avt, then we can't validate at this time. + if (!avt.isSimple()) return avt; + } + catch (TransformerException te) + { + throw new org.xml.sax.SAXException(te); + } + } + + int retVal = this.getEnum(value); + + if (retVal == StringToIntTable.INVALID_KEY) + { + StringBuffer enumNamesList = getListOfEnums(); + handleError(handler, XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },null); + return null; + } + + if (getSupportsAVT()) return avt; + else return new Integer(retVal); + + } + + /** + * Process an attribute string of that is either an enumerated value or a qname-but-not-ncname. + * Returns an AVT, if this attribute support AVT; otherwise returns int or qname. + * + * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. + * @param uri The Namespace URI, or an empty string. + * @param name The local name (without prefix), or empty string if not namespace processing. + * @param rawName The qualified name (with prefix). + * @param value non-null string that represents an enumerated value that is + * valid for this element. + * @param owner + * + * @return AVT if attribute supports AVT. An Integer representation of the enumerated value if + * attribute does not support AVT and an enumerated value was used. Otherwise a qname + * is returned. + */ + Object processENUM_OR_PQNAME(StylesheetHandler handler, String uri, String name, + String rawName, String value, ElemTemplateElement owner) + throws org.xml.sax.SAXException + { + + Object objToReturn = null; + + if (getSupportsAVT()) { + try + { + AVT avt = new AVT(handler, uri, name, rawName, value, owner); + if (!avt.isSimple()) return avt; + else objToReturn = avt; + } + catch (TransformerException te) + { + throw new org.xml.sax.SAXException(te); + } + } + + // An avt wasn't used. + int enum = this.getEnum(value); + + if (enum != StringToIntTable.INVALID_KEY) + { + if (objToReturn == null) objToReturn = new Integer(enum); + } + + // enum not used. Validate qname-but-not-ncname. + else + { + try + { + QName qname = new QName(value, handler, true); + if (objToReturn == null) objToReturn = qname; + + if (qname.getPrefix() == null) { + StringBuffer enumNamesList = getListOfEnums(); + + enumNamesList.append(" <qname-but-not-ncname>"); + handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },null); + return null; + + } + } + catch (IllegalArgumentException ie) + { + StringBuffer enumNamesList = getListOfEnums(); + enumNamesList.append(" <qname-but-not-ncname>"); + + handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },ie); + return null; - return new Integer(enum); + } + catch (RuntimeException re) + { + StringBuffer enumNamesList = getListOfEnums(); + enumNamesList.append(" <qname-but-not-ncname>"); + + handleError(handler,XSLTErrorResources.INVALID_ENUM,new Object[]{name, value, enumNamesList.toString() },re); + return null; + } + } + + return objToReturn; } /** @@ -595,11 +809,37 @@ * @param rawName The qualified name (with prefix). * @param value A NMTOKEN string. * - * @return the value argument. + * @return the value argument or an AVT if this attribute supports AVTs. + * + * @throws org.xml.sax.SAXException if the value is not a valid nmtoken */ Object processNMTOKEN(StylesheetHandler handler, String uri, String name, - String rawName, String value) + String rawName, String value, ElemTemplateElement owner) + throws org.xml.sax.SAXException { + + if (getSupportsAVT()) { + try + { + AVT avt = new AVT(handler, uri, name, rawName, value, owner); + + // If an AVT wasn't used, validate the value + if ((avt.isSimple()) && (!XMLChar.isValidNmtoken(value))) { + handleError(handler,XSLTErrorResources.INVALID_NMTOKEN, new Object[] {name,value},null); + return null; + } + return avt; + } + catch (TransformerException te) + { + throw new org.xml.sax.SAXException(te); + } + } else { + if (!XMLChar.isValidNmtoken(value)) { + handleError(handler,XSLTErrorResources.INVALID_NMTOKEN, new Object[] {name,value},null); + return null; + } + } return value; } @@ -638,7 +878,7 @@ } /** - * Process an attribute string of type T_PRIORITY into + * Process an attribute string of type T_NUMBER into * a double value. * * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. @@ -646,6 +886,7 @@ * @param name The local name (without prefix), or empty string if not namespace processing. * @param rawName The qualified name (with prefix). * @param value A string that can be parsed into a double value. + * @param number * * @return A Double object. * @@ -653,45 +894,203 @@ * {@link javax.xml.transform.TransformerException} * if the string does not contain a parsable number. */ - Object processPRIORITY( - StylesheetHandler handler, String uri, String name, String rawName, String value) + Object processNUMBER( + StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner) throws org.xml.sax.SAXException { - try - { - return Double.valueOf(value); - } - catch (NumberFormatException nfe) - { - handler.error(XSLTErrorResources.ER_PRIORITY_NOT_PARSABLE, null, nfe);//"Priority value does not contain a parsable number.", - //nfe); - return new Double(0.0); - } + if (getSupportsAVT()) + { + Double val; + AVT avt = null; + try + { + avt = new AVT(handler, uri, name, rawName, value, owner); + + // If this attribute used an avt, then we can't validate at this time. + if (avt.isSimple()) + { + val = Double.valueOf(value); + } + } + catch (TransformerException te) + { + throw new org.xml.sax.SAXException(te); + } + catch (NumberFormatException nfe) + { + handleError(handler,XSLTErrorResources.INVALID_NUMBER, new Object[] {name, value}, nfe); + return null; + } + return avt; + + } + else + { + try + { + return Double.valueOf(value); + } + catch (NumberFormatException nfe) + { + handleError(handler,XSLTErrorResources.INVALID_NUMBER, new Object[] {name, value}, nfe); + return null; + } + } } /** - * Process an attribute string of type T_QNAME into - * a QName value. + * Process an attribute string of type T_QNAME into a QName value. * * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. * @param uri The Namespace URI, or an empty string. * @param name The local name (without prefix), or empty string if not namespace processing. * @param rawName The qualified name (with prefix). * @param value A string that represents a potentially prefix qualified name. + * @param owner * - * @return A QName object. + * @return A QName object if this attribute does not support AVT's. Otherwise, an AVT + * is returned. * * @throws org.xml.sax.SAXException if the string contains a prefix that can not be * resolved, or the string contains syntax that is invalid for a qualified name. */ Object processQNAME( - StylesheetHandler handler, String uri, String name, String rawName, String value) + StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner) throws org.xml.sax.SAXException { - return new QName(value, handler); - } + + try + { + QName qname = new QName(value, handler, true); + return qname; + } + catch (IllegalArgumentException ie) + { + // thrown by QName constructor + handleError(handler,XSLTErrorResources.INVALID_QNAME, new Object[] {name, value},ie); + return null; + } + catch (RuntimeException re) { + // thrown by QName constructor + handleError(handler,XSLTErrorResources.INVALID_QNAME, new Object[] {name, value},re); + return null; + } + } + + + /** + * Process an attribute string of type T_QNAME into a QName value. + * + * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. + * @param uri The Namespace URI, or an empty string. + * @param name The local name (without prefix), or empty string if not namespace processing. + * @param rawName The qualified name (with prefix). + * @param value A string that represents a potentially prefix qualified name. + * @param owner + * + * @return An AVT is returned. + * + * @throws org.xml.sax.SAXException if the string contains a prefix that can not be + * resolved, or the string contains syntax that is invalid for a qualified name. + */ + Object processAVT_QNAME( + StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner) + throws org.xml.sax.SAXException + { + + AVT avt = null; + try + { + avt = new AVT(handler, uri, name, rawName, value, owner); + + // If an AVT wasn't used, validate the value + if (avt.isSimple()) + { + int indexOfNSSep = value.indexOf(':'); + + if (indexOfNSSep >= 0) + { + String prefix = value.substring(0, indexOfNSSep); + if (!XMLChar.isValidNCName(prefix)) + { + handleError(handler,XSLTErrorResources.INVALID_QNAME,new Object[]{name,value },null); + return null; + } + } + + String localName = (indexOfNSSep < 0) + ? value : value.substring(indexOfNSSep + 1); + + if ((localName == null) || (localName.length() == 0) || + (!XMLChar.isValidNCName(localName))) + { + handleError(handler,XSLTErrorResources.INVALID_QNAME,new Object[]{name,value },null ); + return null; + } + } + } + catch (TransformerException te) + { + // thrown by AVT constructor + throw new org.xml.sax.SAXException(te); + } + + return avt; + } + + /** + * Process an attribute string of type NCName into a String + * + * @param handler non-null reference to current StylesheetHandler that is constructing the Templates. + * @param uri The Namespace URI, or an empty string. + * @param name The local name (without prefix), or empty string if not namespace processing. + * @param rawName The qualified name (with prefix). + * @param value A string that represents a potentially prefix qualified name. + * @param owner + * + * @return A String object if this attribute does not support AVT's. Otherwise, an AVT + * is returned. + * + * @throws org.xml.sax.SAXException if the string contains a prefix that can not be + * resolved, or the string contains syntax that is invalid for a NCName. + */ + Object processNCNAME( + StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner) + throws org.xml.sax.SAXException + { + + if (getSupportsAVT()) + { + AVT avt = null; + try + { + avt = new AVT(handler, uri, name, rawName, value, owner); + + // If an AVT wasn't used, validate the value + if ((avt.isSimple()) && (!XMLChar.isValidNCName(value))) + { + handleError(handler,XSLTErrorResources.INVALID_NCNAME,new Object[] {name,value},null); + return null; + } + return avt; + } + catch (TransformerException te) + { + // thrown by AVT constructor + throw new org.xml.sax.SAXException(te); + } + + } else { + if (!XMLChar.isValidNCName(value)) + { + handleError(handler,XSLTErrorResources.INVALID_NCNAME,new Object[] {name,value},null); + return null; + } + return value; + } + } /** * Process an attribute string of type T_QNAMES into @@ -843,19 +1242,40 @@ * @param rawName The qualified name (with prefix). * @param value non-null string that conforms to the URL syntax. * - * @return The non-absolutized URL argument, in other words, the value argument. + * @return The non-absolutized URL argument, in other words, the value argument. If this + * attribute supports AVT, an AVT is returned. * * @throws org.xml.sax.SAXException if the URL does not conform to the URL syntax. */ - String processURL( - StylesheetHandler handler, String uri, String name, String rawName, String value) + Object processURL( + StylesheetHandler handler, String uri, String name, String rawName, String value, ElemTemplateElement owner) throws org.xml.sax.SAXException { + if (getSupportsAVT()) { + try + { + AVT avt = new AVT(handler, uri, name, rawName, value, owner); + + // If an AVT wasn't used, validate the value + // if (avt.getSimpleString() != null) { + // TODO: syntax check URL value. + // return SystemIDResolver.getAbsoluteURI(value, + // handler.getBaseIdentifier()); + //} + return avt; + } + catch (TransformerException te) + { + throw new org.xml.sax.SAXException(te); + } + } else { // TODO: syntax check URL value. // return SystemIDResolver.getAbsoluteURI(value, // handler.getBaseIdentifier()); - return value; + + return value; + } } /** @@ -879,10 +1299,12 @@ // Is this already checked somewhere else? -sb if (!(value.equals("yes") || value.equals("no"))) - handler.error(XSLTErrorResources.ER_VALUE_SHOULD_EQUAL, new Object[]{name}, null);//"Value for " + name + " should equal 'yes' or 'no'", - //null); - - return new Boolean(value.equals("yes") ? true : false); + { + handleError(handler, XSLTErrorResources.INVALID_BOOLEAN, new Object[] {name,value}, null); + return null; + } + + return new Boolean(value.equals("yes") ? true : false); } /** @@ -913,28 +1335,28 @@ processedValue = processAVT(handler, uri, name, rawName, value, owner); break; case T_CDATA : - processedValue = processCDATA(handler, uri, name, rawName, value); + processedValue = processCDATA(handler, uri, name, rawName, value, owner); break; case T_CHAR : - processedValue = processCHAR(handler, uri, name, rawName, value); + processedValue = processCHAR(handler, uri, name, rawName, value, owner); break; case T_ENUM : - processedValue = processENUM(handler, uri, name, rawName, value); + processedValue = processENUM(handler, uri, name, rawName, value, owner); break; case T_EXPR : processedValue = processEXPR(handler, uri, name, rawName, value, owner); break; case T_NMTOKEN : - processedValue = processNMTOKEN(handler, uri, name, rawName, value); + processedValue = processNMTOKEN(handler, uri, name, rawName, value, owner); break; case T_PATTERN : processedValue = processPATTERN(handler, uri, name, rawName, value, owner); break; - case T_PRIORITY : - processedValue = processPRIORITY(handler, uri, name, rawName, value); + case T_NUMBER : + processedValue = processNUMBER(handler, uri, name, rawName, value, owner); break; case T_QNAME : - processedValue = processQNAME(handler, uri, name, rawName, value); + processedValue = processQNAME(handler, uri, name, rawName, value, owner); break; case T_QNAMES : processedValue = processQNAMES(handler, uri, name, rawName, value); @@ -944,7 +1366,7 @@ value, owner); break; case T_URL : - processedValue = processURL(handler, uri, name, rawName, value); + processedValue = processURL(handler, uri, name, rawName, value, owner); break; case T_YESNO : processedValue = processYESNO(handler, uri, name, rawName, value); @@ -956,6 +1378,15 @@ processedValue = processPREFIX_URLLIST(handler, uri, name, rawName, value); break; + case T_ENUM_OR_PQNAME : + processedValue = processENUM_OR_PQNAME(handler, uri, name, rawName, value, owner); + break; + case T_NCNAME : + processedValue = processNCNAME(handler, uri, name, rawName, value, owner); + break; + case T_AVT_QNAME : + processedValue = processAVT_QNAME(handler, uri, name, rawName, value, owner); + break; default : } @@ -1033,6 +1464,26 @@ return cl; } + + /** + * StringBuffer containing comma delimited list of valid values for ENUM type. + * Used to build error message. + */ + private StringBuffer getListOfEnums() + { + StringBuffer enumNamesList = new StringBuffer(); + String [] enumValues = this.getEnumNames(); + + for (int i = 0; i < enumValues.length; i++) + { + if (i > 0) + { + enumNamesList.append(' '); + } + enumNamesList.append(enumValues[i]); + } + return enumNamesList; + } /** * Set a value on an attribute. @@ -1046,13 +1497,13 @@ * * @throws org.xml.sax.SAXException */ - void setAttrValue( + boolean setAttrValue( StylesheetHandler handler, String attrUri, String attrLocalName, String attrRawName, String attrValue, ElemTemplateElement elem) throws org.xml.sax.SAXException { if(attrRawName.equals("xmlns") || attrRawName.startsWith("xmlns:")) - return; + return true; String setterString = getSetterMethodName(); @@ -1083,6 +1534,9 @@ { Object value = processValue(handler, attrUri, attrLocalName, attrRawName, attrValue, elem); + // If a warning was issued because the value for this attribute was + // invalid, then the value will be null. Just return + if (null == value) return false; // First try to match with the primative value. Class[] argTypes = new Class[]{ getPrimativeClass(value) }; @@ -1107,17 +1561,39 @@ } catch (NoSuchMethodException nsme) { - if (!setterString.equals(S_FOREIGNATTR_SETTER)) + if (!setterString.equals(S_FOREIGNATTR_SETTER)) + { handler.error(XSLTErrorResources.ER_FAILED_CALLING_METHOD, new Object[]{setterString}, nsme);//"Failed calling " + setterString + " method!", nsme); + return false; + } } catch (IllegalAccessException iae) { handler.error(XSLTErrorResources.ER_FAILED_CALLING_METHOD, new Object[]{setterString}, iae);//"Failed calling " + setterString + " method!", iae); + return false; } catch (InvocationTargetException nsme) { - handler.error(XSLTErrorResources.ER_FAILED_CALLING_METHOD, new Object[]{setterString}, nsme);//"Failed calling " + setterString + " method!", nsme); + handleError(handler, XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_VALUE, + new Object[]{ Constants.ATTRNAME_NAME, getName()}, nsme); + return false; } + } + + return true; + } + + private void handleError(StylesheetHandler handler, int msg, Object [] args, Exception exc) throws org.xml.sax.SAXException + { + switch (getErrorType()) + { + case (FATAL): + case (ERROR): + handler.error(msg, args, exc); + break; + case (WARNING): + handler.warn(msg, args); + default: break; } } } 1.14 +13 -3 xml-xalan/java/src/org/apache/xalan/processor/XSLTElementProcessor.java Index: XSLTElementProcessor.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/XSLTElementProcessor.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- XSLTElementProcessor.java 22 Mar 2002 01:04:40 -0000 1.13 +++ XSLTElementProcessor.java 10 Jul 2002 16:06:31 -0000 1.14 @@ -338,6 +338,9 @@ // Keep track of which XSLTAttributeDefs have been processed, so // I can see which default values need to be set. Vector processedDefs = new Vector(); + + // Keep track of XSLTAttributeDefs that were invalid + Vector errorDefs = new Vector(); int nAttrs = attributes.getLength(); for (int i = 0; i < nAttrs; i++) @@ -373,10 +376,17 @@ } else { - processedDefs.addElement(attrDef); - attrDef.setAttrValue(handler, attrUri, attrLocalName, + // Can we switch the order here: + + boolean success = attrDef.setAttrValue(handler, attrUri, attrLocalName, attributes.getQName(i), attributes.getValue(i), target); + + // Now we only add the element if it passed a validation check + if (success) + processedDefs.addElement(attrDef); + else + errorDefs.addElement(attrDef); } } @@ -398,7 +408,7 @@ if (attrDef.getRequired()) { - if (!processedDefs.contains(attrDef)) + if ((!processedDefs.contains(attrDef)) && (!errorDefs.contains(attrDef))) handler.error( XSLMessages.createMessage( XSLTErrorResources.ER_REQUIRES_ATTRIB, new Object[]{ rawName, 1.27 +178 -89 xml-xalan/java/src/org/apache/xalan/processor/XSLTSchema.java Index: XSLTSchema.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/XSLTSchema.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- XSLTSchema.java 10 Jun 2002 19:24:41 -0000 1.26 +++ XSLTSchema.java 10 Jul 2002 16:06:31 -0000 1.27 @@ -83,170 +83,254 @@ */ void build() { - + // xsl:import, xsl:include XSLTAttributeDef hrefAttr = new XSLTAttributeDef(null, "href", - XSLTAttributeDef.T_URL, true); + XSLTAttributeDef.T_URL, true, false,XSLTAttributeDef.WARNING); + + // xsl:preserve-space, xsl:strip-space XSLTAttributeDef elementsAttr = new XSLTAttributeDef(null, "elements", XSLTAttributeDef.T_SIMPLEPATTERNLIST, - true); + true, false, XSLTAttributeDef.WARNING); + // XSLTAttributeDef anyNamespacedAttr = new XSLTAttributeDef("*", "*", // XSLTAttributeDef.T_CDATA, false); + + // xsl:output XSLTAttributeDef methodAttr = new XSLTAttributeDef(null, "method", - XSLTAttributeDef.T_QNAME, false); + XSLTAttributeDef.T_QNAME, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef versionAttr = new XSLTAttributeDef(null, "version", - XSLTAttributeDef.T_NMTOKEN, false); + XSLTAttributeDef.T_NMTOKEN, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef encodingAttr = new XSLTAttributeDef(null, "encoding", - XSLTAttributeDef.T_CDATA, false); + XSLTAttributeDef.T_CDATA, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef omitXmlDeclarationAttr = new XSLTAttributeDef(null, "omit-xml-declaration", XSLTAttributeDef.T_YESNO, - false); + false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef standaloneAttr = new XSLTAttributeDef(null, "standalone", - XSLTAttributeDef.T_YESNO, false); + XSLTAttributeDef.T_YESNO, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef doctypePublicAttr = new XSLTAttributeDef(null, "doctype-public", - XSLTAttributeDef.T_CDATA, false); + XSLTAttributeDef.T_CDATA, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef doctypeSystemAttr = new XSLTAttributeDef(null, "doctype-system", - XSLTAttributeDef.T_CDATA, false); + XSLTAttributeDef.T_CDATA, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef cdataSectionElementsAttr = new XSLTAttributeDef(null, "cdata-section-elements", XSLTAttributeDef.T_QNAMES, - false); + false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef indentAttr = new XSLTAttributeDef(null, "indent", - XSLTAttributeDef.T_YESNO, false); + XSLTAttributeDef.T_YESNO, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef mediaTypeAttr = new XSLTAttributeDef(null, "media-type", - XSLTAttributeDef.T_CDATA, false); + XSLTAttributeDef.T_CDATA, false, false,XSLTAttributeDef.WARNING); + + + // Required. + // It is an error if the name attribute is invalid on any of these elements + // xsl:key, xsl:attribute-set, xsl:call-template, xsl:with-param, xsl:variable, xsl:param XSLTAttributeDef nameAttrRequired = new XSLTAttributeDef(null, "name", - XSLTAttributeDef.T_QNAME, true); + XSLTAttributeDef.T_QNAME, true, false,XSLTAttributeDef.ERROR); + // Required. + // Support AVT + // xsl:element, xsl:attribute + XSLTAttributeDef nameAVTRequired = new XSLTAttributeDef(null, "name", + XSLTAttributeDef.T_AVT_QNAME, true, true,XSLTAttributeDef.WARNING); + + + // Required. + // Support AVT + // xsl:processing-instruction + XSLTAttributeDef nameAVT_NCNAMERequired = new XSLTAttributeDef(null, "name", + XSLTAttributeDef.T_NCNAME, true, true,XSLTAttributeDef.WARNING); + + // Optional. + // Static error if invalid + // xsl:template + XSLTAttributeDef nameAttrOpt_ERROR = new XSLTAttributeDef(null, "name", + XSLTAttributeDef.T_QNAME, false, false,XSLTAttributeDef.ERROR); + // Optional. + // xsl:decimal-format XSLTAttributeDef nameAttrOpt = new XSLTAttributeDef(null, "name", - XSLTAttributeDef.T_QNAME, false); + XSLTAttributeDef.T_QNAME, false, false,XSLTAttributeDef.WARNING); + + // xsl:key XSLTAttributeDef useAttr = new XSLTAttributeDef(null, "use", - XSLTAttributeDef.T_EXPR, true); - XSLTAttributeDef nameAVTRequired = new XSLTAttributeDef(null, "name", - XSLTAttributeDef.T_AVT, true); + XSLTAttributeDef.T_EXPR, true, false,XSLTAttributeDef.WARNING); + + // xsl:element, xsl:attribute XSLTAttributeDef namespaceAVTOpt = new XSLTAttributeDef(null, - "namespace", XSLTAttributeDef.T_AVT, - false); + "namespace",XSLTAttributeDef.T_URL, + false, true,XSLTAttributeDef.WARNING); + // xsl:decimal-format XSLTAttributeDef decimalSeparatorAttr = new XSLTAttributeDef(null, "decimal-separator", - XSLTAttributeDef.T_CHAR, "."); - XSLTAttributeDef groupingSeparatorAttr = new XSLTAttributeDef(null, - "grouping-separator", - XSLTAttributeDef.T_CHAR, ","); + XSLTAttributeDef.T_CHAR, false,XSLTAttributeDef.ERROR, "."); XSLTAttributeDef infinityAttr = new XSLTAttributeDef(null, "infinity", - XSLTAttributeDef.T_CDATA, "Infinity"); + XSLTAttributeDef.T_CDATA, false,XSLTAttributeDef.WARNING,"Infinity"); XSLTAttributeDef minusSignAttr = new XSLTAttributeDef(null, "minus-sign", - XSLTAttributeDef.T_CHAR, "-"); + XSLTAttributeDef.T_CHAR, false,XSLTAttributeDef.ERROR,"-"); XSLTAttributeDef NaNAttr = new XSLTAttributeDef(null, "NaN", - XSLTAttributeDef.T_CDATA, "NaN"); + XSLTAttributeDef.T_CDATA, false,XSLTAttributeDef.WARNING, "NaN"); XSLTAttributeDef percentAttr = new XSLTAttributeDef(null, "percent", - XSLTAttributeDef.T_CHAR, "%"); + XSLTAttributeDef.T_CHAR, false,XSLTAttributeDef.ERROR, "%"); XSLTAttributeDef perMilleAttr = new XSLTAttributeDef(null, "per-mille", XSLTAttributeDef.T_CHAR, - false /* ,"‰" */); + false, false,XSLTAttributeDef.ERROR /* ,"‰" */); XSLTAttributeDef zeroDigitAttr = new XSLTAttributeDef(null, "zero-digit", - XSLTAttributeDef.T_CHAR, "0"); + XSLTAttributeDef.T_CHAR, false,XSLTAttributeDef.ERROR, "0"); XSLTAttributeDef digitAttr = new XSLTAttributeDef(null, "digit", - XSLTAttributeDef.T_CHAR, "#"); + XSLTAttributeDef.T_CHAR, false,XSLTAttributeDef.ERROR, "#"); XSLTAttributeDef patternSeparatorAttr = new XSLTAttributeDef(null, "pattern-separator", - XSLTAttributeDef.T_CHAR, ";"); + XSLTAttributeDef.T_CHAR, false,XSLTAttributeDef.ERROR, ";"); + // xsl:decimal-format + XSLTAttributeDef groupingSeparatorAttr = new XSLTAttributeDef(null, + "grouping-separator", + XSLTAttributeDef.T_CHAR, false,XSLTAttributeDef.ERROR,","); + + + // xsl:element, xsl:attribute-set, xsl:copy XSLTAttributeDef useAttributeSetsAttr = new XSLTAttributeDef(null, "use-attribute-sets", XSLTAttributeDef.T_QNAMES, - false); + false, false, XSLTAttributeDef.WARNING); + + // xsl:if, xsl:when + XSLTAttributeDef testAttrRequired = new XSLTAttributeDef(null, "test", + XSLTAttributeDef.T_EXPR, true, false,XSLTAttributeDef.WARNING); + + + // Required. + // xsl:value-of, xsl:for-each, xsl:copy-of XSLTAttributeDef selectAttrRequired = new XSLTAttributeDef(null, "select", - XSLTAttributeDef.T_EXPR, true); - XSLTAttributeDef testAttrRequired = new XSLTAttributeDef(null, "test", - XSLTAttributeDef.T_EXPR, true); + XSLTAttributeDef.T_EXPR, true, false,XSLTAttributeDef.WARNING); + + // Optional. + // xsl:variable, xsl:param, xsl:with-param XSLTAttributeDef selectAttrOpt = new XSLTAttributeDef(null, "select", - XSLTAttributeDef.T_EXPR, false); + XSLTAttributeDef.T_EXPR, false, false,XSLTAttributeDef.WARNING); + + // Optional. + // Default: "node()" + // xsl:apply-templates XSLTAttributeDef selectAttrDefNode = new XSLTAttributeDef(null, "select", - XSLTAttributeDef.T_EXPR, "node()"); + XSLTAttributeDef.T_EXPR, false,XSLTAttributeDef.WARNING, "node()"); + // Optional. + // Default: "." + // xsl:sort XSLTAttributeDef selectAttrDefDot = new XSLTAttributeDef(null, "select", - XSLTAttributeDef.T_EXPR, "."); + XSLTAttributeDef.T_EXPR, false,XSLTAttributeDef.ERROR, "."); + // xsl:key XSLTAttributeDef matchAttrRequired = new XSLTAttributeDef(null, "match", - XSLTAttributeDef.T_PATTERN, true); + XSLTAttributeDef.T_PATTERN, true, false,XSLTAttributeDef.WARNING); + // xsl:template XSLTAttributeDef matchAttrOpt = new XSLTAttributeDef(null, "match", - XSLTAttributeDef.T_PATTERN, false); + XSLTAttributeDef.T_PATTERN, false, false,XSLTAttributeDef.WARNING); + // xsl:tempate XSLTAttributeDef priorityAttr = new XSLTAttributeDef(null, "priority", - XSLTAttributeDef.T_PRIORITY, false); + XSLTAttributeDef.T_NUMBER, false, false,XSLTAttributeDef.WARNING); + + // xsl:template, xsl:apply-templates XSLTAttributeDef modeAttr = new XSLTAttributeDef(null, "mode", - XSLTAttributeDef.T_QNAME, false); + XSLTAttributeDef.T_QNAME, false, false,XSLTAttributeDef.WARNING); + XSLTAttributeDef spaceAttr = - new XSLTAttributeDef(Constants.S_XMLNAMESPACEURI, "space", false, + new XSLTAttributeDef(Constants.S_XMLNAMESPACEURI, "space", false, false, false, XSLTAttributeDef.WARNING, "default", Constants.ATTRVAL_STRIP, "preserve", Constants.ATTRVAL_PRESERVE); + + XSLTAttributeDef spaceAttrLiteral = new XSLTAttributeDef(Constants.S_XMLNAMESPACEURI, "space", - XSLTAttributeDef.T_AVT, false); + XSLTAttributeDef.T_URL, false, true,XSLTAttributeDef.WARNING); + // xsl:namespace-alias XSLTAttributeDef stylesheetPrefixAttr = new XSLTAttributeDef(null, "stylesheet-prefix", - XSLTAttributeDef.T_CDATA, true); + XSLTAttributeDef.T_CDATA, true, false,XSLTAttributeDef.WARNING); XSLTAttributeDef resultPrefixAttr = new XSLTAttributeDef(null, "result-prefix", - XSLTAttributeDef.T_CDATA, true); + XSLTAttributeDef.T_CDATA, true, false,XSLTAttributeDef.WARNING); + + // xsl:text, xsl:value-of XSLTAttributeDef disableOutputEscapingAttr = new XSLTAttributeDef(null, "disable-output-escaping", XSLTAttributeDef.T_YESNO, - false); - XSLTAttributeDef levelAttr = new XSLTAttributeDef(null, "level", false, + false, false,XSLTAttributeDef.WARNING); + + // xsl:number + XSLTAttributeDef levelAttr = new XSLTAttributeDef(null, "level", false, false, false, XSLTAttributeDef.WARNING, "single", Constants.NUMBERLEVEL_SINGLE, "multiple", Constants.NUMBERLEVEL_MULTI, "any", Constants.NUMBERLEVEL_ANY); - levelAttr.setDefault("single"); - XSLTAttributeDef countAttr = new XSLTAttributeDef(null, "count", - XSLTAttributeDef.T_PATTERN, false); + XSLTAttributeDef.T_PATTERN, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef fromAttr = new XSLTAttributeDef(null, "from", - XSLTAttributeDef.T_PATTERN, false); + XSLTAttributeDef.T_PATTERN, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef valueAttr = new XSLTAttributeDef(null, "value", - XSLTAttributeDef.T_EXPR, false); + XSLTAttributeDef.T_EXPR, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef formatAttr = new XSLTAttributeDef(null, "format", - XSLTAttributeDef.T_AVT, false); - + XSLTAttributeDef.T_CDATA, false, true,XSLTAttributeDef.WARNING); formatAttr.setDefault("1"); - + + // xsl:number, xsl:sort XSLTAttributeDef langAttr = new XSLTAttributeDef(null, "lang", - XSLTAttributeDef.T_AVT, false); + XSLTAttributeDef.T_NMTOKEN, false, true,XSLTAttributeDef.ERROR); + + // xsl:number XSLTAttributeDef letterValueAttr = new XSLTAttributeDef(null, "letter-value", - XSLTAttributeDef.T_AVT, false); + false, true, false, XSLTAttributeDef.WARNING, + "alphabetic", Constants.NUMBERLETTER_ALPHABETIC, + "traditional", Constants.NUMBERLETTER_TRADITIONAL); + // xsl:number XSLTAttributeDef groupingSeparatorAVT = new XSLTAttributeDef(null, "grouping-separator", - XSLTAttributeDef.T_AVT, false); + XSLTAttributeDef.T_CHAR, false, true,XSLTAttributeDef.WARNING); + // xsl:number XSLTAttributeDef groupingSizeAttr = new XSLTAttributeDef(null, "grouping-size", - XSLTAttributeDef.T_AVT, false); - XSLTAttributeDef dataTypeAttr = new XSLTAttributeDef(null, "data-type", - XSLTAttributeDef.T_AVT, "text"); - XSLTAttributeDef orderAttr = new XSLTAttributeDef(null, "order", - XSLTAttributeDef.T_AVT, "ascending"); - XSLTAttributeDef caseOrderAttr = new XSLTAttributeDef(null, "case-order", - XSLTAttributeDef.T_AVT, false); + XSLTAttributeDef.T_NUMBER, false, true,XSLTAttributeDef.WARNING); + + // xsl:sort + XSLTAttributeDef dataTypeAttr = new XSLTAttributeDef(null, "data-type", false, true, true, XSLTAttributeDef.WARNING, + "text", Constants.SORTDATATYPE_TEXT ,"number", Constants.SORTDATATYPE_TEXT); + dataTypeAttr.setDefault("text"); + + // xsl:sort + XSLTAttributeDef orderAttr = new XSLTAttributeDef(null, "order", false, true, false,XSLTAttributeDef.ERROR, + "ascending", Constants.SORTORDER_ASCENDING, + "descending", Constants.SORTORDER_DESCENDING); + orderAttr.setDefault("ascending"); + + // xsl:sort + XSLTAttributeDef caseOrderAttr = new XSLTAttributeDef(null, "case-order", false, true, false,XSLTAttributeDef.ERROR, + "upper-first", Constants.SORTCASEORDER_UPPERFIRST , + "lower-first", Constants.SORTCASEORDER_LOWERFIRST); + + // xsl:message XSLTAttributeDef terminateAttr = new XSLTAttributeDef(null, "terminate", - XSLTAttributeDef.T_YESNO, false); - + XSLTAttributeDef.T_YESNO, false, false,XSLTAttributeDef.WARNING); terminateAttr.setDefault("no"); + // top level attributes XSLTAttributeDef xslExcludeResultPrefixesAttr = new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "exclude-result-prefixes", - XSLTAttributeDef.T_STRINGLIST, false); + XSLTAttributeDef.T_STRINGLIST, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef xslExtensionElementPrefixesAttr = new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "extension-element-prefixes", - XSLTAttributeDef.T_PREFIX_URLLIST, false); + XSLTAttributeDef.T_PREFIX_URLLIST, false, false,XSLTAttributeDef.WARNING); + // result-element-atts XSLTAttributeDef xslUseAttributeSetsAttr = new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "use-attribute-sets", - XSLTAttributeDef.T_QNAMES, false); + XSLTAttributeDef.T_QNAMES, false, false,XSLTAttributeDef.WARNING); XSLTAttributeDef xslVersionAttr = new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "version", - XSLTAttributeDef.T_NMTOKEN, false); + XSLTAttributeDef.T_NMTOKEN, false, false,XSLTAttributeDef.WARNING); + XSLTElementDef charData = new XSLTElementDef(this, null, "text()", null /*alias */, null /* elements */, null, /* attributes */ new ProcessorCharacters(), @@ -263,10 +347,11 @@ charData.setType(XSLTElementDef.T_PCDATA); XSLTAttributeDef resultAttr = new XSLTAttributeDef(null, "*", - XSLTAttributeDef.T_AVT, false); + XSLTAttributeDef.T_AVT, false, true,XSLTAttributeDef.WARNING); XSLTAttributeDef xslResultAttr = new XSLTAttributeDef(Constants.S_XSLNAMESPACEURL, "*", - XSLTAttributeDef.T_CDATA, false); + XSLTAttributeDef.T_CDATA, false, false,XSLTAttributeDef.WARNING); + XSLTElementDef[] templateElements = new XSLTElementDef[22]; XSLTElementDef[] templateElementsAndParams = new XSLTElementDef[23]; XSLTElementDef[] templateElementsAndSort = new XSLTElementDef[23]; @@ -296,8 +381,8 @@ xslVersionAttr, xslResultAttr, resultAttr }, - new ProcessorUnknown(), - ElemUnknown.class /* class object */, 20, true); + new ProcessorUnknown(), + ElemUnknown.class /* class object */, 20, true); XSLTElementDef xslValueOf = new XSLTElementDef(this, Constants.S_XSLNAMESPACEURL, "value-of", null /*alias */, null /* elements */, @@ -445,7 +530,7 @@ "processing-instruction", null /*alias */, charTemplateElements /* elements */, // %char-template;> new XSLTAttributeDef[]{ - nameAVTRequired, + nameAVT_NCNAMERequired, spaceAttr }, new ProcessorTemplateElem(), ElemPI.class /* class object */, 20, true); @@ -508,7 +593,9 @@ new ProcessorExsltFuncResult(), ElemExsltFuncResult.class /* class object */); + int i = 0; + templateElements[i++] = charData; // #PCDATA // char-instructions @@ -543,7 +630,9 @@ templateElementsAndParams[k] = templateElements[k]; templateElementsAndSort[k] = templateElements[k]; exsltFunctionElements[k] = templateElements[k]; + } + templateElementsAndParams[k] = xslParam; templateElementsAndSort[k] = xslSort; exsltFunctionElements[k] = xslParam; @@ -581,7 +670,6 @@ new ProcessorInclude(), null /* class object */, 20, true); - XSLTElementDef[] topLevelElements = new XSLTElementDef[] {includeDef, importDef, @@ -699,7 +787,7 @@ templateElementsAndParams /* elements */, new XSLTAttributeDef[]{ matchAttrOpt, - nameAttrOpt, + nameAttrOpt_ERROR, priorityAttr, modeAttr, spaceAttr }, @@ -732,33 +820,33 @@ null, "lang", XSLTAttributeDef.T_NMTOKEN, - true), + true, false,XSLTAttributeDef.WARNING), new XSLTAttributeDef( - null, "src", XSLTAttributeDef.T_URL, false) }, + null, "src", XSLTAttributeDef.T_URL, false, false,XSLTAttributeDef.WARNING) }, new ProcessorLRE(), ElemExtensionScript.class /* class object */, 20, true) }, // EMPTY new XSLTAttributeDef[]{ new XSLTAttributeDef( - null, "prefix", XSLTAttributeDef.T_NMTOKEN, true), + null, "prefix", XSLTAttributeDef.T_NMTOKEN, true, false,XSLTAttributeDef.WARNING), new XSLTAttributeDef( - null, "elements", XSLTAttributeDef.T_STRINGLIST, false), + null, "elements", XSLTAttributeDef.T_STRINGLIST, false, false,XSLTAttributeDef.WARNING), new XSLTAttributeDef( - null, "functions", XSLTAttributeDef.T_STRINGLIST, false) }, + null, "functions", XSLTAttributeDef.T_STRINGLIST, false, false,XSLTAttributeDef.WARNING) }, new ProcessorLRE(), ElemExtensionDecl.class /* class object */), exsltFunction}/* exslt */; //end of topevelElements XSLTAttributeDef excludeResultPrefixesAttr = new XSLTAttributeDef(null, "exclude-result-prefixes", - XSLTAttributeDef.T_STRINGLIST, false); + XSLTAttributeDef.T_STRINGLIST, false,false,XSLTAttributeDef.WARNING); XSLTAttributeDef extensionElementPrefixesAttr = new XSLTAttributeDef(null, "extension-element-prefixes", - XSLTAttributeDef.T_PREFIX_URLLIST, false); + XSLTAttributeDef.T_PREFIX_URLLIST, false,false,XSLTAttributeDef.WARNING); XSLTAttributeDef idAttr = new XSLTAttributeDef(null, "id", - XSLTAttributeDef.T_CDATA, false); + XSLTAttributeDef.T_CDATA, false,false,XSLTAttributeDef.WARNING); XSLTAttributeDef versionAttrRequired = new XSLTAttributeDef(null, "version", XSLTAttributeDef.T_NMTOKEN, - true); + true,false,XSLTAttributeDef.WARNING); XSLTElementDef stylesheetElemDef = new XSLTElementDef(this, Constants.S_XSLNAMESPACEURL, "stylesheet", "transform", @@ -825,3 +913,4 @@ return m_availElems.containsKey(elemName); } } + 1.28 +55 -4 xml-xalan/java/src/org/apache/xalan/res/XSLTErrorResources.java Index: XSLTErrorResources.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/res/XSLTErrorResources.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- XSLTErrorResources.java 26 Jun 2002 15:20:06 -0000 1.27 +++ XSLTErrorResources.java 10 Jul 2002 16:06:31 -0000 1.28 @@ -934,8 +934,9 @@ public static final int ER_FAILED_CREATING_ELEMLITRSLT = 203; - /** Priority value does not contain a parsable number */ - public static final int ER_PRIORITY_NOT_PARSABLE = 204; + /** Value for {0} should contain a parsable number */ + public static final int ER_VALUE_SHOULD_BE_NUMBER = 204; + /** Value for {0} should equal 'yes' or 'no' */ @@ -1022,8 +1023,9 @@ // Non-whitespace text is not allowed in this position in the stylesheet! public static final int ER_NONWHITESPACE_NOT_ALLOWED_IN_POSITION = 238; - // An XSLT attribute of type T_CHAR must be only 1 character! - public static final int ER_ATTR_T_CHAR_ONE_CHAR = 239; + // This code is shared with warning codes. + // Illegal value: {1} used for CHAR attribute: {0}. An attribute of type CHAR must be only 1 character! + public static final int INVALID_TCHAR = 239; // SystemId Unknown public static final int ER_SYSTEMID_UNKNOWN = 240; @@ -1031,6 +1033,26 @@ // Location of error unknown public static final int ER_LOCATION_UNKNOWN = 241; + //The following codes are shared with the warning codes... + // Illegal value: {1} used for QNAME attribute: {0} + public static final int INVALID_QNAME = 242; + + // Illegal value\u003a {1} used for ENUM attribute\u003a {0}. Valid values are\u003a {2}. + public static final int INVALID_ENUM = 243; + + // Illegal value\u003a {1} used for NMTOKEN attribute\u003a {0}. + public static final int INVALID_NMTOKEN = 244; + + // Illegal value\u003a {1} used for NCNAME attribute\u003a {0}. + public static final int INVALID_NCNAME = 245; + + // Illegal value\u003a {1} used for boolean attribute\u003a {0}. + public static final int INVALID_BOOLEAN = 246; + + // Illegal value\u003a {1} used for number attribute\u003a {0}. + public static final int INVALID_NUMBER = 247; + // End of shared codes... + /* @@ -1182,7 +1204,36 @@ /** WG_EMPTY_SECOND_ARG */ public static final int WG_EMPTY_SECOND_ARG = 26; + + + //The following warning codes are shared with the error codes ... + // Illegal value: {1} used for CHAR attribute: {0}. An attribute of type CHAR must be only 1 character! + public static final int WG_INVALID_TCHAR = 239; + + + // Illegal value: {1} used for QNAME attribute: {0} + public static final int WG_INVALID_QNAME = 242; + + + // Illegal value\u003a {1} used for ENUM attribute\u003a {0}. Valid values are\u003a {2}. + public static final int WG_INVALID_ENUM = 243; + + + // Illegal value\u003a {1} used for NMTOKEN attribute\u003a {0}. + public static final int WG_INVALID_NMTOKEN = 244; + + + // Illegal value\u003a {1} used for NCNAME attribute\u003a {0}. + public static final int WG_INVALID_NCNAME = 245; + + + // Illegal value\u003a {1} used for boolean attribute\u003a {0}. + public static final int WG_INVALID_BOOLEAN = 246; + + // Illegal value\u003a {1} used for number attribute\u003a {0}. + public static final int WG_INVALID_NUMBER = 247; + // End of codes that are shared... // Other miscellaneous text used inside the code... 1.7 +40 -4 xml-xalan/java/src/org/apache/xalan/res/XSLTErrorResources.properties Index: XSLTErrorResources.properties =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/res/XSLTErrorResources.properties,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- XSLTErrorResources.properties 26 Jun 2002 15:20:06 -0000 1.6 +++ XSLTErrorResources.properties 10 Jul 2002 16:06:31 -0000 1.7 @@ -412,8 +412,8 @@ ER0202=Cannot initialize URI with empty parameters # ER_FAILED_CREATING_ELEMLITRSLT ER0203=Failed creating ElemLiteralResult instance -# ER_PRIORITY_NOT_PARSABLE -ER0204=Priority value does not contain a parsable number +# ER_VALUE_SHOULD_BE_NUMBER +ER0204=Value for {0} should contain a parsable number # ER_VALUE_SHOULD_EQUAL ER0205= Value for {0} should equal yes or no # ER_FAILED_CALLING_METHOD @@ -484,12 +484,25 @@ ER0237={0} is not allowed in this position in the stylesheet! # ER_NONWHITESPACE_NOT_ALLOWED_IN_POSITION ER0238=Non-whitespace text is not allowed in this position in the stylesheet! -# ER_ATTR_T_CHAR_ONE_CHAR -ER0239=An XSLT attribute of type T_CHAR must be only 1 character! +# INVALID_TCHAR +ER0239=Illegal value: {1} used for CHAR attribute: {0}. An attribute of type CHAR must be only 1 character! # ER_SYSTEMID_UNKNOWN ER0240=SystemId Unknown # ER_LOCATION_UNKNOWN ER0241=Location of error unknown +# INVALID_QNAME +ER0242=Illegal value\u003a {1} used for QNAME attribute\u003a {0} +# INVALID_ENUM +ER0243=Illegal value\u003a {1} used for ENUM attribute\u003a {0}. Valid values are\u003a {2}. +# INVALID NMTOKEN +ER0244=Illegal value\u003a {1} used for NMTOKEN attribute\u003a {0} +# INVALID_NCNAME +ER0245=Illegal value\u003a {1} used for NCNAME attribute\u003a {0} +# INVALID_BOOLEAN +ER0246=Illegal value\u003a {1} used for boolean attribute\u003a {0} +# INVALID_NUMBER +ER0247=Illegal value\u003a {1} used for number attribute\u003a {0} + # WG_FOUND_CURLYBRACE @@ -544,6 +557,29 @@ WR0025=Illegal value used for attribute {0}\u003a {1} # WG_EMPTY_SECOND_ARG WR0026=Resulting nodeset from second argument of document function is empty. The first agument will be used. + + +# INVALID_TCHAR +WR0239=Illegal value: {1} used for CHAR attribute: {0}. An attribute of type CHAR must be only 1 character! + +# INVALID_QNAME +WR0242=Illegal value\u003a {1} used for QNAME attribute\u003a {0} + +# INVALID_ENUM +WR0243=Illegal value\u003a {1} used for ENUM attribute\u003a {0}. Valid values are\u003a {2}. + +# INVALID NMTOKEN +WR0244=Illegal value\u003a {1} used for NMTOKEN attribute\u003a {0} + +# INVALID_NCNAME +WR0245=Illegal value\u003a {1} used for NCNAME attribute\u003a {0} + +# INVALID_BOOLEAN +WR0246=Illegal value\u003a {1} used for boolean attribute\u003a {0} + +# INVALID_NUMBER +WR0247=Illegal value\u003a {1} used for number attribute\u003a {0} + ui_language=en help_language=en language=en 1.18 +8 -1 xml-xalan/java/src/org/apache/xalan/templates/AVT.java Index: AVT.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/AVT.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- AVT.java 22 Mar 2002 01:04:40 -0000 1.17 +++ AVT.java 10 Jul 2002 16:06:31 -0000 1.18 @@ -631,5 +631,12 @@ } } } - + + + /** + * Returns true if this AVT is simple + */ + public boolean isSimple() { + return m_simpleString != null; + } } 1.14 +10 -0 xml-xalan/java/src/org/apache/xalan/templates/Constants.java Index: Constants.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/Constants.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- Constants.java 10 Jun 2002 19:24:42 -0000 1.13 +++ Constants.java 10 Jul 2002 16:06:31 -0000 1.14 @@ -463,6 +463,8 @@ /** For Stylesheet-prefix and result-prefix in xsl:namespace-alias */ public static final String ATTRVAL_DEFAULT_PREFIX = "#default"; + /** Integer equivalents for above */ + public static final int NUMBERLETTER_ALPHABETIC = 1, NUMBERLETTER_TRADITIONAL = 2; /** Integer equivelents for above */ public static final int NUMBERLEVEL_SINGLE = 1, NUMBERLEVEL_MULTI = 2, @@ -482,6 +484,14 @@ ATTRVAL_CASEORDER_UPPER = "upper-first", ATTRVAL_CASEORDER_LOWER = "lower-first"; + /** Integer equivelents for DATATYPE attribute */ + public static final int SORTDATATYPE_TEXT = 1, SORTDATATYPE_NUMBER = 2; + + /** Integer equivelents for ORDER attribute */ + public static final int SORTORDER_ASCENDING = 1, SORTORDER_DESCENDING = 2; + + /** Integer equivelents for CASE-ORDER attribute */ + public static final int SORTCASEORDER_UPPERFIRST = 1, SORTCASEORDER_LOWERFIRST = 2; /** some stuff for Decimal-format */ public static final String ATTRVAL_INFINITY = "Infinity", 1.18 +14 -0 xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java Index: ElemAttribute.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- ElemAttribute.java 24 Mar 2002 00:57:52 -0000 1.17 +++ ElemAttribute.java 10 Jul 2002 16:06:31 -0000 1.18 @@ -293,4 +293,18 @@ return super.appendChild(newChild); } + /** + * @see ElemElement#setName(AVT) + */ + public void setName(AVT v) { + if (v.isSimple()) + { + if (v.getSimpleString().equals("xmlns")) + { + throw new IllegalArgumentException(); + } + } + super.setName(v); + } + } 1.26 +6 -3 xml-xalan/java/src/org/apache/xalan/templates/ElemElement.java Index: ElemElement.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemElement.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- ElemElement.java 24 Mar 2002 13:48:47 -0000 1.25 +++ ElemElement.java 10 Jul 2002 16:06:31 -0000 1.26 @@ -285,12 +285,15 @@ ResultTreeHandler rhandler = transformer.getResultTreeHandler(); XPathContext xctxt = transformer.getXPathContext(); int sourceNode = xctxt.getCurrentNode(); - String nodeName = m_name_avt.evaluate(xctxt, sourceNode, this); + + + String nodeName = m_name_avt == null ? null : m_name_avt.evaluate(xctxt, sourceNode, this); String prefix = null; String nodeNamespace = ""; - if (!validateNodeName(nodeName)) + // Only validate if an AVT was used. + if ((nodeName != null) && (!m_name_avt.isSimple()) && (!validateNodeName(nodeName))) { transformer.getMsgMgr().warn( this, XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_VALUE, @@ -299,7 +302,7 @@ nodeName = null; } - else + else if (nodeName != null) { prefix = QName.getPrefixPart(nodeName); 1.28 +8 -6 xml-xalan/java/src/org/apache/xalan/templates/ElemNumber.java Index: ElemNumber.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemNumber.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- ElemNumber.java 1 Jul 2002 15:41:11 -0000 1.27 +++ ElemNumber.java 10 Jul 2002 16:06:31 -0000 1.28 @@ -1144,13 +1144,15 @@ transformer.getXPathContext(), contextNode, this) : null; - // Validate grouping separator - if ((digitGroupSepValue != null) && (digitGroupSepValue.length() != 1)) + // Validate grouping separator if an AVT was used; otherwise this was + // validated statically in XSLTAttributeDef.java. + if ((digitGroupSepValue != null) && (!m_groupingSeparator_avt.isSimple()) && + (digitGroupSepValue.length() != 1)) { - transformer.getMsgMgr().warn( - this, XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_VALUE, - new Object[]{ Constants.ATTRNAME_NAME, m_groupingSeparator_avt.getName() }); - } + transformer.getMsgMgr().warn( + this, XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_VALUE, + new Object[]{ Constants.ATTRNAME_NAME, m_groupingSeparator_avt.getName()}); + } String nDigitsPerGroupValue = 1.13 +3 -1 xml-xalan/java/src/org/apache/xalan/templates/ElemPI.java Index: ElemPI.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemPI.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- ElemPI.java 24 Mar 2002 00:57:53 -0000 1.12 +++ ElemPI.java 10 Jul 2002 16:06:31 -0000 1.13 @@ -179,7 +179,9 @@ { error(XSLTErrorResources.ER_PROCESSINGINSTRUCTION_NAME_CANT_BE_XML); //"processing-instruction name can not be 'xml'"); } - else if (!isValidNCName(piName)) + + // Only check if an avt was used (ie. this wasn't checked at compose time.) + else if ((!m_name_atv.isSimple()) && (!isValidNCName(piName))) { error(XSLTErrorResources.ER_PROCESSINGINSTRUCTION_NOTVALID_NCNAME, new Object[]{ piName }); //"processing-instruction name must be a valid NCName: "+piName); 1.8 +180 -3 xml-xalan/java/src/org/apache/xml/utils/QName.java Index: QName.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/utils/QName.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- QName.java 28 Jul 2001 00:25:59 -0000 1.7 +++ QName.java 10 Jul 2002 16:06:32 -0000 1.8 @@ -105,6 +105,12 @@ "http://www.w3.org/XML/1998/namespace"; /** + * The xmlns namespace. + */ + public static final String S_XMLNSNAMESPACEURI = + "http://www.w3.org/2000/xmlns"; + + /** * The cached hashcode, which is calculated at construction time. * @serial */ @@ -125,16 +131,41 @@ */ public QName(String namespaceURI, String localName) { + this(namespaceURI, localName, false); + } + + /** + * Constructs a new QName with the specified namespace URI and + * local name. + * + * @param namespaceURI The namespace URI if known, or null + * @param localName The local name + * @param validate If true the new QName will be validated and an IllegalArgumentException will + * be thrown if it is invalid. + */ + public QName(String namespaceURI, String localName, boolean validate) + { + // This check was already here. So, for now, I will not add it to the validation + // that is done when the validate parameter is true. if (localName == null) throw new IllegalArgumentException(XSLMessages.createXPATHMessage( XPATHErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null"); + if (validate) + { + if (!XMLChar.isValidNCName(localName)) + { + throw new IllegalArgumentException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName"); + } + } + _namespaceURI = namespaceURI; _localName = localName; m_hashCode = toString().hashCode(); } - + /** * Constructs a new QName with the specified namespace URI, prefix * and local name. @@ -142,37 +173,94 @@ * @param namespaceURI The namespace URI if known, or null * @param prefix The namespace prefix is known, or null * @param localName The local name + * */ public QName(String namespaceURI, String prefix, String localName) { + this(namespaceURI, prefix, localName, false); + } + + /** + * Constructs a new QName with the specified namespace URI, prefix + * and local name. + * + * @param namespaceURI The namespace URI if known, or null + * @param prefix The namespace prefix is known, or null + * @param localName The local name + * @param validate If true the new QName will be validated and an IllegalArgumentException will + * be thrown if it is invalid. + */ + public QName(String namespaceURI, String prefix, String localName, boolean validate) + { + // This check was already here. So, for now, I will not add it to the validation + // that is done when the validate parameter is true. if (localName == null) throw new IllegalArgumentException(XSLMessages.createXPATHMessage( XPATHErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null"); + if (validate) + { + if (!XMLChar.isValidNCName(localName)) + { + throw new IllegalArgumentException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName"); + } + + if ((null != prefix) && (!XMLChar.isValidNCName(prefix))) + { + throw new IllegalArgumentException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_PREFIX_INVALID,null )); //"Argument 'prefix' not a valid NCName"); + } + + } _namespaceURI = namespaceURI; _prefix = prefix; _localName = localName; m_hashCode = toString().hashCode(); - } + } /** * Construct a QName from a string, without namespace resolution. Good * for a few odd cases. * * @param localName Local part of qualified name + * */ public QName(String localName) { + this(localName, false); + } + + /** + * Construct a QName from a string, without namespace resolution. Good + * for a few odd cases. + * + * @param localName Local part of qualified name + * @param validate If true the new QName will be validated and an IllegalArgumentException will + * be thrown if it is invalid. + */ + public QName(String localName, boolean validate) + { + // This check was already here. So, for now, I will not add it to the validation + // that is done when the validate parameter is true. if (localName == null) throw new IllegalArgumentException(XSLMessages.createXPATHMessage( XPATHErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null"); + if (validate) + { + if (!XMLChar.isValidNCName(localName)) + { + throw new IllegalArgumentException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName"); + } + } _namespaceURI = null; _localName = localName; m_hashCode = toString().hashCode(); - } + } /** * Construct a QName from a string, resolving the prefix @@ -184,6 +272,21 @@ */ public QName(String qname, Stack namespaces) { + this(qname, namespaces, false); + } + + /** + * Construct a QName from a string, resolving the prefix + * using the given namespace stack. The default namespace is + * not resolved. + * + * @param qname Qualified name to resolve + * @param namespaces Namespace stack to use to resolve namespace + * @param validate If true the new QName will be validated and an IllegalArgumentException will + * be thrown if it is invalid. + */ + public QName(String qname, Stack namespaces, boolean validate) + { String namespace = null; String prefix = null; @@ -197,6 +300,7 @@ { namespace = S_XMLNAMESPACEURI; } + // Do we want this? else if (prefix.equals("xmlns")) { return; @@ -235,6 +339,15 @@ _localName = (indexOfNSSep < 0) ? qname : qname.substring(indexOfNSSep + 1); + + if (validate) + { + if ((_localName == null) || (!XMLChar.isValidNCName(_localName))) + { + throw new IllegalArgumentException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName"); + } + } _namespaceURI = namespace; _prefix = prefix; m_hashCode = toString().hashCode(); @@ -252,6 +365,23 @@ public QName(String qname, Element namespaceContext, PrefixResolver resolver) { + this(qname, namespaceContext, resolver, false); + } + + /** + * Construct a QName from a string, resolving the prefix + * using the given namespace context and prefix resolver. + * The default namespace is not resolved. + * + * @param qname Qualified name to resolve + * @param namespaceContext Namespace Context to use + * @param resolver Prefix resolver for this context + * @param validate If true the new QName will be validated and an IllegalArgumentException will + * be thrown if it is invalid. + */ + public QName(String qname, Element namespaceContext, + PrefixResolver resolver, boolean validate) + { _namespaceURI = null; @@ -269,6 +399,12 @@ { _namespaceURI = S_XMLNAMESPACEURI; } + + // Do we want this? + else if (prefix.equals("xmlns")) + { + _namespaceURI = S_XMLNSNAMESPACEURI; + } else { _namespaceURI = resolver.getNamespaceForPrefix(prefix, @@ -292,9 +428,20 @@ _localName = (indexOfNSSep < 0) ? qname : qname.substring(indexOfNSSep + 1); + + if (validate) + { + if ((_localName == null) || (!XMLChar.isValidNCName(_localName))) + { + throw new IllegalArgumentException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName"); + } + } + m_hashCode = toString().hashCode(); } + /** * Construct a QName from a string, resolving the prefix * using the given namespace stack. The default namespace is @@ -305,6 +452,21 @@ */ public QName(String qname, PrefixResolver resolver) { + this(qname, resolver, false); + } + + /** + * Construct a QName from a string, resolving the prefix + * using the given namespace stack. The default namespace is + * not resolved. + * + * @param qname Qualified name to resolve + * @param resolver Prefix resolver for this context + * @param validate If true the new QName will be validated and an IllegalArgumentException will + * be thrown if it is invalid. + */ + public QName(String qname, PrefixResolver resolver, boolean validate) + { _namespaceURI = null; @@ -318,6 +480,11 @@ { _namespaceURI = S_XMLNAMESPACEURI; } + // Do we want this? + else if (prefix.equals("xmlns")) + { + _namespaceURI = S_XMLNSNAMESPACEURI; + } else { _namespaceURI = resolver.getNamespaceForPrefix(prefix); @@ -334,6 +501,16 @@ _localName = (indexOfNSSep < 0) ? qname : qname.substring(indexOfNSSep + 1); + + if (validate) + { + if ((_localName == null) || (!XMLChar.isValidNCName(_localName))) + { + throw new IllegalArgumentException(XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName"); + } + } + m_hashCode = toString().hashCode(); } 1.3 +25 -5 xml-xalan/java/src/org/apache/xml/utils/StringToIntTable.java Index: StringToIntTable.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/utils/StringToIntTable.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- StringToIntTable.java 30 Nov 2000 22:58:53 -0000 1.2 +++ StringToIntTable.java 10 Jul 2002 16:06:32 -0000 1.3 @@ -64,6 +64,8 @@ public class StringToIntTable { + public static final int INVALID_KEY = -10000; + /** Block size to allocate */ private int m_blocksize; @@ -155,7 +157,8 @@ * * @param key String to look for * - * @return The String's int value or a bogus value if not found + * @return The String's int value + * */ public final int get(String key) { @@ -166,7 +169,7 @@ return m_values[i]; } - return -10000; // Bogus value, needs to throw exception. + return INVALID_KEY; } /** @@ -174,13 +177,13 @@ * * @param key String to look for * - * @return The string's int value, or a bogus value if not found + * @return The string's int value */ public final int getIgnoreCase(String key) { if (null == key) - return -10000; // Bogus value, needs to throw exception. + return INVALID_KEY; for (int i = 0; i < m_firstFree; i++) { @@ -188,7 +191,7 @@ return m_values[i]; } - return -10000; // Bogus value, needs to throw exception. + return INVALID_KEY; } /** @@ -209,4 +212,21 @@ return false; } + + /** + * Return array of keys in the table. + * + * @return Array of strings + */ + public final String[] keys() + { + String [] keysArr = new String[m_firstFree]; + + for (int i = 0; i < m_firstFree; i++) + { + keysArr[i] = m_map[i]; + } + + return keysArr; + } } 1.16 +7 -0 xml-xalan/java/src/org/apache/xpath/res/XPATHErrorResources.java Index: XPATHErrorResources.java =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/res/XPATHErrorResources.java,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- XPATHErrorResources.java 27 Jun 2002 15:01:19 -0000 1.15 +++ XPATHErrorResources.java 10 Jul 2002 16:06:32 -0000 1.16 @@ -514,6 +514,13 @@ /** Expected relative path pattern */ public static final int ER_EXPECTED_REL_PATH_PATTERN = 100; + + /** localname in QNAME should be a valid NCName */ + public static final int ER_ARG_LOCALNAME_INVALID = 101; + + /** prefix in QNAME should be a valid NCName */ + public static final int ER_ARG_PREFIX_INVALID = 102; + 1.7 +4 -1 xml-xalan/java/src/org/apache/xpath/res/XPATHErrorResources.properties Index: XPATHErrorResources.properties =================================================================== RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/res/XPATHErrorResources.properties,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- XPATHErrorResources.properties 28 Jun 2002 15:00:39 -0000 1.6 +++ XPATHErrorResources.properties 10 Jul 2002 16:06:32 -0000 1.7 @@ -206,7 +206,10 @@ ER0099=A step pattern was expected, but '/' was encountered. # ER_EXPECTED_REL_PATH_PATTERN ER0100=A relative path pattern was expected. - +# ER_ARG_LOCALNAME_INVALID +ER0101= Localname in QNAME should be a valid NCName +# ER_ARG_PREFIX_INVALID +ER0102=Prefix in QNAME should be a valid NCName # WG_LOCALE_NAME_NOT_HANDLED
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]