KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > xni > Writer


1 /*
2  * Copyright 2001-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package xni;
18
19 import java.io.OutputStream JavaDoc;
20 import java.io.OutputStreamWriter JavaDoc;
21 import java.io.PrintWriter JavaDoc;
22 import java.io.UnsupportedEncodingException JavaDoc;
23
24 import org.apache.xerces.parsers.XMLDocumentParser;
25 import org.apache.xerces.xni.Augmentations;
26 import org.apache.xerces.xni.NamespaceContext;
27 import org.apache.xerces.xni.QName;
28 import org.apache.xerces.xni.XMLAttributes;
29 import org.apache.xerces.xni.XMLLocator;
30 import org.apache.xerces.xni.XMLString;
31 import org.apache.xerces.xni.XNIException;
32 import org.apache.xerces.xni.parser.XMLConfigurationException;
33 import org.apache.xerces.xni.parser.XMLErrorHandler;
34 import org.apache.xerces.xni.parser.XMLInputSource;
35 import org.apache.xerces.xni.parser.XMLParseException;
36 import org.apache.xerces.xni.parser.XMLParserConfiguration;
37 import org.apache.xerces.xni.parser.XMLPullParserConfiguration;
38
39 /**
40  * A sample XNI writer. This sample program illustrates how to
41  * use the XNI XMLDocumentHandler callbacks in order to print a
42  * document that is parsed.
43  *
44  * @author Andy Clark, IBM
45  *
46  * @version $Id: Writer.java,v 1.23 2005/06/14 20:51:13 mrglavas Exp $
47  */

48 public class Writer
49     extends XMLDocumentParser
50     implements XMLErrorHandler {
51
52     //
53
// Constants
54
//
55

56     // feature ids
57

58     /** Namespaces feature id (http://xml.org/sax/features/namespaces). */
59     protected static final String JavaDoc NAMESPACES_FEATURE_ID =
60         "http://xml.org/sax/features/namespaces";
61
62     /** Validation feature id (http://xml.org/sax/features/validation). */
63     protected static final String JavaDoc VALIDATION_FEATURE_ID =
64         "http://xml.org/sax/features/validation";
65
66     /** Schema validation feature id (http://apache.org/xml/features/validation/schema). */
67     protected static final String JavaDoc SCHEMA_VALIDATION_FEATURE_ID =
68         "http://apache.org/xml/features/validation/schema";
69
70     /** Schema full checking feature id (http://apache.org/xml/features/validation/schema-full-checking). */
71     protected static final String JavaDoc SCHEMA_FULL_CHECKING_FEATURE_ID =
72         "http://apache.org/xml/features/validation/schema-full-checking";
73
74     // default settings
75

76     /** Default parser configuration (org.apache.xerces.parsers.XIncludeAwareParserConfiguration). */
77     protected static final String JavaDoc DEFAULT_PARSER_CONFIG =
78         "org.apache.xerces.parsers.XIncludeAwareParserConfiguration";
79
80     /** Default namespaces support (true). */
81     protected static final boolean DEFAULT_NAMESPACES = true;
82
83     /** Default validation support (false). */
84     protected static final boolean DEFAULT_VALIDATION = false;
85
86     /** Default Schema validation support (false). */
87     protected static final boolean DEFAULT_SCHEMA_VALIDATION = false;
88
89     /** Default Schema full checking support (false). */
90     protected static final boolean DEFAULT_SCHEMA_FULL_CHECKING = false;
91
92     /** Default canonical output (false). */
93     protected static final boolean DEFAULT_CANONICAL = false;
94
95     /** Default incremental mode (false). */
96     protected static final boolean DEFAULT_INCREMENTAL = false;
97
98     //
99
// Data
100
//
101

102     /** Print writer. */
103     protected PrintWriter JavaDoc fOut;
104
105     /** Canonical output. */
106     protected boolean fCanonical;
107
108     /** Element depth. */
109     protected int fElementDepth;
110
111     /** Seen root element. */
112     protected boolean fSeenRootElement;
113
114     //
115
// Constructors
116
//
117

118     /** Default constructor. */
119     public Writer(XMLParserConfiguration configuration) {
120         super(configuration);
121         fConfiguration.setErrorHandler(this);
122     } // <init>(XMLParserConfiguration)
123

124     //
125
// Public methods
126
//
127

128     /** Sets whether output is canonical. */
129     public void setCanonical(boolean canonical) {
130         fCanonical = canonical;
131     } // setCanonical(boolean)
132

133     /** Sets the output stream for printing. */
134     public void setOutput(OutputStream JavaDoc stream, String JavaDoc encoding)
135         throws UnsupportedEncodingException JavaDoc {
136
137         if (encoding == null) {
138             encoding = "UTF8";
139         }
140
141         java.io.Writer JavaDoc writer = new OutputStreamWriter JavaDoc(stream, encoding);
142         fOut = new PrintWriter JavaDoc(writer);
143
144     } // setOutput(OutputStream,String)
145

146     /** Sets the output writer. */
147     public void setOutput(java.io.Writer JavaDoc writer) {
148
149         fOut = writer instanceof PrintWriter JavaDoc
150              ? (PrintWriter JavaDoc)writer : new PrintWriter JavaDoc(writer);
151
152     } // setOutput(java.io.Writer)
153

154     //
155
// XMLDocumentHandler methods
156
//
157

158     /** Start document. */
159     public void startDocument(XMLLocator locator, String JavaDoc encoding,
160             NamespaceContext namespaceContext, Augmentations augs)
161         throws XNIException {
162
163         fSeenRootElement = false;
164         fElementDepth = 0;
165
166         if (!fCanonical) {
167             fOut.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
168             fOut.flush();
169         }
170
171     } // startDocument(XMLLocator,String,NamespaceContext, Augmentations)
172

173     /** Start element. */
174     public void startElement(QName element, XMLAttributes attrs, Augmentations augs)
175         throws XNIException {
176
177         fSeenRootElement = true;
178         fElementDepth++;
179         fOut.print('<');
180         fOut.print(element.rawname);
181         if (attrs != null) {
182             /***
183             attrs = sortAttributes(attrs);
184             /***/

185             int len = attrs.getLength();
186             for (int i = 0; i < len; i++) {
187                 fOut.print(' ');
188                 fOut.print(attrs.getQName(i));
189                 fOut.print("=\"");
190                 normalizeAndPrint(attrs.getValue(i));
191                 fOut.print('"');
192             }
193         }
194         fOut.print('>');
195         fOut.flush();
196
197     } // startElement(QName,XMLAttributes,Augmentations)
198

199     /** Empty element. */
200     public void emptyElement(QName element, XMLAttributes attrs, Augmentations augs)
201         throws XNIException {
202
203         fSeenRootElement = true;
204         fElementDepth++;
205         fOut.print('<');
206         fOut.print(element.rawname);
207         if (attrs != null) {
208             /***
209             attrs = sortAttributes(attrs);
210             /***/

211             int len = attrs.getLength();
212             for (int i = 0; i < len; i++) {
213                 fOut.print(' ');
214                 fOut.print(attrs.getQName(i));
215                 fOut.print("=\"");
216                 normalizeAndPrint(attrs.getValue(i));
217                 fOut.print('"');
218             }
219         }
220         fOut.print("/>");
221         fOut.flush();
222
223     } // emptyElement(QName,XMLAttributes,Augmentations)
224

225     /** Processing instruction. */
226     public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
227         throws XNIException {
228
229         if (fSeenRootElement) {
230             fOut.print('\n');
231         }
232         fOut.print("<?");
233         fOut.print(target);
234         if (data != null && data.length > 0) {
235             fOut.print(' ');
236             fOut.print(data.toString());
237         }
238         fOut.print("?>");
239         if (!fSeenRootElement) {
240             fOut.print('\n');
241         }
242         fOut.flush();
243
244     } // processingInstruction(String,XMLString,Augmentations)
245

246     /** Comment. */
247     public void comment(XMLString text, Augmentations augs) throws XNIException {
248         if (!fCanonical) {
249             if (fSeenRootElement && fElementDepth == 0) {
250                 fOut.print('\n');
251             }
252             fOut.print("<!--");
253             fOut.print(text.toString());
254             fOut.print("-->");
255             if (!fSeenRootElement) {
256                 fOut.print('\n');
257             }
258             fOut.flush();
259         }
260     } // comment(XMLString,Augmentations)
261

262     /** Characters. */
263     public void characters(XMLString text, Augmentations augs) throws XNIException {
264
265         normalizeAndPrint(text);
266         //fOut.println("one call...");
267
fOut.flush();
268
269     } // characters(XMLString,Augmentations)
270

271     /** Ignorable whitespace. */
272     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
273
274         characters(text, augs);
275         fOut.flush();
276
277     } // ignorableWhitespace(XMLString,Augmentations)
278

279     /** End element. */
280     public void endElement(QName element, Augmentations augs) throws XNIException {
281
282         fElementDepth--;
283         fOut.print("</");
284         fOut.print(element.rawname);
285         fOut.print('>');
286         fOut.flush();
287
288     } // endElement(QName,Augmentations)
289

290     /** Start CDATA section. */
291     public void startCDATA(Augmentations augs) throws XNIException {
292     } // startCDATA(Augmentations)
293

294     /** End CDATA section. */
295     public void endCDATA(Augmentations augs) throws XNIException {
296     } // endCDATA(Augmentations)
297

298     //
299
// XMLDTDHandler methods
300
//
301

302     //
303
// XMLErrorHandler methods
304
//
305

306     /** Warning. */
307     public void warning(String JavaDoc domain, String JavaDoc key, XMLParseException ex)
308         throws XNIException {
309         printError("Warning", ex);
310     } // warning(String,String,XMLParseException)
311

312     /** Error. */
313     public void error(String JavaDoc domain, String JavaDoc key, XMLParseException ex)
314         throws XNIException {
315         printError("Error", ex);
316     } // error(String,String,XMLParseException)
317

318     /** Fatal error. */
319     public void fatalError(String JavaDoc domain, String JavaDoc key, XMLParseException ex)
320         throws XNIException {
321         printError("Fatal Error", ex);
322         throw ex;
323     } // fatalError(String,String,XMLParseException)
324

325     //
326
// Protected methods
327
//
328

329     /** Returns a sorted list of attributes. */
330     /***
331     protected XMLAttributes sortAttributes(XMLAttributes attrs) {
332
333         XMLAttributesImpl attributes = new XMLAttributesImpl();
334
335         int len = (attrs != null) ? attrs.getLength() : 0;
336         for (int i = 0; i < len; i++) {
337             String name = attrs.getQName(i);
338             int count = attributes.getLength();
339             int j = 0;
340             while (j < count) {
341                 if (name.compareTo(attributes.getQName(j)) < 0) {
342                     break;
343                 }
344                 j++;
345             }
346             attributes.insertAttributeAt(j, name, attrs.getType(i),
347                                          attrs.getValue(i));
348         }
349
350         return attributes;
351
352     } // sortAttributes(XMLAttributeList):XMLAttributeList
353     /***/

354
355     /** Normalizes and prints the given string. */
356     protected void normalizeAndPrint(String JavaDoc s) {
357
358         int len = (s != null) ? s.length() : 0;
359         for (int i = 0; i < len; i++) {
360             char c = s.charAt(i);
361             normalizeAndPrint(c);
362         }
363
364     } // normalizeAndPrint(String)
365

366     /** Normalizes and prints the given array of characters. */
367     protected void normalizeAndPrint(XMLString text) {
368         for (int i = 0; i < text.length; i++) {
369             normalizeAndPrint(text.ch[text.offset + i]);
370         }
371     } // normalizeAndPrint(XMLString)
372

373     /** Normalizes and print the given character. */
374     protected void normalizeAndPrint(char c) {
375
376         switch (c) {
377             case '<': {
378                 fOut.print("&lt;");
379                 break;
380             }
381             case '>': {
382                 fOut.print("&gt;");
383                 break;
384             }
385             case '&': {
386                 fOut.print("&amp;");
387                 break;
388             }
389             case '"': {
390                 fOut.print("&quot;");
391                 break;
392             }
393             case '\r':
394             case '\n': {
395                 if (fCanonical) {
396                     fOut.print("&#");
397                     fOut.print(Integer.toString(c));
398                     fOut.print(';');
399                     break;
400                 }
401                 // else, default print char
402
}
403             default: {
404                 fOut.print(c);
405             }
406         }
407
408     } // normalizeAndPrint(char)
409

410     /** Prints the error message. */
411     protected void printError(String JavaDoc type, XMLParseException ex) {
412
413         System.err.print("[");
414         System.err.print(type);
415         System.err.print("] ");
416         String JavaDoc systemId = ex.getExpandedSystemId();
417         if (systemId != null) {
418             int index = systemId.lastIndexOf('/');
419             if (index != -1)
420                 systemId = systemId.substring(index + 1);
421             System.err.print(systemId);
422         }
423         System.err.print(':');
424         System.err.print(ex.getLineNumber());
425         System.err.print(':');
426         System.err.print(ex.getColumnNumber());
427         System.err.print(": ");
428         System.err.print(ex.getMessage());
429         System.err.println();
430         System.err.flush();
431
432     } // printError(String,XMLParseException)
433

434     //
435
// Main
436
//
437

438     /** Main program entry point. */
439     public static void main(String JavaDoc argv[]) {
440
441         // is there anything to do?
442
if (argv.length == 0) {
443             printUsage();
444             System.exit(1);
445         }
446
447         // variables
448
Writer writer = null;
449         XMLParserConfiguration parserConfig = null;
450         boolean namespaces = DEFAULT_NAMESPACES;
451         boolean validation = DEFAULT_VALIDATION;
452         boolean schemaValidation = DEFAULT_SCHEMA_VALIDATION;
453         boolean schemaFullChecking = DEFAULT_SCHEMA_FULL_CHECKING;
454         boolean canonical = DEFAULT_CANONICAL;
455         boolean incremental = DEFAULT_INCREMENTAL;
456
457         // process arguments
458
for (int i = 0; i < argv.length; i++) {
459             String JavaDoc arg = argv[i];
460             if (arg.startsWith("-")) {
461                 String JavaDoc option = arg.substring(1);
462                 if (option.equals("p")) {
463                     // get parser name
464
if (++i == argv.length) {
465                         System.err.println("error: Missing argument to -p option.");
466                     }
467                     String JavaDoc parserName = argv[i];
468
469                     // create parser
470
try {
471                         parserConfig = (XMLParserConfiguration)ObjectFactory.newInstance(parserName,
472                             ObjectFactory.findClassLoader(), true);
473                         /***
474                         parserConfig.addRecognizedFeatures(new String[] {
475                             NAMESPACE_PREFIXES_FEATURE_ID,
476                         });
477                         /***/

478                         writer = null;
479                     }
480                     catch (Exception JavaDoc e) {
481                         parserConfig = null;
482                         System.err.println("error: Unable to instantiate parser configuration ("+parserName+")");
483                         e.printStackTrace(System.err);
484                     }
485                     continue;
486                 }
487                 if (option.equalsIgnoreCase("n")) {
488                     namespaces = option.equals("n");
489                     continue;
490                 }
491                 if (option.equalsIgnoreCase("v")) {
492                     validation = option.equals("v");
493                     continue;
494                 }
495                 if (option.equalsIgnoreCase("s")) {
496                     schemaValidation = option.equals("s");
497                     continue;
498                 }
499                 if (option.equalsIgnoreCase("f")) {
500                     schemaFullChecking = option.equals("f");
501                     continue;
502                 }
503                 if (option.equalsIgnoreCase("c")) {
504                     canonical = option.equals("c");
505                     continue;
506                 }
507                 if (option.equalsIgnoreCase("i")) {
508                     incremental = option.equals("i");
509                     continue;
510                 }
511                 if (option.equals("h")) {
512                     printUsage();
513                     continue;
514                 }
515             }
516
517             // use default parser?
518
if (parserConfig == null) {
519
520                 // create parser
521
try {
522                     parserConfig = (XMLParserConfiguration)ObjectFactory.newInstance(DEFAULT_PARSER_CONFIG,
523                         ObjectFactory.findClassLoader(), true);
524                     /***
525                     parserConfig.addRecognizedFeatures(new String[] {
526                         NAMESPACE_PREFIXES_FEATURE_ID,
527                     });
528                     /***/

529                 }
530                 catch (Exception JavaDoc e) {
531                     System.err.println("error: Unable to instantiate parser configuration ("+DEFAULT_PARSER_CONFIG+")");
532                     e.printStackTrace(System.err);
533                     continue;
534                 }
535             }
536
537             // set parser features
538
if (writer == null) {
539                 writer = new Writer(parserConfig);
540             }
541             try {
542                 parserConfig.setFeature(NAMESPACES_FEATURE_ID, namespaces);
543             }
544             catch (XMLConfigurationException e) {
545                 System.err.println("warning: Parser does not support feature ("+NAMESPACES_FEATURE_ID+")");
546             }
547             try {
548                 parserConfig.setFeature(VALIDATION_FEATURE_ID, validation);
549             }
550             catch (XMLConfigurationException e) {
551                 System.err.println("warning: Parser does not support feature ("+VALIDATION_FEATURE_ID+")");
552             }
553             try {
554                 parserConfig.setFeature(SCHEMA_VALIDATION_FEATURE_ID, schemaValidation);
555             }
556             catch (XMLConfigurationException e) {
557                 if (e.getType() == XMLConfigurationException.NOT_SUPPORTED) {
558                     System.err.println("warning: Parser does not support feature ("+SCHEMA_VALIDATION_FEATURE_ID+")");
559                 }
560             }
561             try {
562                 parserConfig.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, schemaFullChecking);
563             }
564             catch (XMLConfigurationException e) {
565                 if (e.getType() == XMLConfigurationException.NOT_SUPPORTED) {
566                     System.err.println("warning: Parser does not support feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")");
567                 }
568             }
569
570             // parse file
571
try {
572                 writer.setOutput(System.out, "UTF8");
573             }
574             catch (UnsupportedEncodingException JavaDoc e) {
575                 System.err.println("error: Unable to set output. Exiting.");
576                 System.exit(1);
577             }
578             writer.setCanonical(canonical);
579             try {
580                 if (incremental && parserConfig instanceof XMLPullParserConfiguration) {
581                     XMLPullParserConfiguration pullParserConfig = (XMLPullParserConfiguration)parserConfig;
582                     pullParserConfig.setInputSource(new XMLInputSource(null, arg, null));
583                     int step = 1;
584                     do {
585                         //System.err.println("# step "+step++);
586
} while (pullParserConfig.parse(false));
587                 }
588                 else {
589                     writer.parse(new XMLInputSource(null, arg, null));
590                 }
591             }
592             catch (XMLParseException e) {
593                 // ignore
594
}
595             catch (Exception JavaDoc e) {
596                 System.err.println("error: Parse error occurred - "+e.getMessage());
597                 if (e instanceof XNIException) {
598                     e = ((XNIException)e).getException();
599                 }
600                 e.printStackTrace(System.err);
601             }
602         }
603
604     } // main(String[])
605

606     //
607
// Private static methods
608
//
609

610     /** Prints the usage. */
611     private static void printUsage() {
612
613         System.err.println("usage: java sax.Writer (options) uri ...");
614         System.err.println();
615
616         System.err.println("options:");
617         System.err.println(" -p name Select parser configuration by name.");
618         System.err.println(" -n | -N Turn on/off namespace processing.");
619         System.err.println(" -v | -V Turn on/off validation.");
620         System.err.println(" -s | -S Turn on/off Schema validation support.");
621         System.err.println(" NOTE: Not supported by all parsers.");
622         System.err.println(" -f | -F Turn on/off Schema full checking.");
623         System.err.println(" NOTE: Requires use of -s and not supported by all parsers.");
624         /***
625         System.err.println(" -c | -C Turn on/off Canonical XML output.");
626         System.err.println(" NOTE: This is not W3C canonical output.");
627         /***/

628         System.err.println(" -i | -I Incremental mode.");
629         System.err.println(" NOTE: This feature only works if the configuration used");
630         System.err.println(" implements XMLPullParserConfiguration.");
631         System.err.println(" -h This help screen.");
632         System.err.println();
633
634         System.err.println("defaults:");
635         System.err.println(" Config: "+DEFAULT_PARSER_CONFIG);
636         System.err.print(" Namespaces: ");
637         System.err.println(DEFAULT_NAMESPACES ? "on" : "off");
638         System.err.print(" Validation: ");
639         System.err.println(DEFAULT_VALIDATION ? "on" : "off");
640         System.err.print(" Schema: ");
641         System.err.println(DEFAULT_SCHEMA_VALIDATION ? "on" : "off");
642         System.err.print(" Schema full checking: ");
643         System.err.println(DEFAULT_SCHEMA_FULL_CHECKING ? "on" : "off");
644         /***
645         System.err.print(" Canonical: ");
646         System.err.println(DEFAULT_CANONICAL ? "on" : "off");
647         /***/

648         System.err.print(" Incremental: ");
649         System.err.println(DEFAULT_INCREMENTAL ? "on" : "off");
650
651     } // printUsage()
652

653 } // class Writer
654
Popular Tags