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