KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > n3 > nanoxml > XMLUtil


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

28
29 package net.n3.nanoxml;
30
31 import java.io.CharArrayReader JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.io.Reader JavaDoc;
34
35 /**
36  * Utility methods for NanoXML.
37  *
38  * @author Marc De Scheemaecker
39  * @version $Name$, $Revision: 1421 $
40  */

41 class XMLUtil
42 {
43
44     /**
45      * Skips the remainder of a comment. It is assumed that <!- is already read.
46      *
47      * @param reader the reader
48      * @param entityResolver the entity resolver
49      *
50      * @throws java.io.IOException if an error occurred reading the data
51      */

52     static void skipComment(IXMLReader reader, IXMLEntityResolver entityResolver)
53             throws IOException JavaDoc, XMLParseException
54     {
55         if (reader.read() != '-')
56         {
57             XMLUtil.skipTag(reader, '\0', entityResolver);
58             return;
59         }
60
61         int dashesRead = 0;
62
63         for (;;)
64         {
65             char ch = reader.read();
66
67             switch (ch)
68             {
69             case '-':
70                 dashesRead++;
71                 break;
72
73             case '>':
74                 if (dashesRead == 2) { return; }
75
76             default:
77                 dashesRead = 0;
78             }
79         }
80     }
81
82     /**
83      * Skips the remainder of the current XML tag.
84      *
85      * @param reader the reader
86      * @param escapeChar the escape character (& or %)
87      * @param entityResolver the entity resolver
88      *
89      * @throws java.io.IOException if an error occurred reading the data
90      */

91     static void skipTag(IXMLReader reader, char escapeChar, IXMLEntityResolver entityResolver)
92             throws IOException JavaDoc, XMLParseException
93     {
94         int level = 1;
95
96         while (level > 0)
97         {
98             char ch = XMLUtil.read(reader, null, escapeChar, entityResolver);
99
100             switch (ch)
101             {
102             case '<':
103                 ++level;
104                 break;
105
106             case '>':
107                 --level;
108                 break;
109             }
110         }
111     }
112
113     /**
114      * Scans a public ID.
115      *
116      * @param publicID will contain the public ID
117      * @param reader the reader
118      * @param escapeChar the escape character (&amp; or %)
119      * @param entityResolver the entity resolver
120      *
121      * @return the system ID
122      *
123      * @throws java.io.IOException if an error occurred reading the data
124      */

125     static String JavaDoc scanPublicID(StringBuffer JavaDoc publicID, IXMLReader reader, char escapeChar,
126             IXMLEntityResolver entityResolver) throws IOException JavaDoc, XMLParseException
127     {
128         if (!XMLUtil.checkLiteral(reader, escapeChar, entityResolver, "UBLIC")) { return null; }
129
130         XMLUtil.skipWhitespace(reader, escapeChar, null, null);
131         publicID.append(XMLUtil.scanString(reader, escapeChar, false, entityResolver));
132         XMLUtil.skipWhitespace(reader, escapeChar, null, null);
133         return XMLUtil.scanString(reader, escapeChar, false, entityResolver);
134     }
135
136     /**
137      * Scans a system ID.
138      *
139      * @param reader the reader
140      * @param escapeChar the escape character (&amp; or %)
141      * @param entityResolver the entity resolver
142      *
143      * @return the system ID
144      *
145      * @throws java.io.IOException if an error occurred reading the data
146      */

147     static String JavaDoc scanSystemID(IXMLReader reader, char escapeChar, IXMLEntityResolver entityResolver)
148             throws IOException JavaDoc, XMLParseException
149     {
150         if (!XMLUtil.checkLiteral(reader, escapeChar, entityResolver, "YSTEM")) { return null; }
151
152         XMLUtil.skipWhitespace(reader, escapeChar, null, null);
153         return XMLUtil.scanString(reader, escapeChar, false, entityResolver);
154     }
155
156     /**
157      * Retrieves an identifier from the data.
158      *
159      * @param reader the reader
160      * @param escapeChar the escape character (&amp; or %)
161      * @param entityResolver the entity resolver
162      *
163      * @throws java.io.IOException if an error occurred reading the data
164      */

165     static String JavaDoc scanIdentifier(IXMLReader reader, char escapeChar,
166             IXMLEntityResolver entityResolver) throws IOException JavaDoc, XMLParseException
167     {
168         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
169
170         for (;;)
171         {
172             char ch = XMLUtil.read(reader, null, escapeChar, entityResolver);
173
174             if ((ch == '_') || (ch == ':') || (ch == '-') || (ch == '.')
175                     || ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))
176                     || ((ch >= '0') && (ch <= '9')) || (ch > '\u007E'))
177             {
178                 result.append(ch);
179             }
180             else
181             {
182                 reader.unread(ch);
183                 break;
184             }
185         }
186
187         return result.toString();
188     }
189
190     /**
191      * Retrieves a delimited string from the data.
192      *
193      * @param reader the reader
194      * @param escapeChar the escape character (&amp; or %)
195      * @param normalizeWhitespace if all whitespace chars need to be converted to spaces
196      * @param entityResolver the entity resolver
197      *
198      * @throws java.io.IOException if an error occurred reading the data
199      */

200     static String JavaDoc scanString(IXMLReader reader, char escapeChar, boolean normalizeWhitespace,
201             IXMLEntityResolver entityResolver) throws IOException JavaDoc, XMLParseException
202     {
203         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
204         boolean isEntity[] = new boolean[1];
205         char delim = XMLUtil.read(reader, null, escapeChar, entityResolver);
206
207         if ((delim != '\'') && (delim != '"'))
208         {
209             XMLUtil
210                     .errorExpectedInput(reader.getSystemID(), reader.getLineNr(),
211                             "delimited string");
212         }
213
214         for (;;)
215         {
216             char ch = XMLUtil.read(reader, isEntity, escapeChar, entityResolver);
217
218             if ((!isEntity[0]) && (ch == escapeChar))
219             {
220                 reader.startNewStream(XMLUtil.scanEntity(isEntity, reader, escapeChar,
221                         entityResolver));
222                 ch = reader.read();
223             }
224
225             if ((!isEntity[0]) && (ch == delim))
226             {
227                 break;
228             }
229             else if (normalizeWhitespace && (ch < ' '))
230             {
231                 result.append(' ');
232             }
233             else
234             {
235                 result.append(ch);
236             }
237         }
238
239         return result.toString();
240     }
241
242     /**
243      * Processes an entity.
244      *
245      * @param isCharLiteral will contain true if the entity is a char literal
246      * @param reader the reader
247      * @param escapeChar the escape character (&amp; or %)
248      * @param entityResolver the entity resolver
249      *
250      * @return a reader from which the entity value can be retrieved
251      *
252      * @throws java.io.IOException if an error occurred reading the data
253      */

254     static Reader JavaDoc scanEntity(boolean[] isCharLiteral, IXMLReader reader, char escapeChar,
255             IXMLEntityResolver entityResolver) throws IOException JavaDoc, XMLParseException
256     {
257         char ch = reader.read();
258         StringBuffer JavaDoc keyBuf = new StringBuffer JavaDoc();
259
260         while (ch != ';')
261         {
262             keyBuf.append(ch);
263             ch = reader.read();
264         }
265
266         String JavaDoc key = keyBuf.toString();
267
268         if (key.charAt(0) == '#')
269         {
270             if (isCharLiteral != null)
271             {
272                 isCharLiteral[0] = true;
273             }
274
275             char[] chArr = new char[1];
276
277             if (key.charAt(1) == 'x')
278             {
279                 chArr[0] = (char) Integer.parseInt(key.substring(2), 16);
280             }
281             else
282             {
283                 chArr[0] = (char) Integer.parseInt(key.substring(1), 10);
284             }
285
286             return new CharArrayReader JavaDoc(chArr);
287         }
288         else
289         {
290             Reader JavaDoc entityReader = entityResolver.getEntity(reader, key);
291
292             if (entityReader == null)
293             {
294                 XMLUtil.errorInvalidEntity(reader.getSystemID(), reader.getLineNr(), key);
295             }
296
297             return entityReader;
298         }
299     }
300
301     /**
302      * Skips whitespace from the reader.
303      *
304      * @param reader the reader
305      * @param escapeChar the escape character (&amp; or %)
306      * @param buffer where to put the whitespace; null if the whitespace does not have to be stored.
307      * @param isEntity if not null, will contain true if the data following the whitespace is an
308      * entity
309      *
310      * @throws java.io.IOException if an error occurred reading the data
311      */

312     static void skipWhitespace(IXMLReader reader, char escapeChar, StringBuffer JavaDoc buffer,
313             boolean[] isEntity) throws IOException JavaDoc
314     {
315         char ch;
316
317         if (buffer == null)
318         {
319             do
320             {
321                 ch = reader.read();
322             }
323             while ((ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r'));
324         }
325         else
326         {
327             for (;;)
328             {
329                 ch = reader.read();
330
331                 if ((ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r'))
332                 {
333                     break;
334                 }
335
336                 buffer.append(ch);
337             }
338         }
339
340         reader.unread(ch);
341
342         if (isEntity != null)
343         {
344             isEntity[0] = (ch == escapeChar);
345         }
346     }
347
348     /**
349      * Reads a character from the reader.
350      *
351      * @param reader the reader
352      * @param isEntityValue if the character is the first character in an entity
353      * @param escapeChar the escape character (&amp; or %)
354      * @param entityResolver the entity resolver
355      *
356      * @throws java.io.IOException if an error occurred reading the data
357      */

358     static char read(IXMLReader reader, boolean[] isEntityValue, char escapeChar,
359             IXMLEntityResolver entityResolver) throws IOException JavaDoc, XMLParseException
360     {
361         char ch = reader.read();
362
363         if (isEntityValue != null)
364         {
365             isEntityValue[0] = false;
366         }
367
368         if (ch == escapeChar)
369         {
370             boolean[] charLiteral = new boolean[1];
371             reader.startNewStream(XMLUtil.scanEntity(charLiteral, reader, escapeChar,
372                     entityResolver));
373
374             if (charLiteral[0])
375             {
376                 ch = reader.read();
377
378                 if (isEntityValue != null)
379                 {
380                     isEntityValue[0] = true;
381                 }
382             }
383             else
384             {
385                 ch = XMLUtil.read(reader, null, escapeChar, entityResolver);
386             }
387         }
388
389         return ch;
390     }
391
392     /**
393      * Returns true if the data starts with <I>literal</I>. Enough chars are read to determine this
394      * result.
395      *
396      * @param reader the reader
397      * @param escapeChar the escape character (&amp; or %)
398      * @param entityResolver the entity resolver
399      * @param literal the literal to check
400      *
401      * @throws java.io.IOException if an error occurred reading the data
402      */

403     static boolean checkLiteral(IXMLReader reader, char escapeChar,
404             IXMLEntityResolver entityResolver, String JavaDoc literal) throws IOException JavaDoc,
405             XMLParseException
406     {
407         for (int i = 0; i < literal.length(); i++)
408         {
409             char ch = XMLUtil.read(reader, null, escapeChar, entityResolver);
410
411             if (ch != literal.charAt(i)) { return false; }
412         }
413
414         return true;
415     }
416
417     /**
418      * Throws an XMLParseException to indicate that an expected string is not encountered.
419      *
420      * @param systemID the system ID from where the data came
421      * @param lineNr the line number in the XML data where the exception occurred.
422      * @param expectedString the string that is expected
423      */

424     static void errorExpectedInput(String JavaDoc systemID, int lineNr, String JavaDoc expectedString)
425             throws XMLParseException
426     {
427         throw new XMLParseException(systemID, lineNr, "Expected: " + expectedString);
428     }
429
430     /**
431      * Throws an XMLParseException to indicate that an entity could not be resolved.
432      *
433      * @param systemID the system ID from where the data came
434      * @param lineNr the line number in the XML data where the exception occurred.
435      * @param key the name of the entity
436      */

437     static void errorInvalidEntity(String JavaDoc systemID, int lineNr, String JavaDoc key)
438             throws XMLParseException
439     {
440         throw new XMLParseException(systemID, lineNr, "Invalid entity: `&" + key + ";'");
441     }
442
443     /**
444      * Throws an XMLParseException to indicate that a string is not expected at this point.
445      *
446      * @param systemID the system ID from where the data came
447      * @param lineNr the line number in the XML data where the exception occurred.
448      * @param unexpectedString the string that is unexpected
449      */

450     static void errorInvalidInput(String JavaDoc systemID, int lineNr, String JavaDoc unexpectedString)
451             throws XMLParseException
452     {
453         throw new XMLParseException(systemID, lineNr, "Invalid input: " + unexpectedString);
454     }
455
456     /**
457      * Throws an XMLParseException to indicate that the closing tag of an element does not match the
458      * opening tag.
459      *
460      * @param systemID the system ID from where the data came
461      * @param lineNr the line number in the XML data where the exception occurred.
462      * @param expectedName the name of the opening tag
463      * @param wrongName the name of the closing tag
464      */

465     static void errorWrongClosingTag(String JavaDoc systemID, int lineNr, String JavaDoc expectedName,
466             String JavaDoc wrongName) throws XMLParseException
467     {
468         throw new XMLParseException(systemID, lineNr, "Closing tag does not match opening tag: `"
469                 + wrongName + "' != `" + expectedName + "'");
470     }
471
472     /**
473      * Throws an XMLParseException to indicate that extra data is encountered in a closing tag.
474      *
475      * @param systemID the system ID from where the data came
476      * @param lineNr the line number in the XML data where the exception occurred.
477      */

478     static void errorClosingTagNotEmpty(String JavaDoc systemID, int lineNr) throws XMLParseException
479     {
480         throw new XMLParseException(systemID, lineNr, "Closing tag must be empty");
481     }
482
483     /**
484      * Throws an XMLValidationException to indicate that an element is missing.
485      *
486      * @param systemID the system ID from where the data came
487      * @param lineNr the line number in the XML data where the exception occurred.
488      * @param parentElementName the name of the offending element
489      * @param missingElementName the name of the offending attribute
490      */

491     static void errorMissingElement(String JavaDoc systemID, int lineNr, String JavaDoc parentElementName,
492             String JavaDoc missingElementName) throws XMLValidationException
493     {
494         throw new XMLValidationException(XMLValidationException.MISSING_ELEMENT, systemID, lineNr,
495                 missingElementName,
496                 /* attributeName */null,
497                 /* attributeValue */null, "Element " + parentElementName + " expects to have a "
498                         + missingElementName);
499     }
500
501     /**
502      * Throws an XMLValidationException to indicate that an element is unexpected.
503      *
504      * @param systemID the system ID from where the data came
505      * @param lineNr the line number in the XML data where the exception occurred.
506      * @param parentElementName the name of the parent attribute
507      * @param unexpectedElementName the name of the offending attribute
508      */

509     static void errorUnexpectedElement(String JavaDoc systemID, int lineNr, String JavaDoc parentElementName,
510             String JavaDoc unexpectedElementName) throws XMLValidationException
511     {
512         throw new XMLValidationException(XMLValidationException.UNEXPECTED_ELEMENT, systemID,
513                 lineNr, unexpectedElementName,
514                 /* attributeName */null,
515                 /* attributeValue */null, "Unexpected " + unexpectedElementName + " in a "
516                         + parentElementName);
517     }
518
519     /**
520      * Throws an XMLValidationException to indicate that an attribute is missing.
521      *
522      * @param systemID the system ID from where the data came
523      * @param lineNr the line number in the XML data where the exception occurred.
524      * @param elementName the name of the offending element
525      * @param attributeName the name of the offending attribute
526      */

527     static void errorMissingAttribute(String JavaDoc systemID, int lineNr, String JavaDoc elementName,
528             String JavaDoc attributeName) throws XMLValidationException
529     {
530         throw new XMLValidationException(XMLValidationException.MISSING_ATTRIBUTE, systemID,
531                 lineNr, elementName, attributeName,
532                 /* attributeValue */null, "Element " + elementName
533                         + " expects an attribute named " + attributeName);
534     }
535
536     /**
537      * Throws an XMLValidationException to indicate that an attribute is unexpected.
538      *
539      * @param systemID the system ID from where the data came
540      * @param lineNr the line number in the XML data where the exception occurred.
541      * @param elementName the name of the offending element
542      * @param attributeName the name of the offending attribute
543      */

544     static void errorUnexpectedAttribute(String JavaDoc systemID, int lineNr, String JavaDoc elementName,
545             String JavaDoc attributeName) throws XMLValidationException
546     {
547         throw new XMLValidationException(XMLValidationException.UNEXPECTED_ATTRIBUTE, systemID,
548                 lineNr, elementName, attributeName,
549                 /* attributeValue */null, "Element " + elementName
550                         + " did not expect an attribute " + "named " + attributeName);
551     }
552
553     /**
554      * Throws an XMLValidationException to indicate that an attribute has an invalid value.
555      *
556      * @param systemID the system ID from where the data came
557      * @param lineNr the line number in the XML data where the exception occurred.
558      * @param elementName the name of the offending element
559      * @param attributeName the name of the offending attribute
560      * @param attributeValue the value of the offending attribute
561      */

562     static void errorInvalidAttributeValue(String JavaDoc systemID, int lineNr, String JavaDoc elementName,
563             String JavaDoc attributeName, String JavaDoc attributeValue) throws XMLValidationException
564     {
565         throw new XMLValidationException(XMLValidationException.ATTRIBUTE_WITH_INVALID_VALUE,
566                 systemID, lineNr, elementName, attributeName, attributeValue,
567                 "Invalid value for attribute " + attributeName);
568     }
569
570     /**
571      * Throws an XMLValidationException to indicate that a #PCDATA element was missing.
572      *
573      * @param systemID the system ID from where the data came
574      * @param lineNr the line number in the XML data where the exception occurred.
575      * @param parentElementName the name of the offending element
576      */

577     static void errorMissingPCData(String JavaDoc systemID, int lineNr, String JavaDoc parentElementName)
578             throws XMLValidationException
579     {
580         throw new XMLValidationException(XMLValidationException.MISSING_PCDATA, systemID, lineNr,
581         /* elementName */null,
582         /* attributeName */null,
583         /* attributeValue */null, "Missing #PCDATA in element " + parentElementName);
584     }
585
586     /**
587      * Throws an XMLValidationException to indicate that a #PCDATA element was unexpected.
588      *
589      * @param systemID the system ID from where the data came
590      * @param lineNr the line number in the XML data where the exception occurred.
591      * @param parentElementName the name of the offending element
592      */

593     static void errorUnexpectedPCData(String JavaDoc systemID, int lineNr, String JavaDoc parentElementName)
594             throws XMLValidationException
595     {
596         throw new XMLValidationException(XMLValidationException.UNEXPECTED_PCDATA, systemID,
597                 lineNr,
598                 /* elementName */null,
599                 /* attributeName */null,
600                 /* attributeValue */null, "Unexpected #PCDATA in element " + parentElementName);
601     }
602
603     /**
604      * Throws an XMLValidationException.
605      *
606      * @param systemID the system ID from where the data came
607      * @param lineNr the line number in the XML data where the exception occurred.
608      * @param message the message of the exception.
609      * @param elementName the name of the offending element
610      * @param attributeName the name of the offending attribute
611      * @param attributeValue the value of the offending attribute
612      */

613     static void validationError(String JavaDoc systemID, int lineNr, String JavaDoc message, String JavaDoc elementName,
614             String JavaDoc attributeName, String JavaDoc attributeValue) throws XMLValidationException
615     {
616         throw new XMLValidationException(XMLValidationException.MISC_ERROR, systemID, lineNr,
617                 elementName, attributeName, attributeValue, message);
618     }
619
620 }
621
Popular Tags