001: package net.sf.saxon.om;
002:
003: import net.sf.saxon.Err;
004:
005: /**
006: * A NameChecker performs validation and analysis of XML names. There are two implementations
007: * of this interface, one for XML 1.0 names and one for XML 1.1 names. The class also handles
008: * validation of characters against the XML 1.0 or XML 1.1 rules.
009: */
010:
011: public abstract class NameChecker {
012:
013: /**
014: * Validate whether a given string constitutes a valid QName, as defined in XML Namespaces.
015: * Note that this does not test whether the prefix is actually declared.
016: *
017: * @param name the name to be tested
018: * @return true if the name is a lexically-valid QName
019: */
020:
021: public final boolean isQName(String name) {
022: int colon = name.indexOf(':');
023: if (colon < 0)
024: return isValidNCName(name);
025: if (colon == 0 || colon == name.length() - 1)
026: return false;
027: if (!isValidNCName(name.substring(0, colon)))
028: return false;
029: if (!isValidNCName(name.substring(colon + 1)))
030: return false;
031: return true;
032: }
033:
034: /**
035: * Validate whether a given string constitutes a valid NCName, as defined in XML Namespaces.
036: *
037: * @param name the name to be tested
038: * @return true if the name is a lexically-valid QName
039: */
040:
041: public abstract boolean isValidNCName(String name);
042:
043: /**
044: * Extract the prefix from a QName. Note, the QName is assumed to be valid.
045: *
046: * @param qname The lexical QName whose prefix is required
047: * @return the prefix, that is the part before the colon. Returns an empty
048: * string if there is no prefix
049: */
050:
051: public static final String getPrefix(String qname) {
052: int colon = qname.indexOf(':');
053: if (colon < 0) {
054: return "";
055: }
056: return qname.substring(0, colon);
057: }
058:
059: /**
060: * Validate a QName, and return the prefix and local name.
061: *
062: * @exception QNameException if not a valid QName.
063: * @param qname the lexical QName whose parts are required
064: * @return an array of two strings, the prefix and the local name. The first
065: * item is a zero-length string if there is no prefix.
066: */
067:
068: public final String[] getQNameParts(CharSequence qname)
069: throws QNameException {
070: String[] parts = new String[2];
071: int colon = -1;
072: int len = qname.length();
073: for (int i = 0; i < len; i++) {
074: if (qname.charAt(i) == ':') {
075: colon = i;
076: break;
077: }
078: }
079: if (colon < 0) {
080: parts[0] = "";
081: parts[1] = qname.toString();
082: if (!isValidNCName(parts[1])) {
083: throw new QNameException("Invalid QName "
084: + Err.wrap(qname));
085: }
086: } else {
087: if (colon == 0) {
088: throw new QNameException(
089: "QName cannot start with colon: "
090: + Err.wrap(qname));
091: }
092: if (colon == len - 1) {
093: throw new QNameException(
094: "QName cannot end with colon: "
095: + Err.wrap(qname));
096: }
097: parts[0] = qname.subSequence(0, colon).toString();
098: parts[1] = qname.subSequence(colon + 1, len).toString();
099: // don't validate the prefix. If it isn't valid, then we'll get an error when we try to
100: // find the namespace declaration
101: // if (!XMLChar.isValidNCName(parts[0])) {
102: // throw new QNameException("Invalid QName prefix " + Err.wrap(parts[0]));
103: // }
104: if (!isValidNCName(parts[1])) {
105: throw new QNameException("Invalid QName local part "
106: + Err.wrap(parts[1]));
107: }
108: }
109: return parts;
110: }
111:
112: /**
113: * Test whether a character is a valid XML character
114: * @param ch the character to be tested
115: * @return true if this is a valid character in the selected version of XML
116: */
117:
118: public abstract boolean isValidChar(int ch);
119:
120: /**
121: * Return the XML version supported by this NameChecker
122: * @return "1.0" or "1.1" as a string
123: */
124:
125: public abstract String getXMLVersion();
126: }
127:
128: //
129: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
130: // you may not use this file except in compliance with the License. You may obtain a copy of the
131: // License at http://www.mozilla.org/MPL/
132: //
133: // Software distributed under the License is distributed on an "AS IS" basis,
134: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
135: // See the License for the specific language governing rights and limitations under the License.
136: //
137: // The Original Code is: all this file.
138: //
139: // The Initial Developer of the Original Code is Michael H. Kay.
140: //
141: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
142: //
143: // Contributor(s): none.
144: //
|