001: /*
002: * Copyright 2002-2008 Andy Clark
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.cyberneko.html;
018:
019: /**
020: * Collection of HTML element information.
021: *
022: * @author Andy Clark
023: * @author Ahmed Ashour
024: *
025: * @version $Id: HTMLElements.java,v 1.12 2005/02/14 07:16:59 andyc Exp $
026: */
027: public class HTMLElements {
028:
029: //
030: // Constants
031: //
032:
033: // element codes
034:
035: // NOTE: The element codes *must* start with 0 and increment in
036: // sequence. The parent and closes references depends on
037: // this assumption. -Ac
038:
039: public static final short A = 0;
040: public static final short ABBR = A + 1;
041: public static final short ACRONYM = ABBR + 1;
042: public static final short ADDRESS = ACRONYM + 1;
043: public static final short APPLET = ADDRESS + 1;
044: public static final short AREA = APPLET + 1;
045: public static final short B = AREA + 1;
046: public static final short BASE = B + 1;
047: public static final short BASEFONT = BASE + 1;
048: public static final short BDO = BASEFONT + 1;
049: public static final short BGSOUND = BDO + 1;
050: public static final short BIG = BGSOUND + 1;
051: public static final short BLINK = BIG + 1;
052: public static final short BLOCKQUOTE = BLINK + 1;
053: public static final short BODY = BLOCKQUOTE + 1;
054: public static final short BR = BODY + 1;
055: public static final short BUTTON = BR + 1;
056: public static final short CAPTION = BUTTON + 1;
057: public static final short CENTER = CAPTION + 1;
058: public static final short CITE = CENTER + 1;
059: public static final short CODE = CITE + 1;
060: public static final short COL = CODE + 1;
061: public static final short COLGROUP = COL + 1;
062: public static final short COMMENT = COLGROUP + 1;
063: public static final short DEL = COMMENT + 1;
064: public static final short DFN = DEL + 1;
065: public static final short DIR = DFN + 1;
066: public static final short DIV = DIR + 1;
067: public static final short DD = DIV + 1;
068: public static final short DL = DD + 1;
069: public static final short DT = DL + 1;
070: public static final short EM = DT + 1;
071: public static final short EMBED = EM + 1;
072: public static final short FIELDSET = EMBED + 1;
073: public static final short FONT = FIELDSET + 1;
074: public static final short FORM = FONT + 1;
075: public static final short FRAME = FORM + 1;
076: public static final short FRAMESET = FRAME + 1;
077: public static final short H1 = FRAMESET + 1;
078: public static final short H2 = H1 + 1;
079: public static final short H3 = H2 + 1;
080: public static final short H4 = H3 + 1;
081: public static final short H5 = H4 + 1;
082: public static final short H6 = H5 + 1;
083: public static final short HEAD = H6 + 1;
084: public static final short HR = HEAD + 1;
085: public static final short HTML = HR + 1;
086: public static final short I = HTML + 1;
087: public static final short IFRAME = I + 1;
088: public static final short ILAYER = IFRAME + 1;
089: public static final short IMG = ILAYER + 1;
090: public static final short INPUT = IMG + 1;
091: public static final short INS = INPUT + 1;
092: public static final short ISINDEX = INS + 1;
093: public static final short KBD = ISINDEX + 1;
094: public static final short KEYGEN = KBD + 1;
095: public static final short LABEL = KEYGEN + 1;
096: public static final short LAYER = LABEL + 1;
097: public static final short LEGEND = LAYER + 1;
098: public static final short LI = LEGEND + 1;
099: public static final short LINK = LI + 1;
100: public static final short LISTING = LINK + 1;
101: public static final short MAP = LISTING + 1;
102: public static final short MARQUEE = MAP + 1;
103: public static final short MENU = MARQUEE + 1;
104: public static final short META = MENU + 1;
105: public static final short MULTICOL = META + 1;
106: public static final short NEXTID = MULTICOL + 1;
107: public static final short NOBR = NEXTID + 1;
108: public static final short NOEMBED = NOBR + 1;
109: public static final short NOFRAMES = NOEMBED + 1;
110: public static final short NOLAYER = NOFRAMES + 1;
111: public static final short NOSCRIPT = NOLAYER + 1;
112: public static final short OBJECT = NOSCRIPT + 1;
113: public static final short OL = OBJECT + 1;
114: public static final short OPTION = OL + 1;
115: public static final short OPTGROUP = OPTION + 1;
116: public static final short P = OPTGROUP + 1;
117: public static final short PARAM = P + 1;
118: public static final short PLAINTEXT = PARAM + 1;
119: public static final short PRE = PLAINTEXT + 1;
120: public static final short Q = PRE + 1;
121: public static final short RB = Q + 1;
122: public static final short RBC = RB + 1;
123: public static final short RP = RBC + 1;
124: public static final short RT = RP + 1;
125: public static final short RTC = RT + 1;
126: public static final short RUBY = RTC + 1;
127: public static final short S = RUBY + 1;
128: public static final short SAMP = S + 1;
129: public static final short SCRIPT = SAMP + 1;
130: public static final short SELECT = SCRIPT + 1;
131: public static final short SMALL = SELECT + 1;
132: public static final short SOUND = SMALL + 1;
133: public static final short SPACER = SOUND + 1;
134: public static final short SPAN = SPACER + 1;
135: public static final short STRIKE = SPAN + 1;
136: public static final short STRONG = STRIKE + 1;
137: public static final short STYLE = STRONG + 1;
138: public static final short SUB = STYLE + 1;
139: public static final short SUP = SUB + 1;
140: public static final short TABLE = SUP + 1;
141: public static final short TBODY = TABLE + 1;
142: public static final short TD = TBODY + 1;
143: public static final short TEXTAREA = TD + 1;
144: public static final short TFOOT = TEXTAREA + 1;
145: public static final short TH = TFOOT + 1;
146: public static final short THEAD = TH + 1;
147: public static final short TITLE = THEAD + 1;
148: public static final short TR = TITLE + 1;
149: public static final short TT = TR + 1;
150: public static final short U = TT + 1;
151: public static final short UL = U + 1;
152: public static final short VAR = UL + 1;
153: public static final short WBR = VAR + 1;
154: public static final short XML = WBR + 1;
155: public static final short XMP = XML + 1;
156: public static final short UNKNOWN = XMP + 1;
157:
158: // information
159:
160: /** Element information organized by first letter. */
161: protected static final Element[][] ELEMENTS_ARRAY = new Element[26][];
162:
163: /** Element information as a contiguous list. */
164: protected static final ElementList ELEMENTS = new ElementList();
165:
166: /** No such element. */
167: public static final Element NO_SUCH_ELEMENT = new Element(UNKNOWN,
168: "", 0, new short[] { HEAD, BODY }/*HTML*/, null);
169:
170: //
171: // Static initializer
172: //
173:
174: /**
175: * Initializes the element information.
176: * <p>
177: * <strong>Note:</strong>
178: * The <code>getElement</code> method requires that the HTML elements
179: * are added to the list in alphabetical order. If new elements are
180: * added, then they <em>must</em> be inserted in alphabetical order.
181: */
182: static {
183: // <!ENTITY % heading "H1|H2|H3|H4|H5|H6">
184: // <!ENTITY % fontstyle "TT | I | B | BIG | SMALL">
185: // <!ENTITY % phrase "EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >
186: // <!ENTITY % special "A | IMG | OBJECT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO">
187: // <!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">
188: // <!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">
189: // <!ENTITY % block "P | %heading; | %list; | %preformatted; | DL | DIV | NOSCRIPT | BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS">
190: // <!ENTITY % flow "%block; | %inline;">
191:
192: // initialize array of element information
193: ELEMENTS_ARRAY['A' - 'A'] = new Element[] {
194: // A - - (%inline;)* -(A)
195: new Element(A, "A", Element.INLINE, BODY, null),
196: // ABBR - - (%inline;)*
197: new Element(ABBR, "ABBR", Element.INLINE, BODY, null),
198: // ACRONYM - - (%inline;)*
199: new Element(ACRONYM, "ACRONYM", Element.INLINE, BODY,
200: null),
201: // ADDRESS - - (%inline;)*
202: new Element(ADDRESS, "ADDRESS", Element.BLOCK, BODY,
203: null),
204: // APPLET
205: new Element(APPLET, "APPLET", 0, BODY, null),
206: // AREA - O EMPTY
207: new Element(AREA, "AREA", Element.EMPTY, MAP, null), };
208: ELEMENTS_ARRAY['B' - 'A'] = new Element[] {
209: // B - - (%inline;)*
210: new Element(B, "B", Element.INLINE, BODY, null),
211: // BASE - O EMPTY
212: new Element(BASE, "BASE", Element.EMPTY, HEAD, null),
213: // BASEFONT
214: new Element(BASEFONT, "BASEFONT", 0, HEAD, null),
215: // BDO - - (%inline;)*
216: new Element(BDO, "BDO", Element.INLINE, BODY, null),
217: // BGSOUND
218: new Element(BGSOUND, "BGSOUND", Element.EMPTY, HEAD,
219: null),
220: // BIG - - (%inline;)*
221: new Element(BIG, "BIG", Element.INLINE, BODY, null),
222: // BLINK
223: new Element(BLINK, "BLINK", Element.INLINE, BODY, null),
224: // BLOCKQUOTE - - (%block;|SCRIPT)+
225: new Element(BLOCKQUOTE, "BLOCKQUOTE", Element.BLOCK,
226: BODY, new short[] { P }),
227: // BODY O O (%block;|SCRIPT)+ +(INS|DEL)
228: new Element(BODY, "BODY", 0, HTML, new short[] { HEAD }),
229: // BR - O EMPTY
230: new Element(BR, "BR", Element.EMPTY, BODY, null),
231: // BUTTON - - (%flow;)* -(A|%formctrl;|FORM|FIELDSET)
232: new Element(BUTTON, "BUTTON", 0, BODY, null), };
233: ELEMENTS_ARRAY['C' - 'A'] = new Element[] {
234: // CAPTION - - (%inline;)*
235: new Element(CAPTION, "CAPTION", Element.INLINE, TABLE,
236: null),
237: // CENTER,
238: new Element(CENTER, "CENTER", 0, BODY, null),
239: // CITE - - (%inline;)*
240: new Element(CITE, "CITE", Element.INLINE, BODY, null),
241: // CODE - - (%inline;)*
242: new Element(CODE, "CODE", Element.INLINE, BODY, null),
243: // COL - O EMPTY
244: new Element(COL, "COL", Element.EMPTY, TABLE, null),
245: // COLGROUP - O (COL)*
246: new Element(COLGROUP, "COLGROUP", 0, TABLE,
247: new short[] { COL, COLGROUP }),
248: // COMMENT
249: new Element(COMMENT, "COMMENT", Element.SPECIAL, HTML,
250: null), };
251: ELEMENTS_ARRAY['D' - 'A'] = new Element[] {
252: // DEL - - (%flow;)*
253: new Element(DEL, "DEL", 0, BODY, null),
254: // DFN - - (%inline;)*
255: new Element(DFN, "DFN", Element.INLINE, BODY, null),
256: // DIR
257: new Element(DIR, "DIR", 0, BODY, null),
258: // DIV - - (%flow;)*
259: new Element(DIV, "DIV", Element.BLOCK, BODY,
260: new short[] { P }),
261: // DD - O (%flow;)*
262: new Element(DD, "DD", 0, DL, new short[] { DT, DD }),
263: // DL - - (DT|DD)+
264: new Element(DL, "DL", Element.BLOCK, BODY, null),
265: // DT - O (%inline;)*
266: new Element(DT, "DT", 0, DL, new short[] { DT, DD }), };
267: ELEMENTS_ARRAY['E' - 'A'] = new Element[] {
268: // EM - - (%inline;)*
269: new Element(EM, "EM", Element.INLINE, BODY, null),
270: // EMBED
271: new Element(EMBED, "EMBED", 0, BODY, null), };
272: ELEMENTS_ARRAY['F' - 'A'] = new Element[] {
273: // FIELDSET - - (#PCDATA,LEGEND,(%flow;)*)
274: new Element(FIELDSET, "FIELDSET", 0, BODY, null),
275: // FONT
276: new Element(FONT, "FONT", Element.CONTAINER, BODY, null),
277: // FORM - - (%block;|SCRIPT)+ -(FORM)
278: new Element(FORM, "FORM", Element.CONTAINER,
279: new short[] { BODY, TD, P, DIV },
280: new short[] { BUTTON }),
281: // FRAME - O EMPTY
282: new Element(FRAME, "FRAME", Element.EMPTY, FRAMESET,
283: null),
284: // FRAMESET - - ((FRAMESET|FRAME)+ & NOFRAMES?)
285: new Element(FRAMESET, "FRAMESET", 0, HTML, null), };
286: ELEMENTS_ARRAY['H' - 'A'] = new Element[] {
287: // (H1|H2|H3|H4|H5|H6) - - (%inline;)*
288: new Element(H1, "H1", Element.BLOCK, new short[] {
289: BODY, A }, new short[] { H1, H2, H3, H4, H5,
290: H6, P }),
291: new Element(H2, "H2", Element.BLOCK, new short[] {
292: BODY, A }, new short[] { H1, H2, H3, H4, H5,
293: H6, P }),
294: new Element(H3, "H3", Element.BLOCK, new short[] {
295: BODY, A }, new short[] { H1, H2, H3, H4, H5,
296: H6, P }),
297: new Element(H4, "H4", Element.BLOCK, new short[] {
298: BODY, A }, new short[] { H1, H2, H3, H4, H5,
299: H6, P }),
300: new Element(H5, "H5", Element.BLOCK, new short[] {
301: BODY, A }, new short[] { H1, H2, H3, H4, H5,
302: H6, P }),
303: new Element(H6, "H6", Element.BLOCK, new short[] {
304: BODY, A }, new short[] { H1, H2, H3, H4, H5,
305: H6, P }),
306: // HEAD O O (%head.content;) +(%head.misc;)
307: new Element(HEAD, "HEAD", 0, HTML, null),
308: // HR - O EMPTY
309: new Element(HR, "HR", Element.EMPTY, BODY,
310: new short[] { P }),
311: // HTML O O (%html.content;)
312: new Element(HTML, "HTML", 0, null, null), };
313: ELEMENTS_ARRAY['I' - 'A'] = new Element[] {
314: // I - - (%inline;)*
315: new Element(I, "I", Element.INLINE, BODY, null),
316: // IFRAME
317: new Element(IFRAME, "IFRAME", Element.BLOCK, BODY, null),
318: // ILAYER
319: new Element(ILAYER, "ILAYER", Element.BLOCK, BODY, null),
320: // IMG - O EMPTY
321: new Element(IMG, "IMG", Element.EMPTY, BODY, null),
322: // INPUT - O EMPTY
323: new Element(INPUT, "INPUT", Element.EMPTY, BODY, null),
324: // INS - - (%flow;)*
325: new Element(INS, "INS", 0, BODY, null),
326: // ISINDEX
327: new Element(ISINDEX, "ISINDEX", 0, HEAD, null), };
328: ELEMENTS_ARRAY['K' - 'A'] = new Element[] {
329: // KBD - - (%inline;)*
330: new Element(KBD, "KBD", Element.INLINE, BODY, null),
331: // KEYGEN
332: new Element(KEYGEN, "KEYGEN", 0, BODY, null), };
333: ELEMENTS_ARRAY['L' - 'A'] = new Element[] {
334: // LABEL - - (%inline;)* -(LABEL)
335: new Element(LABEL, "LABEL", 0, BODY, null),
336: // LAYER
337: new Element(LAYER, "LAYER", Element.BLOCK, BODY, null),
338: // LEGEND - - (%inline;)*
339: new Element(LEGEND, "LEGEND", Element.INLINE, FIELDSET,
340: null),
341: // LI - O (%flow;)*
342: new Element(LI, "LI", 0, new short[] { BODY, UL, OL },
343: new short[] { LI }),
344: // LINK - O EMPTY
345: new Element(LINK, "LINK", Element.EMPTY, HEAD, null),
346: // LISTING
347: new Element(LISTING, "LISTING", 0, BODY, null), };
348: ELEMENTS_ARRAY['M' - 'A'] = new Element[] {
349: // MAP - - ((%block;) | AREA)+
350: new Element(MAP, "MAP", Element.INLINE, BODY, null),
351: // MARQUEE
352: new Element(MARQUEE, "MARQUEE", 0, BODY, null),
353: // MENU
354: new Element(MENU, "MENU", 0, BODY, null),
355: // META - O EMPTY
356: new Element(META, "META", Element.EMPTY, HEAD,
357: new short[] { STYLE, TITLE }),
358: // MULTICOL
359: new Element(MULTICOL, "MULTICOL", 0, BODY, null), };
360: ELEMENTS_ARRAY['N' - 'A'] = new Element[] {
361: // NEXTID
362: new Element(NEXTID, "NEXTID", Element.EMPTY, BODY, null),
363: // NOBR
364: new Element(NOBR, "NOBR", Element.INLINE, BODY, null),
365: // NOEMBED
366: new Element(NOEMBED, "NOEMBED", 0, BODY, null),
367: // NOFRAMES - - (BODY) -(NOFRAMES)
368: new Element(NOFRAMES, "NOFRAMES", 0, FRAMESET, null),
369: // NOLAYER
370: new Element(NOLAYER, "NOLAYER", 0, BODY, null),
371: // NOSCRIPT - - (%block;)+
372: new Element(NOSCRIPT, "NOSCRIPT", 0,
373: new short[] { BODY }, null), };
374: ELEMENTS_ARRAY['O' - 'A'] = new Element[] {
375: // OBJECT - - (PARAM | %flow;)*
376: new Element(OBJECT, "OBJECT", 0, BODY, null),
377: // OL - - (LI)+
378: new Element(OL, "OL", Element.BLOCK, BODY, null),
379: // OPTGROUP - - (OPTION)+
380: new Element(OPTGROUP, "OPTGROUP", 0, SELECT,
381: new short[] { OPTION }),
382: // OPTION - O (#PCDATA)
383: new Element(OPTION, "OPTION", 0, SELECT,
384: new short[] { OPTION }), };
385: ELEMENTS_ARRAY['P' - 'A'] = new Element[] {
386: // P - O (%inline;)*
387: new Element(P, "P", 0, BODY, new short[] { P }),
388: // PARAM - O EMPTY
389: new Element(PARAM, "PARAM", Element.EMPTY, new short[] {
390: OBJECT, APPLET }, null),
391: // PLAINTEXT
392: new Element(PLAINTEXT, "PLAINTEXT", Element.SPECIAL,
393: BODY, null),
394: // PRE - - (%inline;)* -(%pre.exclusion;)
395: new Element(PRE, "PRE", 0, BODY, null), };
396: ELEMENTS_ARRAY['Q' - 'A'] = new Element[] {
397: // Q - - (%inline;)*
398: new Element(Q, "Q", Element.INLINE, BODY, null), };
399: ELEMENTS_ARRAY['R' - 'A'] = new Element[] {
400: // RB
401: new Element(RB, "RB", Element.INLINE, RUBY,
402: new short[] { RB }),
403: // RBC
404: new Element(RBC, "RBC", 0, RUBY, null),
405: // RP
406: new Element(RP, "RP", Element.INLINE, RUBY,
407: new short[] { RB }),
408: // RT
409: new Element(RT, "RT", Element.INLINE, RUBY,
410: new short[] { RB, RP }),
411: // RTC
412: new Element(RTC, "RTC", 0, RUBY, new short[] { RBC }),
413: // RUBY
414: new Element(RUBY, "RUBY", 0, BODY, new short[] { RUBY }), };
415: ELEMENTS_ARRAY['S' - 'A'] = new Element[] {
416: // S
417: new Element(S, "S", 0, BODY, null),
418: // SAMP - - (%inline;)*
419: new Element(SAMP, "SAMP", Element.INLINE, BODY, null),
420: // SCRIPT - - %Script;
421: new Element(SCRIPT, "SCRIPT", Element.SPECIAL,
422: new short[] { HEAD, BODY }, null),
423: // SELECT - - (OPTGROUP|OPTION)+
424: new Element(SELECT, "SELECT", 0, BODY,
425: new short[] { SELECT }),
426: // SMALL - - (%inline;)*
427: new Element(SMALL, "SMALL", Element.INLINE, BODY, null),
428: // SOUND
429: new Element(SOUND, "SOUND", Element.EMPTY, HEAD, null),
430: // SPACER
431: new Element(SPACER, "SPACER", Element.EMPTY, BODY, null),
432: // SPAN - - (%inline;)*
433: new Element(SPAN, "SPAN", Element.CONTAINER, BODY, null),
434: // STRIKE
435: new Element(STRIKE, "STRIKE", Element.INLINE, BODY,
436: null),
437: // STRONG - - (%inline;)*
438: new Element(STRONG, "STRONG", Element.INLINE, BODY,
439: null),
440: // STYLE - - %StyleSheet;
441: new Element(STYLE, "STYLE", Element.SPECIAL,
442: new short[] { HEAD, BODY }, new short[] {
443: STYLE, TITLE, META }),
444: // SUB - - (%inline;)*
445: new Element(SUB, "SUB", Element.INLINE, BODY, null),
446: // SUP - - (%inline;)*
447: new Element(SUP, "SUP", Element.INLINE, BODY, null), };
448: ELEMENTS_ARRAY['T' - 'A'] = new Element[] {
449: // TABLE - - (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)
450: new Element(TABLE, "TABLE", Element.BLOCK
451: | Element.CONTAINER, BODY, null),
452: // TBODY O O (TR)+
453: new Element(TBODY, "TBODY", 0, TABLE, new short[] {
454: THEAD, TD, TH, TR, COLGROUP }),
455: // TD - O (%flow;)*
456: new Element(TD, "TD", 0, TR, TABLE, new short[] { TD,
457: TH }),
458: // TEXTAREA - - (#PCDATA)
459: new Element(TEXTAREA, "TEXTAREA", Element.SPECIAL,
460: BODY, null),
461: // TFOOT - O (TR)+
462: new Element(TFOOT, "TFOOT", 0, TABLE, new short[] {
463: THEAD, TBODY, TD, TH, TR }),
464: // TH - O (%flow;)*
465: new Element(TH, "TH", 0, TR, TABLE, new short[] { TD,
466: TH }),
467: // THEAD - O (TR)+
468: new Element(THEAD, "THEAD", 0, TABLE,
469: new short[] { COLGROUP }),
470: // TITLE - - (#PCDATA) -(%head.misc;)
471: new Element(TITLE, "TITLE", Element.SPECIAL,
472: new short[] { HEAD, BODY }, null),
473: // TR - O (TH|TD)+
474: new Element(TR, "TR", Element.BLOCK, TABLE,
475: new short[] { TD, TH, TR, COLGROUP }),
476: // TT - - (%inline;)*
477: new Element(TT, "TT", Element.INLINE, BODY, null), };
478: ELEMENTS_ARRAY['U' - 'A'] = new Element[] {
479: // U,
480: new Element(U, "U", Element.INLINE, BODY, null),
481: // UL - - (LI)+
482: new Element(UL, "UL", Element.BLOCK, BODY, null), };
483: ELEMENTS_ARRAY['V' - 'A'] = new Element[] {
484: // VAR - - (%inline;)*
485: new Element(VAR, "VAR", Element.INLINE, BODY, null), };
486: ELEMENTS_ARRAY['W' - 'A'] = new Element[] {
487: // WBR
488: new Element(WBR, "WBR", Element.EMPTY, BODY, null), };
489: ELEMENTS_ARRAY['X' - 'A'] = new Element[] {
490: // XML
491: new Element(XML, "XML", 0, BODY, null),
492: // XMP
493: new Element(XMP, "XMP", Element.SPECIAL, BODY, null), };
494:
495: // keep contiguous list of elements for lookups by code
496: for (int i = 0; i < ELEMENTS_ARRAY.length; i++) {
497: Element[] elements = ELEMENTS_ARRAY[i];
498: if (elements != null) {
499: for (int j = 0; j < elements.length; j++) {
500: Element element = elements[j];
501: ELEMENTS.addElement(element);
502: }
503: }
504: }
505: ELEMENTS.addElement(NO_SUCH_ELEMENT);
506:
507: // initialize cross references to parent elements
508: for (int i = 0; i < ELEMENTS.size; i++) {
509: Element element = ELEMENTS.data[i];
510: if (element.parentCodes != null) {
511: element.parent = new Element[element.parentCodes.length];
512: for (int j = 0; j < element.parentCodes.length; j++) {
513: element.parent[j] = ELEMENTS.data[element.parentCodes[j]];
514: }
515: element.parentCodes = null;
516: }
517: }
518:
519: } // <clinit>()
520:
521: //
522: // Public static methods
523: //
524:
525: /**
526: * Returns the element information for the specified element code.
527: *
528: * @param code The element code.
529: */
530: public static final Element getElement(short code) {
531: return ELEMENTS.data[code];
532: } // getElement(short):Element
533:
534: /**
535: * Returns the element information for the specified element name.
536: *
537: * @param ename The element name.
538: */
539: public static final Element getElement(String ename) {
540: return getElement(ename, NO_SUCH_ELEMENT);
541: } // getElement(String):Element
542:
543: /**
544: * Returns the element information for the specified element name.
545: *
546: * @param ename The element name.
547: * @param element The default element to return if not found.
548: */
549: public static final Element getElement(String ename, Element element) {
550:
551: if (ename.length() > 0) {
552: int c = ename.charAt(0);
553: if (c >= 'a' && c <= 'z') {
554: c = 'A' + c - 'a';
555: }
556: if (c >= 'A' && c <= 'Z') {
557: Element[] elements = ELEMENTS_ARRAY[c - 'A'];
558: if (elements != null) {
559: for (int i = 0; i < elements.length; i++) {
560: Element elem = elements[i];
561: if (elem.name.equalsIgnoreCase(ename)) {
562: return elem;
563: }
564: }
565: }
566: }
567: }
568: return element;
569:
570: } // getElement(String):Element
571:
572: //
573: // Classes
574: //
575:
576: /**
577: * Element information.
578: *
579: * @author Andy Clark
580: */
581: public static class Element {
582:
583: //
584: // Constants
585: //
586:
587: /** Inline element. */
588: public static final int INLINE = 0x01;
589:
590: /** Block element. */
591: public static final int BLOCK = 0x02;
592:
593: /** Empty element. */
594: public static final int EMPTY = 0x04;
595:
596: /** Container element. */
597: public static final int CONTAINER = 0x08;
598:
599: /** Special element. */
600: public static final int SPECIAL = 0x10;
601:
602: //
603: // Data
604: //
605:
606: /** The element code. */
607: public short code;
608:
609: /** The element name. */
610: public String name;
611:
612: /** Informational flags. */
613: public int flags;
614:
615: /** Parent elements. */
616: public short[] parentCodes;
617:
618: /** Parent elements. */
619: public Element[] parent;
620:
621: /** The bounding element code. */
622: public short bounds;
623:
624: /** List of elements this element can close. */
625: public short[] closes;
626:
627: //
628: // Constructors
629: //
630:
631: /**
632: * Constructs an element object.
633: *
634: * @param code The element code.
635: * @param name The element name.
636: * @param flags Informational flags
637: * @param parent Natural closing parent name.
638: * @param closes List of elements this element can close.
639: */
640: public Element(short code, String name, int flags,
641: short parent, short[] closes) {
642: this (code, name, flags, new short[] { parent }, (short) -1,
643: closes);
644: } // <init>(short,String,int,short,short[]);
645:
646: /**
647: * Constructs an element object.
648: *
649: * @param code The element code.
650: * @param name The element name.
651: * @param flags Informational flags
652: * @param parent Natural closing parent name.
653: * @param closes List of elements this element can close.
654: */
655: public Element(short code, String name, int flags,
656: short parent, short bounds, short[] closes) {
657: this (code, name, flags, new short[] { parent }, bounds,
658: closes);
659: } // <init>(short,String,int,short,short,short[])
660:
661: /**
662: * Constructs an element object.
663: *
664: * @param code The element code.
665: * @param name The element name.
666: * @param flags Informational flags
667: * @param parents Natural closing parent names.
668: * @param closes List of elements this element can close.
669: */
670: public Element(short code, String name, int flags,
671: short[] parents, short[] closes) {
672: this (code, name, flags, parents, (short) -1, closes);
673: } // <init>(short,String,int,short[],short[])
674:
675: /**
676: * Constructs an element object.
677: *
678: * @param code The element code.
679: * @param name The element name.
680: * @param flags Informational flags
681: * @param parents Natural closing parent names.
682: * @param closes List of elements this element can close.
683: */
684: public Element(short code, String name, int flags,
685: short[] parents, short bounds, short[] closes) {
686: this .code = code;
687: this .name = name;
688: this .flags = flags;
689: this .parentCodes = parents;
690: this .parent = null;
691: this .bounds = bounds;
692: this .closes = closes;
693: } // <init>(short,String,int,short[],short,short[])
694:
695: //
696: // Public methods
697: //
698:
699: /** Returns true if this element is an inline element. */
700: public final boolean isInline() {
701: return (flags & INLINE) != 0;
702: } // isInline():boolean
703:
704: /** Returns true if this element is a block element. */
705: public final boolean isBlock() {
706: return (flags & BLOCK) != 0;
707: } // isBlock():boolean
708:
709: /** Returns true if this element is an empty element. */
710: public final boolean isEmpty() {
711: return (flags & EMPTY) != 0;
712: } // isEmpty():boolean
713:
714: /** Returns true if this element is a container element. */
715: public final boolean isContainer() {
716: return (flags & CONTAINER) != 0;
717: } // isContainer():boolean
718:
719: /**
720: * Returns true if this element is special -- if its content
721: * should be parsed ignoring markup.
722: */
723: public final boolean isSpecial() {
724: return (flags & SPECIAL) != 0;
725: } // isSpecial():boolean
726:
727: /**
728: * Returns true if this element can close the specified Element.
729: *
730: * @param tag The element.
731: */
732: public boolean closes(short tag) {
733:
734: if (closes != null) {
735: for (int i = 0; i < closes.length; i++) {
736: if (closes[i] == tag) {
737: return true;
738: }
739: }
740: }
741: return false;
742:
743: } // closes(short):boolean
744:
745: //
746: // Object methods
747: //
748:
749: /** Returns a hash code for this object. */
750: public int hashCode() {
751: return name.hashCode();
752: } // hashCode():int
753:
754: /** Returns true if the objects are equal. */
755: public boolean equals(Object o) {
756: return name.equals(o);
757: } // equals(Object):boolean
758:
759: } // class Element
760:
761: /** Unsynchronized list of elements. */
762: public static class ElementList {
763:
764: //
765: // Data
766: //
767:
768: /** The size of the list. */
769: public int size;
770:
771: /** The data in the list. */
772: public Element[] data = new Element[120];
773:
774: //
775: // Public methods
776: //
777:
778: /** Adds an element to list, resizing if necessary. */
779: public void addElement(Element element) {
780: if (size == data.length) {
781: Element[] newarray = new Element[size + 20];
782: System.arraycopy(data, 0, newarray, 0, size);
783: data = newarray;
784: }
785: data[size++] = element;
786: } // addElement(Element)
787:
788: } // class Element
789:
790: } // class HTMLElements
|