KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > boot > XMLElement


1 /* XMLElement.java
2  *
3  *
4  * This file is part of NanoXML 2 Lite.
5  * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
6  *
7  * This software is provided 'as-is', without any express or implied warranty.
8  * In no event will the authors be held liable for any damages arising from the
9  * use of this software.
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute it
13  * freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must not
16  * claim that you wrote the original software. If you use this software in
17  * a product, an acknowledgment in the product documentation would be
18  * appreciated but is not required.
19  *
20  * 2. Altered source versions must be plainly marked as such, and must not be
21  * misrepresented as being the original software.
22  *
23  * 3. This notice may not be removed or altered from any source distribution.
24  *****************************************************************************/

25
26
27 package com.sslexplorer.boot;
28
29 import java.io.ByteArrayOutputStream JavaDoc;
30 import java.io.CharArrayReader JavaDoc;
31 import java.io.IOException JavaDoc;
32 import java.io.OutputStreamWriter JavaDoc;
33 import java.io.Reader JavaDoc;
34 import java.io.StringReader JavaDoc;
35 import java.io.Writer JavaDoc;
36 import java.util.Enumeration JavaDoc;
37 import java.util.Hashtable JavaDoc;
38 import java.util.Vector JavaDoc;
39
40
41 /**
42  * XMLElement is a representation of an XML object. The object is able to parse
43  * XML code.
44  * <P><DL>
45  * <DT><B>Parsing XML Data</B></DT>
46  * <DD>
47  * You can parse XML data using the following code:
48  * <UL><CODE>
49  * XMLElement xml = new XMLElement();<BR>
50  * FileReader reader = new FileReader("filename.xml");<BR>
51  * xml.parseFromReader(reader);
52  * </CODE></UL></DD></DL>
53  * <DL><DT><B>Retrieving Attributes</B></DT>
54  * <DD>
55  * You can enumerate the attributes of an element using the method
56  * {@link #enumerateAttributeNames() enumerateAttributeNames}.
57  * The attribute values can be retrieved using the method
58  * {@link #getStringAttribute(java.lang.String) getStringAttribute}.
59  * The following example shows how to list the attributes of an element:
60  * <UL><CODE>
61  * XMLElement element = ...;<BR>
62  * Enumeration enum = element.getAttributeNames();<BR>
63  * while (enum.hasMoreElements()) {<BR>
64  * &nbsp;&nbsp;&nbsp;&nbsp;String key = (String) enum.nextElement();<BR>
65  * &nbsp;&nbsp;&nbsp;&nbsp;String value = element.getStringAttribute(key);<BR>
66  * &nbsp;&nbsp;&nbsp;&nbsp;System.out.println(key + " = " + value);<BR>
67  * }
68  * </CODE></UL></DD></DL>
69  * <DL><DT><B>Retrieving Child Elements</B></DT>
70  * <DD>
71  * You can enumerate the children of an element using
72  * {@link #enumerateChildren() enumerateChildren}.
73  * The number of child elements can be retrieved using
74  * {@link #countChildren() countChildren}.
75  * </DD></DL>
76  * <DL><DT><B>Elements Containing Character Data</B></DT>
77  * <DD>
78  * If an elements contains character data, like in the following example:
79  * <UL><CODE>
80  * &lt;title&gt;The Title&lt;/title&gt;
81  * </CODE></UL>
82  * you can retrieve that data using the method
83  * {@link #getContent() getContent}.
84  * </DD></DL>
85  * <DL><DT><B>Subclassing XMLElement</B></DT>
86  * <DD>
87  * When subclassing XMLElement, you need to override the method
88  * {@link #createAnotherElement() createAnotherElement}
89  * which has to return a new copy of the receiver.
90  * </DD></DL>
91  * <P>
92  *
93  * @see com.sslexplorer.boot.XMLParseException
94  *
95  * @author Marc De Scheemaecker
96  * &lt;<A HREF="mailto:cyberelf@mac.com">cyberelf@mac.com</A>&gt;
97  */

98 public class XMLElement
99 {
100
101     /**
102      * Serialization serial version ID.
103      */

104     static final long serialVersionUID = 6685035139346394777L;
105
106
107     /**
108      * Major version of NanoXML. Classes with the same major and minor
109      * version are binary compatible. Classes with the same major version
110      * are source compatible. If the major version is different, you may
111      * need to modify the client source code.
112      *
113      * @see XMLElement#NANOXML_MINOR_VERSION
114      */

115     public static final int NANOXML_MAJOR_VERSION = 2;
116
117
118     /**
119      * Minor version of NanoXML. Classes with the same major and minor
120      * version are binary compatible. Classes with the same major version
121      * are source compatible. If the major version is different, you may
122      * need to modify the client source code.
123      *
124      * @see XMLElement#NANOXML_MAJOR_VERSION
125      */

126     public static final int NANOXML_MINOR_VERSION = 2;
127
128
129     /**
130      * The attributes given to the element.
131      *
132      * <dl><dt><b>Invariants:</b></dt><dd>
133      * <ul><li>The field can be empty.
134      * <li>The field is never <code>null</code>.
135      * <li>The keys and the values are strings.
136      * </ul></dd></dl>
137      */

138     private Hashtable JavaDoc attributes;
139
140
141     /**
142      * Child elements of the element.
143      *
144      * <dl><dt><b>Invariants:</b></dt><dd>
145      * <ul><li>The field can be empty.
146      * <li>The field is never <code>null</code>.
147      * <li>The elements are instances of <code>XMLElement</code>
148      * or a subclass of <code>XMLElement</code>.
149      * </ul></dd></dl>
150      */

151     private Vector JavaDoc children;
152
153
154     /**
155      * The name of the element.
156      *
157      * <dl><dt><b>Invariants:</b></dt><dd>
158      * <ul><li>The field is <code>null</code> iff the element is not
159      * initialized by either parse or setName.
160      * <li>If the field is not <code>null</code>, it's not empty.
161      * <li>If the field is not <code>null</code>, it contains a valid
162      * XML identifier.
163      * </ul></dd></dl>
164      */

165     private String JavaDoc name;
166
167
168     /**
169      * The #PCDATA content of the object.
170      *
171      * <dl><dt><b>Invariants:</b></dt><dd>
172      * <ul><li>The field is <code>null</code> iff the element is not a
173      * #PCDATA element.
174      * <li>The field can be any string, including the empty string.
175      * </ul></dd></dl>
176      */

177     private String JavaDoc contents;
178
179
180     /**
181      * Conversion table for &amp;...; entities. The keys are the entity names
182      * without the &amp; and ; delimiters.
183      *
184      * <dl><dt><b>Invariants:</b></dt><dd>
185      * <ul><li>The field is never <code>null</code>.
186      * <li>The field always contains the following associations:
187      * "lt"&nbsp;=&gt;&nbsp;"&lt;", "gt"&nbsp;=&gt;&nbsp;"&gt;",
188      * "quot"&nbsp;=&gt;&nbsp;"\"", "apos"&nbsp;=&gt;&nbsp;"'",
189      * "amp"&nbsp;=&gt;&nbsp;"&amp;"
190      * <li>The keys are strings
191      * <li>The values are char arrays
192      * </ul></dd></dl>
193      */

194     private Hashtable JavaDoc entities;
195
196
197     /**
198      * The line number where the element starts.
199      *
200      * <dl><dt><b>Invariants:</b></dt><dd>
201      * <ul><li><code>lineNr &gt= 0</code>
202      * </ul></dd></dl>
203      */

204     private int lineNr;
205
206
207     /**
208      * <code>true</code> if the case of the element and attribute names
209      * are case insensitive.
210      */

211     private boolean ignoreCase;
212
213
214     /**
215      * <code>true</code> if the leading and trailing whitespace of #PCDATA
216      * sections have to be ignored.
217      */

218     private boolean ignoreWhitespace;
219
220
221     /**
222      * Character read too much.
223      * This character provides push-back functionality to the input reader
224      * without having to use a PushbackReader.
225      * If there is no such character, this field is '\0'.
226      */

227     private char charReadTooMuch;
228
229
230     /**
231      * The reader provided by the caller of the parse method.
232      *
233      * <dl><dt><b>Invariants:</b></dt><dd>
234      * <ul><li>The field is not <code>null</code> while the parse method
235      * is running.
236      * </ul></dd></dl>
237      */

238     private Reader JavaDoc reader;
239
240
241     /**
242      * The current line number in the source content.
243      *
244      * <dl><dt><b>Invariants:</b></dt><dd>
245      * <ul><li>parserLineNr &gt; 0 while the parse method is running.
246      * </ul></dd></dl>
247      */

248     private int parserLineNr;
249
250
251     /**
252      * Creates and initializes a new XML element.
253      * Calling the construction is equivalent to:
254      * <ul><code>new XMLElement(new Hashtable(), false, true)
255      * </code></ul>
256      *
257      * <dl><dt><b>Postconditions:</b></dt><dd>
258      * <ul><li>countChildren() => 0
259      * <li>enumerateChildren() => empty enumeration
260      * <li>enumeratePropertyNames() => empty enumeration
261      * <li>getChildren() => empty vector
262      * <li>getContent() => ""
263      * <li>getLineNr() => 0
264      * <li>getName() => null
265      * </ul></dd></dl>
266      *
267      * @see XMLElement#XMLElement(java.util.Hashtable)
268      * XMLElement(Hashtable)
269      * @see XMLElement#XMLElement(boolean)
270      * @see XMLElement#XMLElement(java.util.Hashtable,boolean)
271      * XMLElement(Hashtable, boolean)
272      */

273     public XMLElement()
274     {
275         this(new Hashtable JavaDoc(), false, true, true);
276     }
277
278
279     /**
280      * Creates and initializes a new XML element.
281      * Calling the construction is equivalent to:
282      * <ul><code>new XMLElement(entities, false, true)
283      * </code></ul>
284      *
285      * @param entities
286      * The entity conversion table.
287      *
288      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
289      * <ul><li><code>entities != null</code>
290      * </ul></dd></dl>
291      *
292      * <dl><dt><b>Postconditions:</b></dt><dd>
293      * <ul><li>countChildren() => 0
294      * <li>enumerateChildren() => empty enumeration
295      * <li>enumeratePropertyNames() => empty enumeration
296      * <li>getChildren() => empty vector
297      * <li>getContent() => ""
298      * <li>getLineNr() => 0
299      * <li>getName() => null
300      * </ul></dd></dl><dl>
301      *
302      * @see XMLElement#XMLElement()
303      * @see XMLElement#XMLElement(boolean)
304      * @see XMLElement#XMLElement(java.util.Hashtable,boolean)
305      * XMLElement(Hashtable, boolean)
306      */

307     public XMLElement(Hashtable JavaDoc entities)
308     {
309         this(entities, false, true, true);
310     }
311
312
313     /**
314      * Creates and initializes a new XML element.
315      * Calling the construction is equivalent to:
316      * <ul><code>new XMLElement(new Hashtable(), skipLeadingWhitespace, true)
317      * </code></ul>
318      *
319      * @param skipLeadingWhitespace
320      * <code>true</code> if leading and trailing whitespace in PCDATA
321      * content has to be removed.
322      *
323      * </dl><dl><dt><b>Postconditions:</b></dt><dd>
324      * <ul><li>countChildren() => 0
325      * <li>enumerateChildren() => empty enumeration
326      * <li>enumeratePropertyNames() => empty enumeration
327      * <li>getChildren() => empty vector
328      * <li>getContent() => ""
329      * <li>getLineNr() => 0
330      * <li>getName() => null
331      * </ul></dd></dl><dl>
332      *
333      * @see XMLElement#XMLElement()
334      * @see XMLElement#XMLElement(java.util.Hashtable)
335      * XMLElement(Hashtable)
336      * @see XMLElement#XMLElement(java.util.Hashtable,boolean)
337      * XMLElement(Hashtable, boolean)
338      */

339     public XMLElement(boolean skipLeadingWhitespace)
340     {
341         this(new Hashtable JavaDoc(), skipLeadingWhitespace, true, true);
342     }
343
344
345     /**
346      * Creates and initializes a new XML element.
347      * Calling the construction is equivalent to:
348      * <ul><code>new XMLElement(entities, skipLeadingWhitespace, true)
349      * </code></ul>
350      *
351      * @param entities
352      * The entity conversion table.
353      * @param skipLeadingWhitespace
354      * <code>true</code> if leading and trailing whitespace in PCDATA
355      * content has to be removed.
356      *
357      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
358      * <ul><li><code>entities != null</code>
359      * </ul></dd></dl>
360      *
361      * <dl><dt><b>Postconditions:</b></dt><dd>
362      * <ul><li>countChildren() => 0
363      * <li>enumerateChildren() => empty enumeration
364      * <li>enumeratePropertyNames() => empty enumeration
365      * <li>getChildren() => empty vector
366      * <li>getContent() => ""
367      * <li>getLineNr() => 0
368      * <li>getName() => null
369      * </ul></dd></dl><dl>
370      *
371      * @see XMLElement#XMLElement()
372      * @see XMLElement#XMLElement(boolean)
373      * @see XMLElement#XMLElement(java.util.Hashtable)
374      * XMLElement(Hashtable)
375      */

376     public XMLElement(Hashtable JavaDoc entities,
377                       boolean skipLeadingWhitespace)
378     {
379         this(entities, skipLeadingWhitespace, true, true);
380     }
381
382
383     /**
384      * Creates and initializes a new XML element.
385      *
386      * @param entities
387      * The entity conversion table.
388      * @param skipLeadingWhitespace
389      * <code>true</code> if leading and trailing whitespace in PCDATA
390      * content has to be removed.
391      * @param ignoreCase
392      * <code>true</code> if the case of element and attribute names have
393      * to be ignored.
394      *
395      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
396      * <ul><li><code>entities != null</code>
397      * </ul></dd></dl>
398      *
399      * <dl><dt><b>Postconditions:</b></dt><dd>
400      * <ul><li>countChildren() => 0
401      * <li>enumerateChildren() => empty enumeration
402      * <li>enumeratePropertyNames() => empty enumeration
403      * <li>getChildren() => empty vector
404      * <li>getContent() => ""
405      * <li>getLineNr() => 0
406      * <li>getName() => null
407      * </ul></dd></dl><dl>
408      *
409      * @see XMLElement#XMLElement()
410      * @see XMLElement#XMLElement(boolean)
411      * @see XMLElement#XMLElement(java.util.Hashtable)
412      * XMLElement(Hashtable)
413      * @see XMLElement#XMLElement(java.util.Hashtable,boolean)
414      * XMLElement(Hashtable, boolean)
415      */

416     public XMLElement(Hashtable JavaDoc entities,
417                       boolean skipLeadingWhitespace,
418                       boolean ignoreCase)
419     {
420         this(entities, skipLeadingWhitespace, true, ignoreCase);
421     }
422
423
424     /**
425      * Creates and initializes a new XML element.
426      * <P>
427      * This constructor should <I>only</I> be called from
428      * {@link #createAnotherElement() createAnotherElement}
429      * to create child elements.
430      *
431      * @param entities
432      * The entity conversion table.
433      * @param skipLeadingWhitespace
434      * <code>true</code> if leading and trailing whitespace in PCDATA
435      * content has to be removed.
436      * @param fillBasicConversionTable
437      * <code>true</code> if the basic entities need to be added to
438      * the entity list.
439      * @param ignoreCase
440      * <code>true</code> if the case of element and attribute names have
441      * to be ignored.
442      *
443      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
444      * <ul><li><code>entities != null</code>
445      * <li>if <code>fillBasicConversionTable == false</code>
446      * then <code>entities</code> contains at least the following
447      * entries: <code>amp</code>, <code>lt</code>, <code>gt</code>,
448      * <code>apos</code> and <code>quot</code>
449      * </ul></dd></dl>
450      *
451      * <dl><dt><b>Postconditions:</b></dt><dd>
452      * <ul><li>countChildren() => 0
453      * <li>enumerateChildren() => empty enumeration
454      * <li>enumeratePropertyNames() => empty enumeration
455      * <li>getChildren() => empty vector
456      * <li>getContent() => ""
457      * <li>getLineNr() => 0
458      * <li>getName() => null
459      * </ul></dd></dl><dl>
460      *
461      * @see XMLElement#createAnotherElement()
462      */

463     protected XMLElement(Hashtable JavaDoc entities,
464                          boolean skipLeadingWhitespace,
465                          boolean fillBasicConversionTable,
466                          boolean ignoreCase)
467     {
468         this.ignoreWhitespace = skipLeadingWhitespace;
469         this.ignoreCase = ignoreCase;
470         this.name = null;
471         this.contents = "";
472         this.attributes = new Hashtable JavaDoc();
473         this.children = new Vector JavaDoc();
474         this.entities = entities;
475         this.lineNr = 0;
476         Enumeration JavaDoc e = this.entities.keys();
477         while (e.hasMoreElements()) {
478             Object JavaDoc key = e.nextElement();
479             Object JavaDoc value = this.entities.get(key);
480             if (value instanceof String JavaDoc) {
481                 value = ((String JavaDoc) value).toCharArray();
482                 this.entities.put(key, value);
483             }
484         }
485         if (fillBasicConversionTable) {
486             this.entities.put("amp", new char[] { '&' });
487             this.entities.put("quot", new char[] { '"' });
488             this.entities.put("apos", new char[] { '\'' });
489             this.entities.put("lt", new char[] { '<' });
490             this.entities.put("gt", new char[] { '>' });
491         }
492     }
493
494
495     /**
496      * Adds a child element.
497      *
498      * @param child
499      * The child element to add.
500      *
501      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
502      * <ul><li><code>child != null</code>
503      * <li><code>child.getName() != null</code>
504      * <li><code>child</code> does not have a parent element
505      * </ul></dd></dl>
506      *
507      * <dl><dt><b>Postconditions:</b></dt><dd>
508      * <ul><li>countChildren() => old.countChildren() + 1
509      * <li>enumerateChildren() => old.enumerateChildren() + child
510      * <li>getChildren() => old.enumerateChildren() + child
511      * </ul></dd></dl><dl>
512      *
513      * @see XMLElement#countChildren()
514      * @see XMLElement#enumerateChildren()
515      * @see XMLElement#getChildren()
516      * @see XMLElement#removeChild(XMLElement)
517      * removeChild(XMLElement)
518      */

519     public void addChild(XMLElement child)
520     {
521         this.children.addElement(child);
522     }
523
524
525     /**
526      * Adds or modifies an attribute.
527      *
528      * @param name
529      * The name of the attribute.
530      * @param value
531      * The value of the attribute.
532      *
533      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
534      * <ul><li><code>name != null</code>
535      * <li><code>name</code> is a valid XML identifier
536      * <li><code>value != null</code>
537      * </ul></dd></dl>
538      *
539      * <dl><dt><b>Postconditions:</b></dt><dd>
540      * <ul><li>enumerateAttributeNames()
541      * => old.enumerateAttributeNames() + name
542      * <li>getAttribute(name) => value
543      * </ul></dd></dl><dl>
544      *
545      * @see XMLElement#setDoubleAttribute(java.lang.String, double)
546      * setDoubleAttribute(String, double)
547      * @see XMLElement#setIntAttribute(java.lang.String, int)
548      * setIntAttribute(String, int)
549      * @see XMLElement#enumerateAttributeNames()
550      * @see XMLElement#getAttribute(java.lang.String)
551      * getAttribute(String)
552      * @see XMLElement#getAttribute(java.lang.String, java.lang.Object)
553      * getAttribute(String, Object)
554      * @see XMLElement#getAttribute(java.lang.String,
555      * java.util.Hashtable,
556      * java.lang.String, boolean)
557      * getAttribute(String, Hashtable, String, boolean)
558      * @see XMLElement#getStringAttribute(java.lang.String)
559      * getStringAttribute(String)
560      * @see XMLElement#getStringAttribute(java.lang.String,
561      * java.lang.String)
562      * getStringAttribute(String, String)
563      * @see XMLElement#getStringAttribute(java.lang.String,
564      * java.util.Hashtable,
565      * java.lang.String, boolean)
566      * getStringAttribute(String, Hashtable, String, boolean)
567      */

568     public void setAttribute(String JavaDoc name,
569                              Object JavaDoc value)
570     {
571         if (this.ignoreCase) {
572             name = name.toUpperCase();
573         }
574         this.attributes.put(name, value.toString());
575     }
576
577
578     /**
579      * Adds or modifies an attribute.
580      *
581      * @param name
582      * The name of the attribute.
583      * @param value
584      * The value of the attribute.
585      *
586      * @deprecated Use {@link #setAttribute(java.lang.String, java.lang.Object)
587      * setAttribute} instead.
588      */

589     public void addProperty(String JavaDoc name,
590                             Object JavaDoc value)
591     {
592         this.setAttribute(name, value);
593     }
594
595
596     /**
597      * Adds or modifies an attribute.
598      *
599      * @param name
600      * The name of the attribute.
601      * @param value
602      * The value of the attribute.
603      *
604      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
605      * <ul><li><code>name != null</code>
606      * <li><code>name</code> is a valid XML identifier
607      * </ul></dd></dl>
608      *
609      * <dl><dt><b>Postconditions:</b></dt><dd>
610      * <ul><li>enumerateAttributeNames()
611      * => old.enumerateAttributeNames() + name
612      * <li>getIntAttribute(name) => value
613      * </ul></dd></dl><dl>
614      *
615      * @see XMLElement#setDoubleAttribute(java.lang.String, double)
616      * setDoubleAttribute(String, double)
617      * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
618      * setAttribute(String, Object)
619      * @see XMLElement#removeAttribute(java.lang.String)
620      * removeAttribute(String)
621      * @see XMLElement#enumerateAttributeNames()
622      * @see XMLElement#getIntAttribute(java.lang.String)
623      * getIntAttribute(String)
624      * @see XMLElement#getIntAttribute(java.lang.String, int)
625      * getIntAttribute(String, int)
626      * @see XMLElement#getIntAttribute(java.lang.String,
627      * java.util.Hashtable,
628      * java.lang.String, boolean)
629      * getIntAttribute(String, Hashtable, String, boolean)
630      */

631     public void setIntAttribute(String JavaDoc name,
632                                 int value)
633     {
634         if (this.ignoreCase) {
635             name = name.toUpperCase();
636         }
637         this.attributes.put(name, Integer.toString(value));
638     }
639
640
641     /**
642      * Adds or modifies an attribute.
643      *
644      * @param key
645      * The name of the attribute.
646      * @param value
647      * The value of the attribute.
648      *
649      * @deprecated Use {@link #setIntAttribute(java.lang.String, int)
650      * setIntAttribute} instead.
651      */

652     public void addProperty(String JavaDoc key,
653                             int value)
654     {
655         this.setIntAttribute(key, value);
656     }
657
658
659     /**
660      * Adds or modifies an attribute.
661      *
662      * @param name
663      * The name of the attribute.
664      * @param value
665      * The value of the attribute.
666      *
667      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
668      * <ul><li><code>name != null</code>
669      * <li><code>name</code> is a valid XML identifier
670      * </ul></dd></dl>
671      *
672      * <dl><dt><b>Postconditions:</b></dt><dd>
673      * <ul><li>enumerateAttributeNames()
674      * => old.enumerateAttributeNames() + name
675      * <li>getDoubleAttribute(name) => value
676      * </ul></dd></dl><dl>
677      *
678      * @see XMLElement#setIntAttribute(java.lang.String, int)
679      * setIntAttribute(String, int)
680      * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
681      * setAttribute(String, Object)
682      * @see XMLElement#removeAttribute(java.lang.String)
683      * removeAttribute(String)
684      * @see XMLElement#enumerateAttributeNames()
685      * @see XMLElement#getDoubleAttribute(java.lang.String)
686      * getDoubleAttribute(String)
687      * @see XMLElement#getDoubleAttribute(java.lang.String, double)
688      * getDoubleAttribute(String, double)
689      * @see XMLElement#getDoubleAttribute(java.lang.String,
690      * java.util.Hashtable,
691      * java.lang.String, boolean)
692      * getDoubleAttribute(String, Hashtable, String, boolean)
693      */

694     public void setDoubleAttribute(String JavaDoc name,
695                                    double value)
696     {
697         if (this.ignoreCase) {
698             name = name.toUpperCase();
699         }
700         this.attributes.put(name, Double.toString(value));
701     }
702
703
704     /**
705      * Adds or modifies an attribute.
706      *
707      * @param name
708      * The name of the attribute.
709      * @param value
710      * The value of the attribute.
711      *
712      * @deprecated Use {@link #setDoubleAttribute(java.lang.String, double)
713      * setDoubleAttribute} instead.
714      */

715     public void addProperty(String JavaDoc name,
716                             double value)
717     {
718         this.setDoubleAttribute(name, value);
719     }
720
721
722     /**
723      * Returns the number of child elements of the element.
724      *
725      * <dl><dt><b>Postconditions:</b></dt><dd>
726      * <ul><li><code>result >= 0</code>
727      * </ul></dd></dl>
728      *
729      * @return child count
730      *
731      * @see XMLElement#addChild(XMLElement)
732      * addChild(XMLElement)
733      * @see XMLElement#enumerateChildren()
734      * @see XMLElement#getChildren()
735      * @see XMLElement#removeChild(XMLElement)
736      * removeChild(XMLElement)
737      */

738     public int countChildren()
739     {
740         return this.children.size();
741     }
742
743
744     /**
745      * Enumerates the attribute names.
746      *
747      * <dl><dt><b>Postconditions:</b></dt><dd>
748      * <ul><li><code>result != null</code>
749      * </ul></dd></dl>
750      *
751      * @return enumeration of attribute names
752      * @see XMLElement#setDoubleAttribute(java.lang.String, double)
753      * setDoubleAttribute(String, double)
754      * @see XMLElement#setIntAttribute(java.lang.String, int)
755      * setIntAttribute(String, int)
756      * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
757      * setAttribute(String, Object)
758      * @see XMLElement#removeAttribute(java.lang.String)
759      * removeAttribute(String)
760      * @see XMLElement#getAttribute(java.lang.String)
761      * getAttribute(String)
762      * @see XMLElement#getAttribute(java.lang.String, java.lang.Object)
763      * getAttribute(String, String)
764      * @see XMLElement#getAttribute(java.lang.String,
765      * java.util.Hashtable,
766      * java.lang.String, boolean)
767      * getAttribute(String, Hashtable, String, boolean)
768      * @see XMLElement#getStringAttribute(java.lang.String)
769      * getStringAttribute(String)
770      * @see XMLElement#getStringAttribute(java.lang.String,
771      * java.lang.String)
772      * getStringAttribute(String, String)
773      * @see XMLElement#getStringAttribute(java.lang.String,
774      * java.util.Hashtable,
775      * java.lang.String, boolean)
776      * getStringAttribute(String, Hashtable, String, boolean)
777      * @see XMLElement#getIntAttribute(java.lang.String)
778      * getIntAttribute(String)
779      * @see XMLElement#getIntAttribute(java.lang.String, int)
780      * getIntAttribute(String, int)
781      * @see XMLElement#getIntAttribute(java.lang.String,
782      * java.util.Hashtable,
783      * java.lang.String, boolean)
784      * getIntAttribute(String, Hashtable, String, boolean)
785      * @see XMLElement#getDoubleAttribute(java.lang.String)
786      * getDoubleAttribute(String)
787      * @see XMLElement#getDoubleAttribute(java.lang.String, double)
788      * getDoubleAttribute(String, double)
789      * @see XMLElement#getDoubleAttribute(java.lang.String,
790      * java.util.Hashtable,
791      * java.lang.String, boolean)
792      * getDoubleAttribute(String, Hashtable, String, boolean)
793      * @see XMLElement#getBooleanAttribute(java.lang.String,
794      * java.lang.String,
795      * java.lang.String, boolean)
796      * getBooleanAttribute(String, String, String, boolean)
797      */

798     public Enumeration JavaDoc enumerateAttributeNames()
799     {
800         return this.attributes.keys();
801     }
802
803
804     /**
805      * Enumerates the attribute names.
806      *
807      * @return enumeration of attribute names
808      * @deprecated Use {@link #enumerateAttributeNames()
809      * enumerateAttributeNames} instead.
810      */

811     public Enumeration JavaDoc enumeratePropertyNames()
812     {
813         return this.enumerateAttributeNames();
814     }
815
816
817     /**
818      * Enumerates the child elements.
819      *
820      * <dl><dt><b>Postconditions:</b></dt><dd>
821      * <ul><li><code>result != null</code>
822      * </ul></dd></dl>
823      *
824      * @return enumeration of child elements
825      * @see XMLElement#addChild(XMLElement)
826      * addChild(XMLElement)
827      * @see XMLElement#countChildren()
828      * @see XMLElement#getChildren()
829      * @see XMLElement#removeChild(XMLElement)
830      * removeChild(XMLElement)
831      */

832     public Enumeration JavaDoc enumerateChildren()
833     {
834         return this.children.elements();
835     }
836
837
838     /**
839      * Returns the child elements as a Vector. It is safe to modify this
840      * Vector.
841      *
842      * <dl><dt><b>Postconditions:</b></dt><dd>
843      * <ul><li><code>result != null</code>
844      * </ul></dd></dl>
845      *
846      * @return vector of children
847      * @see XMLElement#addChild(XMLElement)
848      * addChild(XMLElement)
849      * @see XMLElement#countChildren()
850      * @see XMLElement#enumerateChildren()
851      * @see XMLElement#removeChild(XMLElement)
852      * removeChild(XMLElement)
853      */

854     public Vector JavaDoc getChildren()
855     {
856         try {
857             return (Vector JavaDoc) this.children.clone();
858         } catch (Exception JavaDoc e) {
859             // this never happens, however, some Java compilers are so
860
// braindead that they require this exception clause
861
return null;
862         }
863     }
864
865
866     /**
867      * Returns the PCDATA content of the object. If there is no such content,
868      * <CODE>null</CODE> is returned.
869      *
870      * @return PCDATA content of element
871      * @deprecated Use {@link #getContent() getContent} instead.
872      */

873     public String JavaDoc getContents()
874     {
875         return this.getContent();
876     }
877
878
879     /**
880      * Returns the PCDATA content of the object. If there is no such content,
881      * <CODE>null</CODE> is returned.
882      *
883      * @return PCDATA content of element
884      * @see XMLElement#setContent(java.lang.String)
885      * setContent(String)
886      */

887     public String JavaDoc getContent()
888     {
889         return this.contents;
890     }
891
892
893     /**
894      * Returns the line nr in the source data on which the element is found.
895      * This method returns <code>0</code> there is no associated source data.
896      *
897      * <dl><dt><b>Postconditions:</b></dt><dd>
898      * <ul><li><code>result >= 0</code>
899      * </ul></dd></dl>
900      *
901      * @return line number in source of element
902      */

903     public int getLineNr()
904     {
905         return this.lineNr;
906     }
907
908
909     /**
910      * Returns an attribute of the element.
911      * If the attribute doesn't exist, <code>null</code> is returned.
912      *
913      * @param name The name of the attribute.
914      *
915      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
916      * <ul><li><code>name != null</code>
917      * <li><code>name</code> is a valid XML identifier
918      * </ul></dd></dl><dl>
919      *
920      * @return attribute
921      * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
922      * setAttribute(String, Object)
923      * @see XMLElement#removeAttribute(java.lang.String)
924      * removeAttribute(String)
925      * @see XMLElement#enumerateAttributeNames()
926      * @see XMLElement#getAttribute(java.lang.String, java.lang.Object)
927      * getAttribute(String, Object)
928      * @see XMLElement#getAttribute(java.lang.String,
929      * java.util.Hashtable,
930      * java.lang.String, boolean)
931      * getAttribute(String, Hashtable, String, boolean)
932      */

933     public Object JavaDoc getAttribute(String JavaDoc name)
934     {
935         return this.getAttribute(name, null);
936     }
937
938
939     /**
940      * Returns an attribute of the element.
941      * If the attribute doesn't exist, <code>defaultValue</code> is returned.
942      *
943      *
944      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
945      * <ul><li><code>name != null</code>
946      * <li><code>name</code> is a valid XML identifier
947      * </ul></dd></dl><dl>
948      *
949      * @param name The name of the attribute.
950      * @param defaultValue Key to use if the attribute is missing.
951      * @return attribute
952      *
953      * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
954      * setAttribute(String, Object)
955      * @see XMLElement#removeAttribute(java.lang.String)
956      * removeAttribute(String)
957      * @see XMLElement#enumerateAttributeNames()
958      * @see XMLElement#getAttribute(java.lang.String)
959      * getAttribute(String)
960      * @see XMLElement#getAttribute(java.lang.String,
961      * java.util.Hashtable,
962      * java.lang.String, boolean)
963      * getAttribute(String, Hashtable, String, boolean)
964      */

965     public Object JavaDoc getAttribute(String JavaDoc name,
966                                Object JavaDoc defaultValue)
967     {
968         if (this.ignoreCase) {
969             name = name.toUpperCase();
970         }
971         Object JavaDoc value = this.attributes.get(name);
972         if (value == null) {
973             value = defaultValue;
974         }
975         return value;
976     }
977
978
979     /**
980      * Returns an attribute by looking up a key in a hashtable.
981      * If the attribute doesn't exist, the value corresponding to defaultKey
982      * is returned.
983      * <P>
984      * As an example, if valueSet contains the mapping <code>"one" =>
985      * "1"</code>
986      * and the element contains the attribute <code>attr="one"</code>, then
987      * <code>getAttribute("attr", mapping, defaultKey, false)</code> returns
988      * <code>"1"</code>.
989      *
990      * @param name
991      * The name of the attribute.
992      * @param valueSet
993      * Hashtable mapping keys to values.
994      * @param defaultKey
995      * Key to use if the attribute is missing.
996      * @param allowLiterals
997      * <code>true</code> if literals are valid.
998      *
999      * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1000     * <ul><li><code>name != null</code>
1001     * <li><code>name</code> is a valid XML identifier
1002     * <li><code>valueSet</code> != null
1003     * <li>the keys of <code>valueSet</code> are strings
1004     * </ul></dd></dl><dl>
1005     *
1006     * @return attribute
1007     * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
1008     * setAttribute(String, Object)
1009     * @see XMLElement#removeAttribute(java.lang.String)
1010     * removeAttribute(String)
1011     * @see XMLElement#enumerateAttributeNames()
1012     * @see XMLElement#getAttribute(java.lang.String)
1013     * getAttribute(String)
1014     * @see XMLElement#getAttribute(java.lang.String, java.lang.Object)
1015     * getAttribute(String, Object)
1016     */

1017    public Object JavaDoc getAttribute(String JavaDoc name,
1018                               Hashtable JavaDoc valueSet,
1019                               String JavaDoc defaultKey,
1020                               boolean allowLiterals)
1021    {
1022        if (this.ignoreCase) {
1023            name = name.toUpperCase();
1024        }
1025        Object JavaDoc key = this.attributes.get(name);
1026        Object JavaDoc result;
1027        if (key == null) {
1028            key = defaultKey;
1029        }
1030        result = valueSet.get(key);
1031        if (result == null) {
1032            if (allowLiterals) {
1033                result = key;
1034            } else {
1035                throw this.invalidValue(name, (String JavaDoc) key);
1036            }
1037        }
1038        return result;
1039    }
1040
1041
1042    /**
1043     * Returns an attribute of the element.
1044     * If the attribute doesn't exist, <code>null</code> is returned.
1045     *
1046     * @param name The name of the attribute.
1047     *
1048     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1049     * <ul><li><code>name != null</code>
1050     * <li><code>name</code> is a valid XML identifier
1051     * </ul></dd></dl><dl>
1052     *
1053     * @return attribute
1054     * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
1055     * setAttribute(String, Object)
1056     * @see XMLElement#removeAttribute(java.lang.String)
1057     * removeAttribute(String)
1058     * @see XMLElement#enumerateAttributeNames()
1059     * @see XMLElement#getStringAttribute(java.lang.String,
1060     * java.lang.String)
1061     * getStringAttribute(String, String)
1062     * @see XMLElement#getStringAttribute(java.lang.String,
1063     * java.util.Hashtable,
1064     * java.lang.String, boolean)
1065     * getStringAttribute(String, Hashtable, String, boolean)
1066     */

1067    public String JavaDoc getStringAttribute(String JavaDoc name)
1068    {
1069        return this.getStringAttribute(name, null);
1070    }
1071
1072
1073    /**
1074     * Returns an attribute of the element.
1075     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
1076     *
1077     * @param name The name of the attribute.
1078     * @param defaultValue Key to use if the attribute is missing.
1079     *
1080     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1081     * <ul><li><code>name != null</code>
1082     * <li><code>name</code> is a valid XML identifier
1083     * </ul></dd></dl><dl>
1084     *
1085     * @return attribute
1086     * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
1087     * setAttribute(String, Object)
1088     * @see XMLElement#removeAttribute(java.lang.String)
1089     * removeAttribute(String)
1090     * @see XMLElement#enumerateAttributeNames()
1091     * @see XMLElement#getStringAttribute(java.lang.String)
1092     * getStringAttribute(String)
1093     * @see XMLElement#getStringAttribute(java.lang.String,
1094     * java.util.Hashtable,
1095     * java.lang.String, boolean)
1096     * getStringAttribute(String, Hashtable, String, boolean)
1097     */

1098    public String JavaDoc getStringAttribute(String JavaDoc name,
1099                                     String JavaDoc defaultValue)
1100    {
1101        return (String JavaDoc) this.getAttribute(name, defaultValue);
1102    }
1103
1104
1105    /**
1106     * Returns an attribute by looking up a key in a hashtable.
1107     * If the attribute doesn't exist, the value corresponding to defaultKey
1108     * is returned.
1109     * <P>
1110     * As an example, if valueSet contains the mapping <code>"one" =>
1111     * "1"</code>
1112     * and the element contains the attribute <code>attr="one"</code>, then
1113     * <code>getAttribute("attr", mapping, defaultKey, false)</code> returns
1114     * <code>"1"</code>.
1115     *
1116     * @param name
1117     * The name of the attribute.
1118     * @param valueSet
1119     * Hashtable mapping keys to values.
1120     * @param defaultKey
1121     * Key to use if the attribute is missing.
1122     * @param allowLiterals
1123     * <code>true</code> if literals are valid.
1124     *
1125     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1126     * <ul><li><code>name != null</code>
1127     * <li><code>name</code> is a valid XML identifier
1128     * <li><code>valueSet</code> != null
1129     * <li>the keys of <code>valueSet</code> are strings
1130     * <li>the values of <code>valueSet</code> are strings
1131     * </ul></dd></dl><dl>
1132     *
1133     * @return attribute
1134     * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
1135     * setAttribute(String, Object)
1136     * @see XMLElement#removeAttribute(java.lang.String)
1137     * removeAttribute(String)
1138     * @see XMLElement#enumerateAttributeNames()
1139     * @see XMLElement#getStringAttribute(java.lang.String)
1140     * getStringAttribute(String)
1141     * @see XMLElement#getStringAttribute(java.lang.String,
1142     * java.lang.String)
1143     * getStringAttribute(String, String)
1144     */

1145    public String JavaDoc getStringAttribute(String JavaDoc name,
1146                                     Hashtable JavaDoc valueSet,
1147                                     String JavaDoc defaultKey,
1148                                     boolean allowLiterals)
1149    {
1150        return (String JavaDoc) this.getAttribute(name, valueSet, defaultKey,
1151                                          allowLiterals);
1152    }
1153
1154
1155    /**
1156     * Returns an attribute of the element.
1157     * If the attribute doesn't exist, <code>0</code> is returned.
1158     *
1159     * @param name The name of the attribute.
1160     *
1161     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1162     * <ul><li><code>name != null</code>
1163     * <li><code>name</code> is a valid XML identifier
1164     * </ul></dd></dl><dl>
1165     *
1166     * @return attribute
1167     * @see XMLElement#setIntAttribute(java.lang.String, int)
1168     * setIntAttribute(String, int)
1169     * @see XMLElement#enumerateAttributeNames()
1170     * @see XMLElement#getIntAttribute(java.lang.String, int)
1171     * getIntAttribute(String, int)
1172     * @see XMLElement#getIntAttribute(java.lang.String,
1173     * java.util.Hashtable,
1174     * java.lang.String, boolean)
1175     * getIntAttribute(String, Hashtable, String, boolean)
1176     */

1177    public int getIntAttribute(String JavaDoc name)
1178    {
1179        return this.getIntAttribute(name, 0);
1180    }
1181
1182
1183    /**
1184     * Returns an attribute of the element.
1185     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
1186     *
1187     * @param name The name of the attribute.
1188     * @param defaultValue Key to use if the attribute is missing.
1189     *
1190     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1191     * <ul><li><code>name != null</code>
1192     * <li><code>name</code> is a valid XML identifier
1193     * </ul></dd></dl><dl>
1194     *
1195     * @return attribute
1196     * @see XMLElement#setIntAttribute(java.lang.String, int)
1197     * setIntAttribute(String, int)
1198     * @see XMLElement#enumerateAttributeNames()
1199     * @see XMLElement#getIntAttribute(java.lang.String)
1200     * getIntAttribute(String)
1201     * @see XMLElement#getIntAttribute(java.lang.String,
1202     * java.util.Hashtable,
1203     * java.lang.String, boolean)
1204     * getIntAttribute(String, Hashtable, String, boolean)
1205     */

1206    public int getIntAttribute(String JavaDoc name,
1207                               int defaultValue)
1208    {
1209        if (this.ignoreCase) {
1210            name = name.toUpperCase();
1211        }
1212        String JavaDoc value = (String JavaDoc) this.attributes.get(name);
1213        if (value == null) {
1214            return defaultValue;
1215        } else {
1216            try {
1217                return Integer.parseInt(value);
1218            } catch (NumberFormatException JavaDoc e) {
1219                throw this.invalidValue(name, value);
1220            }
1221        }
1222    }
1223
1224
1225    /**
1226     * Returns an attribute by looking up a key in a hashtable.
1227     * If the attribute doesn't exist, the value corresponding to defaultKey
1228     * is returned.
1229     * <P>
1230     * As an example, if valueSet contains the mapping <code>"one" => 1</code>
1231     * and the element contains the attribute <code>attr="one"</code>, then
1232     * <code>getIntAttribute("attr", mapping, defaultKey, false)</code> returns
1233     * <code>1</code>.
1234     *
1235     * @param name
1236     * The name of the attribute.
1237     * @param valueSet
1238     * Hashtable mapping keys to values.
1239     * @param defaultKey
1240     * Key to use if the attribute is missing.
1241     * @param allowLiteralNumbers
1242     * <code>true</code> if literal numbers are valid.
1243     *
1244     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1245     * <ul><li><code>name != null</code>
1246     * <li><code>name</code> is a valid XML identifier
1247     * <li><code>valueSet</code> != null
1248     * <li>the keys of <code>valueSet</code> are strings
1249     * <li>the values of <code>valueSet</code> are Integer objects
1250     * <li><code>defaultKey</code> is either <code>null</code>, a
1251     * key in <code>valueSet</code> or an integer.
1252     * </ul></dd></dl><dl>
1253     *
1254     * @return attribute
1255     * @see XMLElement#setIntAttribute(java.lang.String, int)
1256     * setIntAttribute(String, int)
1257     * @see XMLElement#enumerateAttributeNames()
1258     * @see XMLElement#getIntAttribute(java.lang.String)
1259     * getIntAttribute(String)
1260     * @see XMLElement#getIntAttribute(java.lang.String, int)
1261     * getIntAttribute(String, int)
1262     */

1263    public int getIntAttribute(String JavaDoc name,
1264                               Hashtable JavaDoc valueSet,
1265                               String JavaDoc defaultKey,
1266                               boolean allowLiteralNumbers)
1267    {
1268        if (this.ignoreCase) {
1269            name = name.toUpperCase();
1270        }
1271        Object JavaDoc key = this.attributes.get(name);
1272        Integer JavaDoc result;
1273        if (key == null) {
1274            key = defaultKey;
1275        }
1276        try {
1277            result = (Integer JavaDoc) valueSet.get(key);
1278        } catch (ClassCastException JavaDoc e) {
1279            throw this.invalidValueSet(name);
1280        }
1281        if (result == null) {
1282            if (! allowLiteralNumbers) {
1283                throw this.invalidValue(name, (String JavaDoc) key);
1284            }
1285            try {
1286                result = Integer.valueOf((String JavaDoc) key);
1287            } catch (NumberFormatException JavaDoc e) {
1288                throw this.invalidValue(name, (String JavaDoc) key);
1289            }
1290        }
1291        return result.intValue();
1292    }
1293
1294
1295    /**
1296     * Returns an attribute of the element.
1297     * If the attribute doesn't exist, <code>0.0</code> is returned.
1298     *
1299     * @param name The name of the attribute.
1300     *
1301     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1302     * <ul><li><code>name != null</code>
1303     * <li><code>name</code> is a valid XML identifier
1304     * </ul></dd></dl><dl>
1305     *
1306     * @return attribute
1307     * @see XMLElement#setDoubleAttribute(java.lang.String, double)
1308     * setDoubleAttribute(String, double)
1309     * @see XMLElement#enumerateAttributeNames()
1310     * @see XMLElement#getDoubleAttribute(java.lang.String, double)
1311     * getDoubleAttribute(String, double)
1312     * @see XMLElement#getDoubleAttribute(java.lang.String,
1313     * java.util.Hashtable,
1314     * java.lang.String, boolean)
1315     * getDoubleAttribute(String, Hashtable, String, boolean)
1316     */

1317    public double getDoubleAttribute(String JavaDoc name)
1318    {
1319        return this.getDoubleAttribute(name, 0.);
1320    }
1321
1322
1323    /**
1324     * Returns an attribute of the element.
1325     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
1326     *
1327     * @param name The name of the attribute.
1328     * @param defaultValue Key to use if the attribute is missing.
1329     *
1330     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1331     * <ul><li><code>name != null</code>
1332     * <li><code>name</code> is a valid XML identifier
1333     * </ul></dd></dl><dl>
1334     *
1335     * @return attribute
1336     * @see XMLElement#setDoubleAttribute(java.lang.String, double)
1337     * setDoubleAttribute(String, double)
1338     * @see XMLElement#enumerateAttributeNames()
1339     * @see XMLElement#getDoubleAttribute(java.lang.String)
1340     * getDoubleAttribute(String)
1341     * @see XMLElement#getDoubleAttribute(java.lang.String,
1342     * java.util.Hashtable,
1343     * java.lang.String, boolean)
1344     * getDoubleAttribute(String, Hashtable, String, boolean)
1345     */

1346    public double getDoubleAttribute(String JavaDoc name,
1347                                     double defaultValue)
1348    {
1349        if (this.ignoreCase) {
1350            name = name.toUpperCase();
1351        }
1352        String JavaDoc value = (String JavaDoc) this.attributes.get(name);
1353        if (value == null) {
1354            return defaultValue;
1355        } else {
1356            try {
1357                return Double.valueOf(value).doubleValue();
1358            } catch (NumberFormatException JavaDoc e) {
1359                throw this.invalidValue(name, value);
1360            }
1361        }
1362    }
1363
1364
1365    /**
1366     * Returns an attribute by looking up a key in a hashtable.
1367     * If the attribute doesn't exist, the value corresponding to defaultKey
1368     * is returned.
1369     * <P>
1370     * As an example, if valueSet contains the mapping <code>"one" =&gt;
1371     * 1.0</code>
1372     * and the element contains the attribute <code>attr="one"</code>, then
1373     * <code>getDoubleAttribute("attr", mapping, defaultKey, false)</code>
1374     * returns <code>1.0</code>.
1375     *
1376     * @param name
1377     * The name of the attribute.
1378     * @param valueSet
1379     * Hashtable mapping keys to values.
1380     * @param defaultKey
1381     * Key to use if the attribute is missing.
1382     * @param allowLiteralNumbers
1383     * <code>true</code> if literal numbers are valid.
1384     *
1385     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1386     * <ul><li><code>name != null</code>
1387     * <li><code>name</code> is a valid XML identifier
1388     * <li><code>valueSet != null</code>
1389     * <li>the keys of <code>valueSet</code> are strings
1390     * <li>the values of <code>valueSet</code> are Double objects
1391     * <li><code>defaultKey</code> is either <code>null</code>, a
1392     * key in <code>valueSet</code> or a double.
1393     * </ul></dd></dl><dl>
1394     *
1395     * @return attribute
1396     * @see XMLElement#setDoubleAttribute(java.lang.String, double)
1397     * setDoubleAttribute(String, double)
1398     * @see XMLElement#enumerateAttributeNames()
1399     * @see XMLElement#getDoubleAttribute(java.lang.String)
1400     * getDoubleAttribute(String)
1401     * @see XMLElement#getDoubleAttribute(java.lang.String, double)
1402     * getDoubleAttribute(String, double)
1403     */

1404    public double getDoubleAttribute(String JavaDoc name,
1405                                     Hashtable JavaDoc valueSet,
1406                                     String JavaDoc defaultKey,
1407                                     boolean allowLiteralNumbers)
1408    {
1409        if (this.ignoreCase) {
1410            name = name.toUpperCase();
1411        }
1412        Object JavaDoc key = this.attributes.get(name);
1413        Double JavaDoc result;
1414        if (key == null) {
1415            key = defaultKey;
1416        }
1417        try {
1418            result = (Double JavaDoc) valueSet.get(key);
1419        } catch (ClassCastException JavaDoc e) {
1420            throw this.invalidValueSet(name);
1421        }
1422        if (result == null) {
1423            if (! allowLiteralNumbers) {
1424                throw this.invalidValue(name, (String JavaDoc) key);
1425            }
1426            try {
1427                result = Double.valueOf((String JavaDoc) key);
1428            } catch (NumberFormatException JavaDoc e) {
1429                throw this.invalidValue(name, (String JavaDoc) key);
1430            }
1431        }
1432        return result.doubleValue();
1433    }
1434
1435
1436    /**
1437     * Returns an attribute of the element.
1438     * If the attribute doesn't exist, <code>defaultValue</code> is returned.
1439     * If the value of the attribute is equal to <code>trueValue</code>,
1440     * <code>true</code> is returned.
1441     * If the value of the attribute is equal to <code>falseValue</code>,
1442     * <code>false</code> is returned.
1443     * If the value doesn't match <code>trueValue</code> or
1444     * <code>falseValue</code>, an exception is thrown.
1445     *
1446     * @param name The name of the attribute.
1447     * @param trueValue The value associated with <code>true</code>.
1448     * @param falseValue The value associated with <code>true</code>.
1449     * @param defaultValue Value to use if the attribute is missing.
1450     * @return attribute
1451     *
1452     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1453     * <ul><li><code>name != null</code>
1454     * <li><code>name</code> is a valid XML identifier
1455     * <li><code>trueValue</code> and <code>falseValue</code>
1456     * are different strings.
1457     * </ul></dd></dl><dl>
1458     *
1459     * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
1460     * setAttribute(String, Object)
1461     * @see XMLElement#removeAttribute(java.lang.String)
1462     * removeAttribute(String)
1463     * @see XMLElement#enumerateAttributeNames()
1464     */

1465    public boolean getBooleanAttribute(String JavaDoc name,
1466                                       String JavaDoc trueValue,
1467                                       String JavaDoc falseValue,
1468                                       boolean defaultValue)
1469    {
1470        if (this.ignoreCase) {
1471            name = name.toUpperCase();
1472        }
1473        Object JavaDoc value = this.attributes.get(name);
1474        if (value == null) {
1475            return defaultValue;
1476        } else if (value.equals(trueValue)) {
1477            return true;
1478        } else if (value.equals(falseValue)) {
1479            return false;
1480        } else {
1481            throw this.invalidValue(name, (String JavaDoc) value);
1482        }
1483    }
1484
1485
1486    /**
1487     * Returns an attribute by looking up a key in a hashtable.
1488     *
1489     * @param name name
1490     * @param valueSet value
1491     * @param defaultKey default
1492     * @return attribute
1493     *
1494     * @deprecated Use {@link #getIntAttribute(java.lang.String,
1495     * java.util.Hashtable, java.lang.String, boolean)
1496     * getIntAttribute} instead.
1497     */

1498    public int getIntProperty(String JavaDoc name,
1499                              Hashtable JavaDoc valueSet,
1500                              String JavaDoc defaultKey)
1501    {
1502        return this.getIntAttribute(name, valueSet, defaultKey, false);
1503    }
1504
1505
1506    /**
1507     * Returns an attribute.
1508     *
1509     * @param name name
1510     * @return attribute
1511     *
1512     * @deprecated Use {@link #getStringAttribute(java.lang.String)
1513     * getStringAttribute} instead.
1514     */

1515    public String JavaDoc getProperty(String JavaDoc name)
1516    {
1517        return this.getStringAttribute(name);
1518    }
1519
1520
1521    /**
1522     * Returns an attribute.
1523     *
1524     * @param name name
1525     * @param defaultValue default value
1526     * @return attribute
1527     *
1528     * @deprecated Use {@link #getStringAttribute(java.lang.String,
1529     * java.lang.String) getStringAttribute} instead.
1530     */

1531    public String JavaDoc getProperty(String JavaDoc name,
1532                              String JavaDoc defaultValue)
1533    {
1534        return this.getStringAttribute(name, defaultValue);
1535    }
1536
1537
1538    /**
1539     * Returns an attribute.
1540     *
1541     * @param name name
1542     * @param defaultValue default value
1543     * @return attribute
1544     *
1545     * @deprecated Use {@link #getIntAttribute(java.lang.String, int)
1546     * getIntAttribute} instead.
1547     */

1548    public int getProperty(String JavaDoc name,
1549                           int defaultValue)
1550    {
1551        return this.getIntAttribute(name, defaultValue);
1552    }
1553
1554
1555    /**
1556     * Returns an attribute.
1557     *
1558     * @param name name
1559     * @param defaultValue default value
1560     * @return attribute
1561     * @deprecated Use {@link #getDoubleAttribute(java.lang.String, double)
1562     * getDoubleAttribute} instead.
1563     */

1564    public double getProperty(String JavaDoc name,
1565                              double defaultValue)
1566    {
1567        return this.getDoubleAttribute(name, defaultValue);
1568    }
1569
1570
1571    /**
1572     * Returns an attribute.
1573     *
1574     * @param key key
1575     * @param trueValue true value
1576     * @param falseValue fasle value
1577     * @param defaultValue default value
1578     * @return attribute
1579     *
1580     * @deprecated Use {@link #getBooleanAttribute(java.lang.String,
1581     * java.lang.String, java.lang.String, boolean)
1582     * getBooleanAttribute} instead.
1583     */

1584    public boolean getProperty(String JavaDoc key,
1585                               String JavaDoc trueValue,
1586                               String JavaDoc falseValue,
1587                               boolean defaultValue)
1588    {
1589        return this.getBooleanAttribute(key, trueValue, falseValue,
1590                                        defaultValue);
1591    }
1592
1593
1594    /**
1595     * Returns an attribute by looking up a key in a hashtable.
1596     *
1597     * @param name name
1598     * @param valueSet value set
1599     * @param defaultKey default key
1600     * @return value
1601     *
1602     * @deprecated Use {@link #getAttribute(java.lang.String,
1603     * java.util.Hashtable, java.lang.String, boolean)
1604     * getAttribute} instead.
1605     */

1606    public Object JavaDoc getProperty(String JavaDoc name,
1607                              Hashtable JavaDoc valueSet,
1608                              String JavaDoc defaultKey)
1609    {
1610        return this.getAttribute(name, valueSet, defaultKey, false);
1611    }
1612
1613
1614    /**
1615     * Returns an attribute by looking up a key in a hashtable.
1616     *
1617     * @param name name
1618     * @param valueSet value set
1619     * @param defaultKey default key
1620     * @return attribute
1621     *
1622     * @deprecated Use {@link #getStringAttribute(java.lang.String,
1623     * java.util.Hashtable, java.lang.String, boolean)
1624     * getStringAttribute} instead.
1625     */

1626    public String JavaDoc getStringProperty(String JavaDoc name,
1627                                    Hashtable JavaDoc valueSet,
1628                                    String JavaDoc defaultKey)
1629    {
1630        return this.getStringAttribute(name, valueSet, defaultKey, false);
1631    }
1632
1633
1634    /**
1635     * Returns an attribute by looking up a key in a hashtable.
1636     *
1637     * @param name name
1638     * @param valueSet value set
1639     * @param defaultKey default key
1640     * @return attribute
1641     * @deprecated Use {@link #getIntAttribute(java.lang.String,
1642     * java.util.Hashtable, java.lang.String, boolean)
1643     * getIntAttribute} instead.
1644     */

1645    public int getSpecialIntProperty(String JavaDoc name,
1646                                     Hashtable JavaDoc valueSet,
1647                                     String JavaDoc defaultKey)
1648    {
1649        return this.getIntAttribute(name, valueSet, defaultKey, true);
1650    }
1651
1652
1653    /**
1654     * Returns an attribute by looking up a key in a hashtable.
1655     *
1656     * @param name name
1657     * @param valueSet value set
1658     * @param defaultKey default value
1659     * @return attribute
1660     *
1661     * @deprecated Use {@link #getDoubleAttribute(java.lang.String,
1662     * java.util.Hashtable, java.lang.String, boolean)
1663     * getDoubleAttribute} instead.
1664     */

1665    public double getSpecialDoubleProperty(String JavaDoc name,
1666                                           Hashtable JavaDoc valueSet,
1667                                           String JavaDoc defaultKey)
1668    {
1669        return this.getDoubleAttribute(name, valueSet, defaultKey, true);
1670    }
1671
1672
1673    /**
1674     * Returns the name of the element.
1675     *
1676     * @return name of element
1677     * @see XMLElement#setName(java.lang.String) setName(String)
1678     */

1679    public String JavaDoc getName()
1680    {
1681        return this.name;
1682    }
1683
1684
1685    /**
1686     * Returns the name of the element.
1687     *
1688     * @return name of element
1689     * @deprecated Use {@link #getName() getName} instead.
1690     */

1691    public String JavaDoc getTagName()
1692    {
1693        return this.getName();
1694    }
1695
1696
1697    /**
1698     * Reads one XML element from a java.io.Reader and parses it.
1699     *
1700     * @param reader
1701     * The reader from which to retrieve the XML data.
1702     *
1703     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1704     * <ul><li><code>reader != null</code>
1705     * <li><code>reader</code> is not closed
1706     * </ul></dd></dl>
1707     *
1708     * <dl><dt><b>Postconditions:</b></dt><dd>
1709     * <ul><li>the state of the receiver is updated to reflect the XML element
1710     * parsed from the reader
1711     * <li>the reader points to the first character following the last
1712     * '&gt;' character of the XML element
1713     * </ul></dd></dl><dl>
1714     *
1715     * @throws java.io.IOException
1716     * If an error occured while reading the input.
1717     * @throws XMLParseException
1718     * If an error occured while parsing the read data.
1719     */

1720    public void parseFromReader(Reader JavaDoc reader)
1721    throws IOException JavaDoc, XMLParseException
1722    {
1723        this.parseFromReader(reader, /*startingLineNr*/ 1);
1724    }
1725
1726
1727    /**
1728     * Reads one XML element from a java.io.Reader and parses it.
1729     *
1730     * @param reader
1731     * The reader from which to retrieve the XML data.
1732     * @param startingLineNr
1733     * The line number of the first line in the data.
1734     *
1735     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1736     * <ul><li><code>reader != null</code>
1737     * <li><code>reader</code> is not closed
1738     * </ul></dd></dl>
1739     *
1740     * <dl><dt><b>Postconditions:</b></dt><dd>
1741     * <ul><li>the state of the receiver is updated to reflect the XML element
1742     * parsed from the reader
1743     * <li>the reader points to the first character following the last
1744     * '&gt;' character of the XML element
1745     * </ul></dd></dl><dl>
1746     *
1747     * @throws java.io.IOException
1748     * If an error occured while reading the input.
1749     * @throws XMLParseException
1750     * If an error occured while parsing the read data.
1751     */

1752    public void parseFromReader(Reader JavaDoc reader,
1753                                int startingLineNr)
1754        throws IOException JavaDoc, XMLParseException
1755    {
1756        this.charReadTooMuch = '\0';
1757        this.reader = reader;
1758        this.parserLineNr = startingLineNr;
1759
1760        for (;;) {
1761            char ch = this.scanWhitespace();
1762
1763            if (ch != '<') {
1764                throw this.expectedInput("<");
1765            }
1766
1767            ch = this.readChar();
1768
1769            if ((ch == '!') || (ch == '?')) {
1770                this.skipSpecialTag(0);
1771            } else {
1772                this.unreadChar(ch);
1773                this.scanElement(this);
1774                return;
1775            }
1776        }
1777    }
1778
1779
1780    /**
1781     * Reads one XML element from a String and parses it.
1782     *
1783     * @param string
1784     * The string.
1785     *
1786     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1787     * <ul><li><code>string != null</code>
1788     * <li><code>string.length() &gt; 0</code>
1789     * </ul></dd></dl>
1790     *
1791     * <dl><dt><b>Postconditions:</b></dt><dd>
1792     * <ul><li>the state of the receiver is updated to reflect the XML element
1793     * parsed from the reader
1794     * </ul></dd></dl><dl>
1795     *
1796     * @throws XMLParseException
1797     * If an error occured while parsing the string.
1798     */

1799    public void parseString(String JavaDoc string)
1800        throws XMLParseException
1801    {
1802        try {
1803            this.parseFromReader(new StringReader JavaDoc(string),
1804                                 /*startingLineNr*/ 1);
1805        } catch (IOException JavaDoc e) {
1806            // Java exception handling suxx
1807
}
1808    }
1809
1810
1811    /**
1812     * Reads one XML element from a String and parses it.
1813     *
1814     * @param string
1815     * The string.
1816     * @param offset
1817     * The first character in <code>string</code> to scan.
1818     *
1819     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1820     * <ul><li><code>string != null</code>
1821     * <li><code>offset &lt; string.length()</code>
1822     * <li><code>offset &gt;= 0</code>
1823     * </ul></dd></dl>
1824     *
1825     * <dl><dt><b>Postconditions:</b></dt><dd>
1826     * <ul><li>the state of the receiver is updated to reflect the XML element
1827     * parsed from the reader
1828     * </ul></dd></dl><dl>
1829     *
1830     * @throws XMLParseException
1831     * If an error occured while parsing the string.
1832     */

1833    public void parseString(String JavaDoc string,
1834                            int offset)
1835        throws XMLParseException
1836    {
1837        this.parseString(string.substring(offset));
1838    }
1839
1840
1841    /**
1842     * Reads one XML element from a String and parses it.
1843     *
1844     * @param string
1845     * The string.
1846     * @param offset
1847     * The first character in <code>string</code> to scan.
1848     * @param end
1849     * The character where to stop scanning.
1850     * This character is not scanned.
1851     *
1852     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1853     * <ul><li><code>string != null</code>
1854     * <li><code>end &lt;= string.length()</code>
1855     * <li><code>offset &lt; end</code>
1856     * <li><code>offset &gt;= 0</code>
1857     * </ul></dd></dl>
1858     *
1859     * <dl><dt><b>Postconditions:</b></dt><dd>
1860     * <ul><li>the state of the receiver is updated to reflect the XML element
1861     * parsed from the reader
1862     * </ul></dd></dl><dl>
1863     *
1864     * @throws XMLParseException
1865     * If an error occured while parsing the string.
1866     */

1867    public void parseString(String JavaDoc string,
1868                            int offset,
1869                            int end)
1870        throws XMLParseException
1871    {
1872        this.parseString(string.substring(offset, end));
1873    }
1874
1875
1876    /**
1877     * Reads one XML element from a String and parses it.
1878     *
1879     * @param string
1880     * The string.
1881     * @param offset
1882     * The first character in <code>string</code> to scan.
1883     * @param end
1884     * The character where to stop scanning.
1885     * This character is not scanned.
1886     * @param startingLineNr
1887     * The line number of the first line in the data.
1888     *
1889     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1890     * <ul><li><code>string != null</code>
1891     * <li><code>end &lt;= string.length()</code>
1892     * <li><code>offset &lt; end</code>
1893     * <li><code>offset &gt;= 0</code>
1894     * </ul></dd></dl>
1895     *
1896     * <dl><dt><b>Postconditions:</b></dt><dd>
1897     * <ul><li>the state of the receiver is updated to reflect the XML element
1898     * parsed from the reader
1899     * </ul></dd></dl><dl>
1900     *
1901     * @throws XMLParseException
1902     * If an error occured while parsing the string.
1903     */

1904    public void parseString(String JavaDoc string,
1905                            int offset,
1906                            int end,
1907                            int startingLineNr)
1908        throws XMLParseException
1909    {
1910        string = string.substring(offset, end);
1911        try {
1912            this.parseFromReader(new StringReader JavaDoc(string), startingLineNr);
1913        } catch (IOException JavaDoc e) {
1914            // Java exception handling suxx
1915
}
1916    }
1917
1918
1919    /**
1920     * Reads one XML element from a char array and parses it.
1921     *
1922     * @param input
1923     * The input.
1924     * @param offset
1925     * The first character in <code>string</code> to scan.
1926     * @param end
1927     * The character where to stop scanning.
1928     * This character is not scanned.
1929     *
1930     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1931     * <ul><li><code>input != null</code>
1932     * <li><code>end &lt;= input.length</code>
1933     * <li><code>offset &lt; end</code>
1934     * <li><code>offset &gt;= 0</code>
1935     * </ul></dd></dl>
1936     *
1937     * <dl><dt><b>Postconditions:</b></dt><dd>
1938     * <ul><li>the state of the receiver is updated to reflect the XML element
1939     * parsed from the reader
1940     * </ul></dd></dl><dl>
1941     *
1942     * @throws XMLParseException
1943     * If an error occured while parsing the string.
1944     */

1945    public void parseCharArray(char[] input,
1946                               int offset,
1947                               int end)
1948        throws XMLParseException
1949    {
1950        this.parseCharArray(input, offset, end, /*startingLineNr*/ 1);
1951    }
1952
1953
1954    /**
1955     * Reads one XML element from a char array and parses it.
1956     *
1957     * @param input
1958     * The input.
1959     * @param offset
1960     * The first character in <code>string</code> to scan.
1961     * @param end
1962     * The character where to stop scanning.
1963     * This character is not scanned.
1964     * @param startingLineNr
1965     * The line number of the first line in the data.
1966     *
1967     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
1968     * <ul><li><code>input != null</code>
1969     * <li><code>end &lt;= input.length</code>
1970     * <li><code>offset &lt; end</code>
1971     * <li><code>offset &gt;= 0</code>
1972     * </ul></dd></dl>
1973     *
1974     * <dl><dt><b>Postconditions:</b></dt><dd>
1975     * <ul><li>the state of the receiver is updated to reflect the XML element
1976     * parsed from the reader
1977     * </ul></dd></dl><dl>
1978     *
1979     * @throws XMLParseException
1980     * If an error occured while parsing the string.
1981     */

1982    public void parseCharArray(char[] input,
1983                               int offset,
1984                               int end,
1985                               int startingLineNr)
1986        throws XMLParseException
1987    {
1988        try {
1989            Reader JavaDoc reader = new CharArrayReader JavaDoc(input, offset, end);
1990            this.parseFromReader(reader, startingLineNr);
1991        } catch (IOException JavaDoc e) {
1992            // This exception will never happen.
1993
}
1994    }
1995
1996
1997    /**
1998     * Removes a child element.
1999     *
2000     * @param child
2001     * The child element to remove.
2002     *
2003     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2004     * <ul><li><code>child != null</code>
2005     * <li><code>child</code> is a child element of the receiver
2006     * </ul></dd></dl>
2007     *
2008     * <dl><dt><b>Postconditions:</b></dt><dd>
2009     * <ul><li>countChildren() => old.countChildren() - 1
2010     * <li>enumerateChildren() => old.enumerateChildren() - child
2011     * <li>getChildren() => old.enumerateChildren() - child
2012     * </ul></dd></dl><dl>
2013     *
2014     * @see XMLElement#addChild(XMLElement)
2015     * addChild(XMLElement)
2016     * @see XMLElement#countChildren()
2017     * @see XMLElement#enumerateChildren()
2018     * @see XMLElement#getChildren()
2019     */

2020    public void removeChild(XMLElement child)
2021    {
2022        this.children.removeElement(child);
2023    }
2024
2025
2026    /**
2027     * Removes an attribute.
2028     *
2029     * @param name
2030     * The name of the attribute.
2031     *
2032     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2033     * <ul><li><code>name != null</code>
2034     * <li><code>name</code> is a valid XML identifier
2035     * </ul></dd></dl>
2036     *
2037     * <dl><dt><b>Postconditions:</b></dt><dd>
2038     * <ul><li>enumerateAttributeNames()
2039     * => old.enumerateAttributeNames() - name
2040     * <li>getAttribute(name) => <code>null</code>
2041     * </ul></dd></dl><dl>
2042     *
2043     * @see XMLElement#enumerateAttributeNames()
2044     * @see XMLElement#setDoubleAttribute(java.lang.String, double)
2045     * setDoubleAttribute(String, double)
2046     * @see XMLElement#setIntAttribute(java.lang.String, int)
2047     * setIntAttribute(String, int)
2048     * @see XMLElement#setAttribute(java.lang.String, java.lang.Object)
2049     * setAttribute(String, Object)
2050     * @see XMLElement#getAttribute(java.lang.String)
2051     * getAttribute(String)
2052     * @see XMLElement#getAttribute(java.lang.String, java.lang.Object)
2053     * getAttribute(String, Object)
2054     * @see XMLElement#getAttribute(java.lang.String,
2055     * java.util.Hashtable,
2056     * java.lang.String, boolean)
2057     * getAttribute(String, Hashtable, String, boolean)
2058     * @see XMLElement#getStringAttribute(java.lang.String)
2059     * getStringAttribute(String)
2060     * @see XMLElement#getStringAttribute(java.lang.String,
2061     * java.lang.String)
2062     * getStringAttribute(String, String)
2063     * @see XMLElement#getStringAttribute(java.lang.String,
2064     * java.util.Hashtable,
2065     * java.lang.String, boolean)
2066     * getStringAttribute(String, Hashtable, String, boolean)
2067     * @see XMLElement#getIntAttribute(java.lang.String)
2068     * getIntAttribute(String)
2069     * @see XMLElement#getIntAttribute(java.lang.String, int)
2070     * getIntAttribute(String, int)
2071     * @see XMLElement#getIntAttribute(java.lang.String,
2072     * java.util.Hashtable,
2073     * java.lang.String, boolean)
2074     * getIntAttribute(String, Hashtable, String, boolean)
2075     * @see XMLElement#getDoubleAttribute(java.lang.String)
2076     * getDoubleAttribute(String)
2077     * @see XMLElement#getDoubleAttribute(java.lang.String, double)
2078     * getDoubleAttribute(String, double)
2079     * @see XMLElement#getDoubleAttribute(java.lang.String,
2080     * java.util.Hashtable,
2081     * java.lang.String, boolean)
2082     * getDoubleAttribute(String, Hashtable, String, boolean)
2083     * @see XMLElement#getBooleanAttribute(java.lang.String,
2084     * java.lang.String,
2085     * java.lang.String, boolean)
2086     * getBooleanAttribute(String, String, String, boolean)
2087     */

2088    public void removeAttribute(String JavaDoc name)
2089    {
2090        if (this.ignoreCase) {
2091            name = name.toUpperCase();
2092        }
2093        this.attributes.remove(name);
2094    }
2095
2096
2097    /**
2098     * Removes an attribute.
2099     *
2100     * @param name
2101     * The name of the attribute.
2102     *
2103     * @deprecated Use {@link #removeAttribute(java.lang.String)
2104     * removeAttribute} instead.
2105     */

2106    public void removeProperty(String JavaDoc name)
2107    {
2108        this.removeAttribute(name);
2109    }
2110
2111
2112    /**
2113     * Removes an attribute.
2114     *
2115     * @param name
2116     * The name of the attribute.
2117     *
2118     * @deprecated Use {@link #removeAttribute(java.lang.String)
2119     * removeAttribute} instead.
2120     */

2121    public void removeChild(String JavaDoc name)
2122    {
2123        this.removeAttribute(name);
2124    }
2125
2126
2127    /**
2128     * Creates a new similar XML element.
2129     * <P>
2130     * You should override this method when subclassing XMLElement.
2131     *
2132     * @return element
2133     */

2134    protected XMLElement createAnotherElement()
2135    {
2136        return new XMLElement(this.entities,
2137                              this.ignoreWhitespace,
2138                              false,
2139                              this.ignoreCase);
2140    }
2141
2142
2143    /**
2144     * Changes the content string.
2145     *
2146     * @param content
2147     * The new content string.
2148     */

2149    public void setContent(String JavaDoc content)
2150    {
2151        this.contents = content;
2152    }
2153
2154
2155    /**
2156     * Changes the name of the element.
2157     *
2158     * @param name
2159     * The new name.
2160     *
2161     * @deprecated Use {@link #setName(java.lang.String) setName} instead.
2162     */

2163    public void setTagName(String JavaDoc name)
2164    {
2165        this.setName(name);
2166    }
2167
2168
2169    /**
2170     * Changes the name of the element.
2171     *
2172     * @param name
2173     * The new name.
2174     *
2175     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2176     * <ul><li><code>name != null</code>
2177     * <li><code>name</code> is a valid XML identifier
2178     * </ul></dd></dl>
2179     *
2180     * @see XMLElement#getName()
2181     */

2182    public void setName(String JavaDoc name)
2183    {
2184        this.name = name;
2185    }
2186
2187
2188    /**
2189     * Writes the XML element to a string.
2190     *
2191     * @see XMLElement#write(java.io.Writer) write(Writer)
2192     */

2193    public String JavaDoc toString()
2194    {
2195        try {
2196            ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc();
2197            OutputStreamWriter JavaDoc writer = new OutputStreamWriter JavaDoc(out);
2198            this.write(writer);
2199            writer.flush();
2200            return new String JavaDoc(out.toByteArray());
2201        } catch (IOException JavaDoc e) {
2202            // Java exception handling suxx
2203
return super.toString();
2204        }
2205    }
2206
2207
2208    /**
2209     * Writes the XML element to a writer.
2210     *
2211     * @param writer
2212     * The writer to write the XML data to.
2213     *
2214     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2215     * <ul><li><code>writer != null</code>
2216     * <li><code>writer</code> is not closed
2217     * </ul></dd></dl>
2218     *
2219     * @throws java.io.IOException
2220     * If the data could not be written to the writer.
2221     *
2222     * @see XMLElement#toString()
2223     */

2224    public void write(Writer JavaDoc writer)
2225        throws IOException JavaDoc
2226    {
2227        if (this.name == null) {
2228            this.writeEncoded(writer, this.contents);
2229            return;
2230        }
2231        writer.write('<');
2232        writer.write(this.name);
2233        if (! this.attributes.isEmpty()) {
2234            Enumeration JavaDoc e = this.attributes.keys();
2235            while (e.hasMoreElements()) {
2236                writer.write(' ');
2237                String JavaDoc key = (String JavaDoc) e.nextElement();
2238                String JavaDoc value = (String JavaDoc) this.attributes.get(key);
2239                writer.write(key);
2240                writer.write('='); writer.write('"');
2241                this.writeEncoded(writer, value);
2242                writer.write('"');
2243            }
2244        }
2245        if ((this.contents != null) && (this.contents.length() > 0)) {
2246            writer.write('>');
2247            this.writeEncoded(writer, this.contents);
2248            writer.write('<'); writer.write('/');
2249            writer.write(this.name);
2250            writer.write('>');
2251        } else if (this.children.isEmpty()) {
2252            writer.write('/'); writer.write('>');
2253        } else {
2254            writer.write('>');
2255            Enumeration JavaDoc e = this.enumerateChildren();
2256            while (e.hasMoreElements()) {
2257                XMLElement child = (XMLElement) e.nextElement();
2258                child.write(writer);
2259            }
2260            writer.write('<'); writer.write('/');
2261            writer.write(this.name);
2262            writer.write('>');
2263        }
2264    }
2265
2266
2267    /**
2268     * Writes a string encoded to a writer.
2269     *
2270     * @param writer
2271     * The writer to write the XML data to.
2272     * @param str
2273     * The string to write encoded.
2274     * @throws IOException on any error
2275     *
2276     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2277     * <ul><li><code>writer != null</code>
2278     * <li><code>writer</code> is not closed
2279     * <li><code>str != null</code>
2280     * </ul></dd></dl>
2281     */

2282    protected void writeEncoded(Writer JavaDoc writer,
2283                                String JavaDoc str)
2284        throws IOException JavaDoc
2285    {
2286        for (int i = 0; i < str.length(); i += 1) {
2287            char ch = str.charAt(i);
2288            switch (ch) {
2289                case '<':
2290                    writer.write('&'); writer.write('l'); writer.write('t');
2291                    writer.write(';');
2292                    break;
2293                case '>':
2294                    writer.write('&'); writer.write('g'); writer.write('t');
2295                    writer.write(';');
2296                    break;
2297                case '&':
2298                    writer.write('&'); writer.write('a'); writer.write('m');
2299                    writer.write('p'); writer.write(';');
2300                    break;
2301                case '"':
2302                    writer.write('&'); writer.write('q'); writer.write('u');
2303                    writer.write('o'); writer.write('t'); writer.write(';');
2304                    break;
2305                case '\'':
2306                    writer.write('&'); writer.write('a'); writer.write('p');
2307                    writer.write('o'); writer.write('s'); writer.write(';');
2308                    break;
2309                default:
2310                    int unicode = (int) ch;
2311                    if ((unicode < 32) || (unicode > 126)) {
2312                        writer.write('&'); writer.write('#');
2313                        writer.write('x');
2314                        writer.write(Integer.toString(unicode, 16));
2315                        writer.write(';');
2316                    } else {
2317                        writer.write(ch);
2318                    }
2319            }
2320        }
2321    }
2322
2323
2324    /**
2325     * Scans an identifier from the current reader.
2326     * The scanned identifier is appended to <code>result</code>.
2327     *
2328     * @param result
2329     * The buffer in which the scanned identifier will be put.
2330     * @throws IOException on any error
2331     *
2332     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2333     * <ul><li><code>result != null</code>
2334     * <li>The next character read from the reader is a valid first
2335     * character of an XML identifier.
2336     * </ul></dd></dl>
2337     *
2338     * <dl><dt><b>Postconditions:</b></dt><dd>
2339     * <ul><li>The next character read from the reader won't be an identifier
2340     * character.
2341     * </ul></dd></dl><dl>
2342     */

2343    protected void scanIdentifier(StringBuffer JavaDoc result)
2344        throws IOException JavaDoc
2345    {
2346        for (;;) {
2347            char ch = this.readChar();
2348            if (((ch < 'A') || (ch > 'Z')) && ((ch < 'a') || (ch > 'z'))
2349                && ((ch < '0') || (ch > '9')) && (ch != '_') && (ch != '.')
2350                && (ch != ':') && (ch != '-') && (ch <= '\u007E')) {
2351                this.unreadChar(ch);
2352                return;
2353            }
2354            result.append(ch);
2355        }
2356    }
2357
2358
2359    /**
2360     * This method scans an identifier from the current reader.
2361     *
2362     * @return the next character following the whitespace.
2363     * @throws IOException on any error
2364     */

2365    protected char scanWhitespace()
2366        throws IOException JavaDoc
2367    {
2368        for (;;) {
2369            char ch = this.readChar();
2370            switch (ch) {
2371                case ' ':
2372                case '\t':
2373                case '\n':
2374                case '\r':
2375                    break;
2376                default:
2377                    return ch;
2378            }
2379        }
2380    }
2381
2382
2383    /**
2384     * This method scans an identifier from the current reader.
2385     * The scanned whitespace is appended to <code>result</code>.
2386     *
2387     * @param result result
2388     * @return the next character following the whitespace.
2389     * @throws IOException on any error
2390     *
2391     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2392     * <ul><li><code>result != null</code>
2393     * </ul></dd></dl>
2394     */

2395    protected char scanWhitespace(StringBuffer JavaDoc result)
2396        throws IOException JavaDoc
2397    {
2398        for (;;) {
2399            char ch = this.readChar();
2400            switch (ch) {
2401                case ' ':
2402                case '\t':
2403                case '\n':
2404                    result.append(ch);
2405                case '\r':
2406                    break;
2407                default:
2408                    return ch;
2409            }
2410        }
2411    }
2412
2413
2414    /**
2415     * This method scans a delimited string from the current reader.
2416     * The scanned string without delimiters is appended to
2417     * <code>string</code>.
2418     *
2419     * @param string
2420     * @throws IOException
2421     *
2422     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2423     * <ul><li><code>string != null</code>
2424     * <li>the next char read is the string delimiter
2425     * </ul></dd></dl>
2426     */

2427    protected void scanString(StringBuffer JavaDoc string)
2428        throws IOException JavaDoc
2429    {
2430        char delimiter = this.readChar();
2431        if ((delimiter != '\'') && (delimiter != '"')) {
2432            throw this.expectedInput("' or \"");
2433        }
2434        for (;;) {
2435            char ch = this.readChar();
2436            if (ch == delimiter) {
2437                return;
2438            } else if (ch == '&') {
2439                this.resolveEntity(string);
2440            } else {
2441                string.append(ch);
2442            }
2443        }
2444    }
2445
2446
2447    /**
2448     * Scans a #PCDATA element. CDATA sections and entities are resolved.
2449     * The next &lt; char is skipped.
2450     * The scanned data is appended to <code>data</code>.
2451     *
2452     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2453     * <ul><li><code>data != null</code>
2454     * </ul></dd></dl>
2455     *
2456     * @param data data
2457     * @throws IOException on any error
2458     */

2459    protected void scanPCData(StringBuffer JavaDoc data)
2460        throws IOException JavaDoc
2461    {
2462        for (;;) {
2463            char ch = this.readChar();
2464            if (ch == '<') {
2465                ch = this.readChar();
2466                if (ch == '!') {
2467                    this.checkCDATA(data);
2468                } else {
2469                    this.unreadChar(ch);
2470                    return;
2471                }
2472            } else if (ch == '&') {
2473                this.resolveEntity(data);
2474            } else {
2475                data.append(ch);
2476            }
2477        }
2478    }
2479
2480
2481    /**
2482     * Scans a special tag and if the tag is a CDATA section, append its
2483     * content to <code>buf</code>.
2484     *
2485     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2486     * <ul><li><code>buf != null</code>
2487     * <li>The first &lt; has already been read.
2488     * </ul></dd></dl>
2489     *
2490     * @param buf buf
2491     * @return is CDATA
2492     * @throws IOException
2493     */

2494    protected boolean checkCDATA(StringBuffer JavaDoc buf)
2495        throws IOException JavaDoc
2496    {
2497        char ch = this.readChar();
2498        if (ch != '[') {
2499            this.unreadChar(ch);
2500            this.skipSpecialTag(0);
2501            return false;
2502        } else if (! this.checkLiteral("CDATA[")) {
2503            this.skipSpecialTag(1); // one [ has already been read
2504
return false;
2505        } else {
2506            int delimiterCharsSkipped = 0;
2507            while (delimiterCharsSkipped < 3) {
2508                ch = this.readChar();
2509                switch (ch) {
2510                    case ']':
2511                        if (delimiterCharsSkipped < 2) {
2512                            delimiterCharsSkipped += 1;
2513                        } else {
2514                            buf.append(']');
2515                            buf.append(']');
2516                            delimiterCharsSkipped = 0;
2517                        }
2518                        break;
2519                    case '>':
2520                        if (delimiterCharsSkipped < 2) {
2521                            for (int i = 0; i < delimiterCharsSkipped; i++) {
2522                                buf.append(']');
2523                            }
2524                            delimiterCharsSkipped = 0;
2525                            buf.append('>');
2526                        } else {
2527                            delimiterCharsSkipped = 3;
2528                        }
2529                        break;
2530                    default:
2531                        for (int i = 0; i < delimiterCharsSkipped; i += 1) {
2532                            buf.append(']');
2533                        }
2534                        buf.append(ch);
2535                        delimiterCharsSkipped = 0;
2536                }
2537            }
2538            return true;
2539        }
2540    }
2541
2542
2543    /**
2544     * Skips a comment.
2545     *
2546     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2547     * <ul><li>The first &lt;!-- has already been read.
2548     * </ul></dd></dl>
2549     *
2550     * @throws IOException on any error
2551     */

2552    protected void skipComment()
2553        throws IOException JavaDoc
2554    {
2555        int dashesToRead = 2;
2556        while (dashesToRead > 0) {
2557            char ch = this.readChar();
2558            if (ch == '-') {
2559                dashesToRead -= 1;
2560            } else {
2561                dashesToRead = 2;
2562            }
2563        }
2564        if (this.readChar() != '>') {
2565            throw this.expectedInput(">");
2566        }
2567    }
2568
2569
2570    /**
2571     * Skips a special tag or comment.
2572     *
2573     * @param bracketLevel The number of open square brackets ([) that have
2574     * already been read.
2575     *
2576     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2577     * <ul><li>The first &lt;! has already been read.
2578     * <li><code>bracketLevel >= 0</code>
2579     * </ul></dd></dl>
2580     *
2581     * @throws IOException on any error
2582     */

2583    protected void skipSpecialTag(int bracketLevel)
2584        throws IOException JavaDoc
2585    {
2586        int tagLevel = 1; // <
2587
char stringDelimiter = '\0';
2588        if (bracketLevel == 0) {
2589            char ch = this.readChar();
2590            if (ch == '[') {
2591                bracketLevel += 1;
2592            } else if (ch == '-') {
2593                ch = this.readChar();
2594                if (ch == '[') {
2595                    bracketLevel += 1;
2596                } else if (ch == ']') {
2597                    bracketLevel -= 1;
2598                } else if (ch == '-') {
2599                    this.skipComment();
2600                    return;
2601                }
2602            }
2603        }
2604        while (tagLevel > 0) {
2605            char ch = this.readChar();
2606            if (stringDelimiter == '\0') {
2607                if ((ch == '"') || (ch == '\'')) {
2608                    stringDelimiter = ch;
2609                } else if (bracketLevel <= 0) {
2610                    if (ch == '<') {
2611                        tagLevel += 1;
2612                    } else if (ch == '>') {
2613                        tagLevel -= 1;
2614                    }
2615                }
2616                if (ch == '[') {
2617                    bracketLevel += 1;
2618                } else if (ch == ']') {
2619                    bracketLevel -= 1;
2620                }
2621            } else {
2622                if (ch == stringDelimiter) {
2623                    stringDelimiter = '\0';
2624                }
2625            }
2626        }
2627    }
2628
2629
2630    /**
2631     * Scans the data for literal text.
2632     * Scanning stops when a character does not match or after the complete
2633     * text has been checked, whichever comes first.
2634     *
2635     * @param literal the literal to check.
2636     *
2637     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2638     * <ul><li><code>literal != null</code>
2639     * </ul></dd></dl>
2640     *
2641     * @return literal
2642     * @throws IOException
2643     */

2644    protected boolean checkLiteral(String JavaDoc literal)
2645        throws IOException JavaDoc
2646    {
2647        int length = literal.length();
2648        for (int i = 0; i < length; i += 1) {
2649            if (this.readChar() != literal.charAt(i)) {
2650                return false;
2651            }
2652        }
2653        return true;
2654    }
2655
2656
2657    /**
2658     * Reads a character from a reader.
2659     *
2660     * @return character
2661     * @throws IOException
2662     */

2663    protected char readChar()
2664        throws IOException JavaDoc
2665    {
2666        if (this.charReadTooMuch != '\0') {
2667            char ch = this.charReadTooMuch;
2668            this.charReadTooMuch = '\0';
2669            return ch;
2670        } else {
2671            int i = this.reader.read();
2672            if (i < 0) {
2673                throw this.unexpectedEndOfData();
2674            } else if (i == 10) {
2675                this.parserLineNr += 1;
2676                return '\n';
2677            } else {
2678                return (char) i;
2679            }
2680        }
2681    }
2682
2683
2684    /**
2685     * Scans an XML element.
2686     *
2687     * @param elt The element that will contain the result.
2688     *
2689     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2690     * <ul><li>The first &lt; has already been read.
2691     * <li><code>elt != null</code>
2692     * </ul></dd></dl>
2693     *
2694     * @throws IOException on any error
2695     */

2696    protected void scanElement(XMLElement elt)
2697        throws IOException JavaDoc
2698    {
2699        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
2700        this.scanIdentifier(buf);
2701        String JavaDoc name = buf.toString();
2702        elt.setName(name);
2703        char ch = this.scanWhitespace();
2704        while ((ch != '>') && (ch != '/')) {
2705            buf.setLength(0);
2706            this.unreadChar(ch);
2707            this.scanIdentifier(buf);
2708            String JavaDoc key = buf.toString();
2709            ch = this.scanWhitespace();
2710            if (ch != '=') {
2711                throw this.expectedInput("=");
2712            }
2713            this.unreadChar(this.scanWhitespace());
2714            buf.setLength(0);
2715            this.scanString(buf);
2716            elt.setAttribute(key, buf);
2717            ch = this.scanWhitespace();
2718        }
2719        if (ch == '/') {
2720            ch = this.readChar();
2721            if (ch != '>') {
2722                throw this.expectedInput(">");
2723            }
2724            return;
2725        }
2726        buf.setLength(0);
2727        ch = this.scanWhitespace(buf);
2728        if (ch != '<') {
2729            this.unreadChar(ch);
2730            this.scanPCData(buf);
2731        } else {
2732            for (;;) {
2733                ch = this.readChar();
2734                if (ch == '!') {
2735                    if (this.checkCDATA(buf)) {
2736                        this.scanPCData(buf);
2737                        break;
2738                    } else {
2739                        ch = this.scanWhitespace(buf);
2740                        if (ch != '<') {
2741                            this.unreadChar(ch);
2742                            this.scanPCData(buf);
2743                            break;
2744                        }
2745                    }
2746                } else {
2747                    buf.setLength(0);
2748                    break;
2749                }
2750            }
2751        }
2752        if (buf.length() == 0) {
2753            while (ch != '/') {
2754                if (ch == '!') {
2755                    ch = this.readChar();
2756                    if (ch != '-') {
2757                        throw this.expectedInput("Comment or Element");
2758                    }
2759                    ch = this.readChar();
2760                    if (ch != '-') {
2761                        throw this.expectedInput("Comment or Element");
2762                    }
2763                    this.skipComment();
2764                } else {
2765                    this.unreadChar(ch);
2766                    XMLElement child = this.createAnotherElement();
2767                    this.scanElement(child);
2768                    elt.addChild(child);
2769                }
2770                ch = this.scanWhitespace();
2771                if (ch != '<') {
2772                    throw this.expectedInput("<");
2773                }
2774                ch = this.readChar();
2775            }
2776            this.unreadChar(ch);
2777        } else {
2778            if (this.ignoreWhitespace) {
2779                elt.setContent(buf.toString().trim());
2780            } else {
2781                elt.setContent(buf.toString());
2782            }
2783        }
2784        ch = this.readChar();
2785        if (ch != '/') {
2786            throw this.expectedInput("/");
2787        }
2788        this.unreadChar(this.scanWhitespace());
2789        if (! this.checkLiteral(name)) {
2790            throw this.expectedInput(name);
2791        }
2792        if (this.scanWhitespace() != '>') {
2793            throw this.expectedInput(">");
2794        }
2795    }
2796
2797
2798    /**
2799     * Resolves an entity. The name of the entity is read from the reader.
2800     * The value of the entity is appended to <code>buf</code>.
2801     *
2802     * @param buf Where to put the entity value.
2803     *
2804     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2805     * <ul><li>The first &amp; has already been read.
2806     * <li><code>buf != null</code>
2807     * </ul></dd></dl>
2808     *
2809     * @throws IOException on any error
2810     */

2811    protected void resolveEntity(StringBuffer JavaDoc buf)
2812        throws IOException JavaDoc
2813    {
2814        char ch = '\0';
2815        StringBuffer JavaDoc keyBuf = new StringBuffer JavaDoc();
2816        for (;;) {
2817            ch = this.readChar();
2818            if (ch == ';') {
2819                break;
2820            }
2821            keyBuf.append(ch);
2822        }
2823        String JavaDoc key = keyBuf.toString();
2824        if (key.charAt(0) == '#') {
2825            try {
2826                if (key.charAt(1) == 'x') {
2827                    ch = (char) Integer.parseInt(key.substring(2), 16);
2828                } else {
2829                    ch = (char) Integer.parseInt(key.substring(1), 10);
2830                }
2831            } catch (NumberFormatException JavaDoc e) {
2832                throw this.unknownEntity(key);
2833            }
2834            buf.append(ch);
2835        } else {
2836            char[] value = (char[]) this.entities.get(key);
2837            if (value == null) {
2838                throw this.unknownEntity(key);
2839            }
2840            buf.append(value);
2841        }
2842    }
2843
2844
2845    /**
2846     * Pushes a character back to the read-back buffer.
2847     *
2848     * @param ch The character to push back.
2849     *
2850     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2851     * <ul><li>The read-back buffer is empty.
2852     * <li><code>ch != '\0'</code>
2853     * </ul></dd></dl>
2854     */

2855    protected void unreadChar(char ch)
2856    {
2857        this.charReadTooMuch = ch;
2858    }
2859
2860
2861    /**
2862     * Creates a parse exception for when an invalid valueset is given to
2863     * a method.
2864     *
2865     * @param name The name of the entity.
2866     *
2867     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2868     * <ul><li><code>name != null</code>
2869     * </ul></dd></dl>
2870     *
2871     * @return exception
2872     */

2873    protected XMLParseException invalidValueSet(String JavaDoc name)
2874    {
2875        String JavaDoc msg = "Invalid value set (entity name = \"" + name + "\")";
2876        return new XMLParseException(this.getName(), this.parserLineNr, msg);
2877    }
2878
2879
2880    /**
2881     * Creates a parse exception for when an invalid value is given to a
2882     * method.
2883     *
2884     * @param name The name of the entity.
2885     * @param value The value of the entity.
2886     *
2887     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2888     * <ul><li><code>name != null</code>
2889     * <li><code>value != null</code>
2890     * </ul></dd></dl>
2891     *
2892     * @return invalid
2893     */

2894    protected XMLParseException invalidValue(String JavaDoc name,
2895                                             String JavaDoc value)
2896    {
2897        String JavaDoc msg = "Attribute \"" + name + "\" does not contain a valid "
2898                   + "value (\"" + value + "\")";
2899        return new XMLParseException(this.getName(), this.parserLineNr, msg);
2900    }
2901
2902
2903    /**
2904     * Creates a parse exception for when the end of the data input has been
2905     * reached.
2906     *
2907     * @return exception
2908     */

2909    protected XMLParseException unexpectedEndOfData()
2910    {
2911        String JavaDoc msg = "Unexpected end of data reached";
2912        return new XMLParseException(this.getName(), this.parserLineNr, msg);
2913    }
2914
2915
2916    /**
2917     * Creates a parse exception for when a syntax error occured.
2918     *
2919     * @param context The context in which the error occured.
2920     *
2921     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2922     * <ul><li><code>context != null</code>
2923     * <li><code>context.length() &gt; 0</code>
2924     * </ul></dd></dl>
2925     *
2926     * @return exception
2927     */

2928    protected XMLParseException syntaxError(String JavaDoc context)
2929    {
2930        String JavaDoc msg = "Syntax error while parsing " + context;
2931        return new XMLParseException(this.getName(), this.parserLineNr, msg);
2932    }
2933
2934
2935    /**
2936     * Creates a parse exception for when the next character read is not
2937     * the character that was expected.
2938     *
2939     * @param charSet The set of characters (in human readable form) that was
2940     * expected.
2941     *
2942     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2943     * <ul><li><code>charSet != null</code>
2944     * <li><code>charSet.length() &gt; 0</code>
2945     * </ul></dd></dl>
2946     *
2947     * @return exception
2948     */

2949    protected XMLParseException expectedInput(String JavaDoc charSet)
2950    {
2951        String JavaDoc msg = "Expected: " + charSet;
2952        return new XMLParseException(this.getName(), this.parserLineNr, msg);
2953    }
2954
2955
2956    /**
2957     * Creates a parse exception for when an entity could not be resolved.
2958     *
2959     * @param name The name of the entity.
2960     *
2961     * </dl><dl><dt><b>Preconditions:</b></dt><dd>
2962     * <ul><li><code>name != null</code>
2963     * <li><code>name.length() &gt; 0</code>
2964     * </ul></dd></dl>
2965     *
2966     * @return exception
2967     */

2968    protected XMLParseException unknownEntity(String JavaDoc name)
2969    {
2970        String JavaDoc msg = "Unknown or invalid entity: &" + name + ";";
2971        return new XMLParseException(this.getName(), this.parserLineNr, msg);
2972    }
2973
2974}
2975
Popular Tags