1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id$ 20 */ 21 22 package org.apache.xml.utils; 23 24 /** 25 * This class defines the basic XML character properties. The data 26 * in this class can be used to verify that a character is a valid 27 * XML character or if the character is a space, name start, or name 28 * character. 29 * <p> 30 * A series of convenience methods are supplied to ease the burden 31 * of the developer. Because inlining the checks can improve per 32 * character performance, the tables of character properties are 33 * public. Using the character as an index into the <code>CHARS</code> 34 * array and applying the appropriate mask flag (e.g. 35 * <code>MASK_VALID</code>), yields the same results as calling the 36 * convenience methods. There is one exception: check the comments 37 * for the <code>isValid</code> method for details. 38 * 39 * @author Glenn Marcy, IBM 40 * @author Andy Clark, IBM 41 * @author Eric Ye, IBM 42 * @author Arnaud Le Hors, IBM 43 * @author Rahul Srivastava, Sun Microsystems Inc. 44 * 45 * @version $Id: XMLChar.java,v 1.7 2002/01/29 01:15:18 lehors Exp $ 46 */ 47 public class XMLChar { 48 49 // 50 // Constants 51 // 52 53 /** Character flags. */ 54 private static final byte[] CHARS = new byte[1 << 16]; 55 56 /** Valid character mask. */ 57 public static final int MASK_VALID = 0x01; 58 59 /** Space character mask. */ 60 public static final int MASK_SPACE = 0x02; 61 62 /** Name start character mask. */ 63 public static final int MASK_NAME_START = 0x04; 64 65 /** Name character mask. */ 66 public static final int MASK_NAME = 0x08; 67 68 /** Pubid character mask. */ 69 public static final int MASK_PUBID = 0x10; 70 71 /** 72 * Content character mask. Special characters are those that can 73 * be considered the start of markup, such as '<' and '&'. 74 * The various newline characters are considered special as well. 75 * All other valid XML characters can be considered content. 76 * <p> 77 * This is an optimization for the inner loop of character scanning. 78 */ 79 public static final int MASK_CONTENT = 0x20; 80 81 /** NCName start character mask. */ 82 public static final int MASK_NCNAME_START = 0x40; 83 84 /** NCName character mask. */ 85 public static final int MASK_NCNAME = 0x80; 86 87 // 88 // Static initialization 89 // 90 91 static { 92 93 // 94 // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | 95 // [#xE000-#xFFFD] | [#x10000-#x10FFFF] 96 // 97 98 int charRange[] = { 99 0x0009, 0x000A, 0x000D, 0x000D, 0x0020, 0xD7FF, 0xE000, 0xFFFD, 100 }; 101 102 // 103 // [3] S ::= (#x20 | #x9 | #xD | #xA)+ 104 // 105 106 int spaceChar[] = { 107 0x0020, 0x0009, 0x000D, 0x000A, 108 }; 109 110 // 111 // [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | 112 // CombiningChar | Extender 113 // 114 115 int nameChar[] = { 116 0x002D, 0x002E, // '-' and '.' 117 }; 118 119 // 120 // [5] Name ::= (Letter | '_' | ':') (NameChar)* 121 // 122 123 int nameStartChar[] = { 124 0x003A, 0x005F, // ':' and '_' 125 }; 126 127 // 128 // [13] PubidChar ::= #x20 | 0xD | 0xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] 129 // 130 131 int pubidChar[] = { 132 0x000A, 0x000D, 0x0020, 0x0021, 0x0023, 0x0024, 0x0025, 0x003D, 133 0x005F 134 }; 135 136 int pubidRange[] = { 137 0x0027, 0x003B, 0x003F, 0x005A, 0x0061, 0x007A 138 }; 139 140 // 141 // [84] Letter ::= BaseChar | Ideographic 142 // 143 144 int letterRange[] = { 145 // BaseChar 146 0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6, 0x00D8, 0x00F6, 147 0x00F8, 0x0131, 0x0134, 0x013E, 0x0141, 0x0148, 0x014A, 0x017E, 148 0x0180, 0x01C3, 0x01CD, 0x01F0, 0x01F4, 0x01F5, 0x01FA, 0x0217, 149 0x0250, 0x02A8, 0x02BB, 0x02C1, 0x0388, 0x038A, 0x038E, 0x03A1, 150 0x03A3, 0x03CE, 0x03D0, 0x03D6, 0x03E2, 0x03F3, 0x0401, 0x040C, 151 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 0x0490, 0x04C4, 152 0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5, 153 0x04F8, 0x04F9, 0x0531, 0x0556, 0x0561, 0x0586, 0x05D0, 0x05EA, 154 0x05F0, 0x05F2, 0x0621, 0x063A, 0x0641, 0x064A, 0x0671, 0x06B7, 155 0x06BA, 0x06BE, 0x06C0, 0x06CE, 0x06D0, 0x06D3, 0x06E5, 0x06E6, 156 0x0905, 0x0939, 0x0958, 0x0961, 0x0985, 0x098C, 0x098F, 0x0990, 157 0x0993, 0x09A8, 0x09AA, 0x09B0, 0x09B6, 0x09B9, 0x09DC, 0x09DD, 158 0x09DF, 0x09E1, 0x09F0, 0x09F1, 0x0A05, 0x0A0A, 0x0A0F, 0x0A10, 159 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36, 160 0x0A38, 0x0A39, 0x0A59, 0x0A5C, 0x0A72, 0x0A74, 0x0A85, 0x0A8B, 161 0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 162 0x0AB5, 0x0AB9, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, 163 0x0B2A, 0x0B30, 0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B5C, 0x0B5D, 164 0x0B5F, 0x0B61, 0x0B85, 0x0B8A, 0x0B8E, 0x0B90, 0x0B92, 0x0B95, 165 0x0B99, 0x0B9A, 0x0B9E, 0x0B9F, 0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA, 166 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10, 167 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C60, 0x0C61, 168 0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3, 169 0x0CB5, 0x0CB9, 0x0CE0, 0x0CE1, 0x0D05, 0x0D0C, 0x0D0E, 0x0D10, 170 0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D60, 0x0D61, 0x0E01, 0x0E2E, 171 0x0E32, 0x0E33, 0x0E40, 0x0E45, 0x0E81, 0x0E82, 0x0E87, 0x0E88, 172 0x0E94, 0x0E97, 0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EAA, 0x0EAB, 173 0x0EAD, 0x0EAE, 0x0EB2, 0x0EB3, 0x0EC0, 0x0EC4, 0x0F40, 0x0F47, 174 0x0F49, 0x0F69, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1102, 0x1103, 175 0x1105, 0x1107, 0x110B, 0x110C, 0x110E, 0x1112, 0x1154, 0x1155, 176 0x115F, 0x1161, 0x116D, 0x116E, 0x1172, 0x1173, 0x11AE, 0x11AF, 177 0x11B7, 0x11B8, 0x11BC, 0x11C2, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9, 178 0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, 179 0x1F50, 0x1F57, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 0x1FB6, 0x1FBC, 180 0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 0x1FD6, 0x1FDB, 181 0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x212A, 0x212B, 182 0x2180, 0x2182, 0x3041, 0x3094, 0x30A1, 0x30FA, 0x3105, 0x312C, 183 0xAC00, 0xD7A3, 184 // Ideographic 185 0x3021, 0x3029, 0x4E00, 0x9FA5, 186 }; 187 int letterChar[] = { 188 // BaseChar 189 0x0386, 0x038C, 0x03DA, 0x03DC, 0x03DE, 0x03E0, 0x0559, 0x06D5, 190 0x093D, 0x09B2, 0x0A5E, 0x0A8D, 0x0ABD, 0x0AE0, 0x0B3D, 0x0B9C, 191 0x0CDE, 0x0E30, 0x0E84, 0x0E8A, 0x0E8D, 0x0EA5, 0x0EA7, 0x0EB0, 192 0x0EBD, 0x1100, 0x1109, 0x113C, 0x113E, 0x1140, 0x114C, 0x114E, 193 0x1150, 0x1159, 0x1163, 0x1165, 0x1167, 0x1169, 0x1175, 0x119E, 194 0x11A8, 0x11AB, 0x11BA, 0x11EB, 0x11F0, 0x11F9, 0x1F59, 0x1F5B, 195 0x1F5D, 0x1FBE, 0x2126, 0x212E, 196 // Ideographic 197 0x3007, 198 }; 199 200 // 201 // [87] CombiningChar ::= ... 202 // 203 204 int combiningCharRange[] = { 205 0x0300, 0x0345, 0x0360, 0x0361, 0x0483, 0x0486, 0x0591, 0x05A1, 206 0x05A3, 0x05B9, 0x05BB, 0x05BD, 0x05C1, 0x05C2, 0x064B, 0x0652, 207 0x06D6, 0x06DC, 0x06DD, 0x06DF, 0x06E0, 0x06E4, 0x06E7, 0x06E8, 208 0x06EA, 0x06ED, 0x0901, 0x0903, 0x093E, 0x094C, 0x0951, 0x0954, 209 0x0962, 0x0963, 0x0981, 0x0983, 0x09C0, 0x09C4, 0x09C7, 0x09C8, 210 0x09CB, 0x09CD, 0x09E2, 0x09E3, 0x0A40, 0x0A42, 0x0A47, 0x0A48, 211 0x0A4B, 0x0A4D, 0x0A70, 0x0A71, 0x0A81, 0x0A83, 0x0ABE, 0x0AC5, 212 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0B01, 0x0B03, 0x0B3E, 0x0B43, 213 0x0B47, 0x0B48, 0x0B4B, 0x0B4D, 0x0B56, 0x0B57, 0x0B82, 0x0B83, 214 0x0BBE, 0x0BC2, 0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD, 0x0C01, 0x0C03, 215 0x0C3E, 0x0C44, 0x0C46, 0x0C48, 0x0C4A, 0x0C4D, 0x0C55, 0x0C56, 216 0x0C82, 0x0C83, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8, 0x0CCA, 0x0CCD, 217 0x0CD5, 0x0CD6, 0x0D02, 0x0D03, 0x0D3E, 0x0D43, 0x0D46, 0x0D48, 218 0x0D4A, 0x0D4D, 0x0E34, 0x0E3A, 0x0E47, 0x0E4E, 0x0EB4, 0x0EB9, 219 0x0EBB, 0x0EBC, 0x0EC8, 0x0ECD, 0x0F18, 0x0F19, 0x0F71, 0x0F84, 220 0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F99, 0x0FAD, 0x0FB1, 0x0FB7, 221 0x20D0, 0x20DC, 0x302A, 0x302F, 222 }; 223 224 int combiningCharChar[] = { 225 0x05BF, 0x05C4, 0x0670, 0x093C, 0x094D, 0x09BC, 0x09BE, 0x09BF, 226 0x09D7, 0x0A02, 0x0A3C, 0x0A3E, 0x0A3F, 0x0ABC, 0x0B3C, 0x0BD7, 227 0x0D57, 0x0E31, 0x0EB1, 0x0F35, 0x0F37, 0x0F39, 0x0F3E, 0x0F3F, 228 0x0F97, 0x0FB9, 0x20E1, 0x3099, 0x309A, 229 }; 230 231 // 232 // [88] Digit ::= ... 233 // 234 235 int digitRange[] = { 236 0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F, 237 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F, 238 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F, 239 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29, 240 }; 241 242 // 243 // [89] Extender ::= ... 244 // 245 246 int extenderRange[] = { 247 0x3031, 0x3035, 0x309D, 0x309E, 0x30FC, 0x30FE, 248 }; 249 250 int extenderChar[] = { 251 0x00B7, 0x02D0, 0x02D1, 0x0387, 0x0640, 0x0E46, 0x0EC6, 0x3005, 252 }; 253 254 // 255 // SpecialChar ::= '<', '&', '\n', '\r', ']' 256 // 257 258 int specialChar[] = { 259 '<', '&', '\n', '\r', ']', 260 }; 261 262 // 263 // Initialize 264 // 265 266 // set valid characters 267 for (int i = 0; i < charRange.length; i += 2) { 268 for (int j = charRange[i]; j <= charRange[i + 1]; j++) { 269 CHARS[j] |= MASK_VALID | MASK_CONTENT; 270 } 271 } 272 273 // remove special characters 274 for (int i = 0; i < specialChar.length; i++) { 275 CHARS[specialChar[i]] = (byte)(CHARS[specialChar[i]] & ~MASK_CONTENT); 276 } 277 278 // set space characters 279 for (int i = 0; i < spaceChar.length; i++) { 280 CHARS[spaceChar[i]] |= MASK_SPACE; 281 } 282 283 // set name start characters 284 for (int i = 0; i < nameStartChar.length; i++) { 285 CHARS[nameStartChar[i]] |= MASK_NAME_START | MASK_NAME | 286 MASK_NCNAME_START | MASK_NCNAME; 287 } 288 for (int i = 0; i < letterRange.length; i += 2) { 289 for (int j = letterRange[i]; j <= letterRange[i + 1]; j++) { 290 CHARS[j] |= MASK_NAME_START | MASK_NAME | 291 MASK_NCNAME_START | MASK_NCNAME; 292 } 293 } 294 for (int i = 0; i < letterChar.length; i++) { 295 CHARS[letterChar[i]] |= MASK_NAME_START | MASK_NAME | 296 MASK_NCNAME_START | MASK_NCNAME; 297 } 298 299 // set name characters 300 for (int i = 0; i < nameChar.length; i++) { 301 CHARS[nameChar[i]] |= MASK_NAME | MASK_NCNAME; 302 } 303 for (int i = 0; i < digitRange.length; i += 2) { 304 for (int j = digitRange[i]; j <= digitRange[i + 1]; j++) { 305 CHARS[j] |= MASK_NAME | MASK_NCNAME; 306 } 307 } 308 for (int i = 0; i < combiningCharRange.length; i += 2) { 309 for (int j = combiningCharRange[i]; j <= combiningCharRange[i + 1]; j++) { 310 CHARS[j] |= MASK_NAME | MASK_NCNAME; 311 } 312 } 313 for (int i = 0; i < combiningCharChar.length; i++) { 314 CHARS[combiningCharChar[i]] |= MASK_NAME | MASK_NCNAME; 315 } 316 for (int i = 0; i < extenderRange.length; i += 2) { 317 for (int j = extenderRange[i]; j <= extenderRange[i + 1]; j++) { 318 CHARS[j] |= MASK_NAME | MASK_NCNAME; 319 } 320 } 321 for (int i = 0; i < extenderChar.length; i++) { 322 CHARS[extenderChar[i]] |= MASK_NAME | MASK_NCNAME; 323 } 324 325 // remove ':' from allowable MASK_NCNAME_START and MASK_NCNAME chars 326 CHARS[':'] &= ~(MASK_NCNAME_START | MASK_NCNAME); 327 328 // set Pubid characters 329 for (int i = 0; i < pubidChar.length; i++) { 330 CHARS[pubidChar[i]] |= MASK_PUBID; 331 } 332 for (int i = 0; i < pubidRange.length; i += 2) { 333 for (int j = pubidRange[i]; j <= pubidRange[i + 1]; j++) { 334 CHARS[j] |= MASK_PUBID; 335 } 336 } 337 338 } // <clinit>() 339 340 // 341 // Public static methods 342 // 343 344 /** 345 * Returns true if the specified character is a supplemental character. 346 * 347 * @param c The character to check. 348 */ isSupplemental(int c)349 public static boolean isSupplemental(int c) { 350 return (c >= 0x10000 && c <= 0x10FFFF); 351 } 352 353 /** 354 * Returns true the supplemental character corresponding to the given 355 * surrogates. 356 * 357 * @param h The high surrogate. 358 * @param l The low surrogate. 359 */ supplemental(char h, char l)360 public static int supplemental(char h, char l) { 361 return (h - 0xD800) * 0x400 + (l - 0xDC00) + 0x10000; 362 } 363 364 /** 365 * Returns the high surrogate of a supplemental character 366 * 367 * @param c The supplemental character to "split". 368 */ highSurrogate(int c)369 public static char highSurrogate(int c) { 370 return (char) (((c - 0x00010000) >> 10) + 0xD800); 371 } 372 373 /** 374 * Returns the low surrogate of a supplemental character 375 * 376 * @param c The supplemental character to "split". 377 */ lowSurrogate(int c)378 public static char lowSurrogate(int c) { 379 return (char) (((c - 0x00010000) & 0x3FF) + 0xDC00); 380 } 381 382 /** 383 * Returns whether the given character is a high surrogate 384 * 385 * @param c The character to check. 386 */ isHighSurrogate(int c)387 public static boolean isHighSurrogate(int c) { 388 return (0xD800 <= c && c <= 0xDBFF); 389 } 390 391 /** 392 * Returns whether the given character is a low surrogate 393 * 394 * @param c The character to check. 395 */ isLowSurrogate(int c)396 public static boolean isLowSurrogate(int c) { 397 return (0xDC00 <= c && c <= 0xDFFF); 398 } 399 400 401 /** 402 * Returns true if the specified character is valid. This method 403 * also checks the surrogate character range from 0x10000 to 0x10FFFF. 404 * <p> 405 * If the program chooses to apply the mask directly to the 406 * <code>CHARS</code> array, then they are responsible for checking 407 * the surrogate character range. 408 * 409 * @param c The character to check. 410 */ isValid(int c)411 public static boolean isValid(int c) { 412 return (c < 0x10000 && (CHARS[c] & MASK_VALID) != 0) || 413 (0x10000 <= c && c <= 0x10FFFF); 414 } // isValid(int):boolean 415 416 /** 417 * Returns true if the specified character is invalid. 418 * 419 * @param c The character to check. 420 */ isInvalid(int c)421 public static boolean isInvalid(int c) { 422 return !isValid(c); 423 } // isInvalid(int):boolean 424 425 /** 426 * Returns true if the specified character can be considered content. 427 * 428 * @param c The character to check. 429 */ isContent(int c)430 public static boolean isContent(int c) { 431 return (c < 0x10000 && (CHARS[c] & MASK_CONTENT) != 0) || 432 (0x10000 <= c && c <= 0x10FFFF); 433 } // isContent(int):boolean 434 435 /** 436 * Returns true if the specified character can be considered markup. 437 * Markup characters include '<', '&', and '%'. 438 * 439 * @param c The character to check. 440 */ isMarkup(int c)441 public static boolean isMarkup(int c) { 442 return c == '<' || c == '&' || c == '%'; 443 } // isMarkup(int):boolean 444 445 /** 446 * Returns true if the specified character is a space character 447 * as defined by production [3] in the XML 1.0 specification. 448 * 449 * @param c The character to check. 450 */ isSpace(int c)451 public static boolean isSpace(int c) { 452 return c < 0x10000 && (CHARS[c] & MASK_SPACE) != 0; 453 } // isSpace(int):boolean 454 455 /** 456 * Returns true if the specified character is a valid name start 457 * character as defined by production [5] in the XML 1.0 458 * specification. 459 * 460 * @param c The character to check. 461 */ isNameStart(int c)462 public static boolean isNameStart(int c) { 463 return c < 0x10000 && (CHARS[c] & MASK_NAME_START) != 0; 464 } // isNameStart(int):boolean 465 466 /** 467 * Returns true if the specified character is a valid name 468 * character as defined by production [4] in the XML 1.0 469 * specification. 470 * 471 * @param c The character to check. 472 */ isName(int c)473 public static boolean isName(int c) { 474 return c < 0x10000 && (CHARS[c] & MASK_NAME) != 0; 475 } // isName(int):boolean 476 477 /** 478 * Returns true if the specified character is a valid NCName start 479 * character as defined by production [4] in Namespaces in XML 480 * recommendation. 481 * 482 * @param c The character to check. 483 */ isNCNameStart(int c)484 public static boolean isNCNameStart(int c) { 485 return c < 0x10000 && (CHARS[c] & MASK_NCNAME_START) != 0; 486 } // isNCNameStart(int):boolean 487 488 /** 489 * Returns true if the specified character is a valid NCName 490 * character as defined by production [5] in Namespaces in XML 491 * recommendation. 492 * 493 * @param c The character to check. 494 */ isNCName(int c)495 public static boolean isNCName(int c) { 496 return c < 0x10000 && (CHARS[c] & MASK_NCNAME) != 0; 497 } // isNCName(int):boolean 498 499 /** 500 * Returns true if the specified character is a valid Pubid 501 * character as defined by production [13] in the XML 1.0 502 * specification. 503 * 504 * @param c The character to check. 505 */ isPubid(int c)506 public static boolean isPubid(int c) { 507 return c < 0x10000 && (CHARS[c] & MASK_PUBID) != 0; 508 } // isPubid(int):boolean 509 510 /* 511 * [5] Name ::= (Letter | '_' | ':') (NameChar)* 512 */ 513 /** 514 * Check to see if a string is a valid Name according to [5] 515 * in the XML 1.0 Recommendation 516 * 517 * @param name string to check 518 * @return true if name is a valid Name 519 */ isValidName(String name)520 public static boolean isValidName(String name) { 521 if (name.length() == 0) 522 return false; 523 char ch = name.charAt(0); 524 if( isNameStart(ch) == false) 525 return false; 526 for (int i = 1; i < name.length(); i++ ) { 527 ch = name.charAt(i); 528 if( isName( ch ) == false ){ 529 return false; 530 } 531 } 532 return true; 533 } // isValidName(String):boolean 534 535 536 /* 537 * from the namespace rec 538 * [4] NCName ::= (Letter | '_') (NCNameChar)* 539 */ 540 /** 541 * Check to see if a string is a valid NCName according to [4] 542 * from the XML Namespaces 1.0 Recommendation 543 * 544 * @param ncName string to check 545 * @return true if name is a valid NCName 546 */ isValidNCName(String ncName)547 public static boolean isValidNCName(String ncName) { 548 if (ncName.length() == 0) 549 return false; 550 char ch = ncName.charAt(0); 551 if( isNCNameStart(ch) == false) 552 return false; 553 for (int i = 1; i < ncName.length(); i++ ) { 554 ch = ncName.charAt(i); 555 if( isNCName( ch ) == false ){ 556 return false; 557 } 558 } 559 return true; 560 } // isValidNCName(String):boolean 561 562 /* 563 * [7] Nmtoken ::= (NameChar)+ 564 */ 565 /** 566 * Check to see if a string is a valid Nmtoken according to [7] 567 * in the XML 1.0 Recommendation 568 * 569 * @param nmtoken string to check 570 * @return true if nmtoken is a valid Nmtoken 571 */ isValidNmtoken(String nmtoken)572 public static boolean isValidNmtoken(String nmtoken) { 573 if (nmtoken.length() == 0) 574 return false; 575 for (int i = 0; i < nmtoken.length(); i++ ) { 576 char ch = nmtoken.charAt(i); 577 if( ! isName( ch ) ){ 578 return false; 579 } 580 } 581 return true; 582 } // isValidName(String):boolean 583 584 585 586 587 588 // encodings 589 590 /** 591 * Returns true if the encoding name is a valid IANA encoding. 592 * This method does not verify that there is a decoder available 593 * for this encoding, only that the characters are valid for an 594 * IANA encoding name. 595 * 596 * @param ianaEncoding The IANA encoding name. 597 */ isValidIANAEncoding(String ianaEncoding)598 public static boolean isValidIANAEncoding(String ianaEncoding) { 599 if (ianaEncoding != null) { 600 int length = ianaEncoding.length(); 601 if (length > 0) { 602 char c = ianaEncoding.charAt(0); 603 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { 604 for (int i = 1; i < length; i++) { 605 c = ianaEncoding.charAt(i); 606 if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && 607 (c < '0' || c > '9') && c != '.' && c != '_' && 608 c != '-') { 609 return false; 610 } 611 } 612 return true; 613 } 614 } 615 } 616 return false; 617 } // isValidIANAEncoding(String):boolean 618 619 /** 620 * Returns true if the encoding name is a valid Java encoding. 621 * This method does not verify that there is a decoder available 622 * for this encoding, only that the characters are valid for an 623 * Java encoding name. 624 * 625 * @param javaEncoding The Java encoding name. 626 */ isValidJavaEncoding(String javaEncoding)627 public static boolean isValidJavaEncoding(String javaEncoding) { 628 if (javaEncoding != null) { 629 int length = javaEncoding.length(); 630 if (length > 0) { 631 for (int i = 1; i < length; i++) { 632 char c = javaEncoding.charAt(i); 633 if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && 634 (c < '0' || c > '9') && c != '.' && c != '_' && 635 c != '-') { 636 return false; 637 } 638 } 639 return true; 640 } 641 } 642 return false; 643 } // isValidIANAEncoding(String):boolean 644 645 /** 646 * Simple check to determine if qname is legal. If it returns false 647 * then <param>str</param> is illegal; if it returns true then 648 * <param>str</param> is legal. 649 */ isValidQName(String str)650 public static boolean isValidQName(String str) { 651 652 final int colon = str.indexOf(':'); 653 654 if (colon == 0 || colon == str.length() - 1) { 655 return false; 656 } 657 658 if (colon > 0) { 659 final String prefix = str.substring(0,colon); 660 final String localPart = str.substring(colon+1); 661 return isValidNCName(prefix) && isValidNCName(localPart); 662 } 663 else { 664 return isValidNCName(str); 665 } 666 } 667 668 } // class XMLChar 669