KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > vfs > XmlWriter


1 /*
2  * Copyright (c) 1998-2005 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Sam
27  */

28
29 package com.caucho.vfs;
30
31 import java.io.PrintWriter JavaDoc;
32 import java.io.Writer JavaDoc;
33 import java.util.HashMap JavaDoc;
34
35 // TODO: get rid of set/getContentType, use getStrategyForContentType(...) and setStrategy(...)
36
// TODO: trap all print(...) for xml escaping, indenting
37
// TODO: capture all \n and \r\n and make them do println()
38
// TODO: clean up flags now that patterns are known
39
// TODO: CDATA
40
// TODO: startDocument, endDocument (<?xml with charset and DOCTYPE)
41
// TODO: li review (including test case), because of bug in some browser (dt,dd?)
42
public class XmlWriter
43   extends PrintWriter JavaDoc
44 {
45   public final static Strategy XML = new Xml();
46   public final static Strategy XHTML = new Xhtml();
47   public final static Strategy HTML = new Html();
48
49   private boolean _isIndenting = false;
50   private int _indent = 0;
51
52   private boolean _isElementOpen;
53   private boolean _isElementOpenNeedsNewline;
54   private String JavaDoc _openElementName;
55
56   private Strategy _strategy = XML;
57   private String JavaDoc _contentType = "text/xml";
58   private String JavaDoc _characterEncoding;
59   private boolean _isNewLine = true;
60
61   public XmlWriter(Writer JavaDoc out)
62   {
63     super(out);
64   }
65
66   public String JavaDoc getContentType()
67   {
68     return _contentType;
69   }
70
71   /**
72    * Default is "text/xml".
73    */

74   public void setContentType(String JavaDoc contentType)
75   {
76     _contentType = contentType;
77
78     if (_contentType.equals("text/xml"))
79       _strategy = XML;
80     if (_contentType.equals("application/xml"))
81       _strategy = XML;
82     else if (_contentType.equals("text/xhtml"))
83       _strategy = XHTML;
84     else if (_contentType.equals("application/xhtml+xml"))
85       _strategy = XHTML;
86     else if (_contentType.equals("text/html"))
87       _strategy = HTML;
88     else
89       _strategy = XML;
90   }
91
92   public void setStrategy(Strategy strategy)
93   {
94     _strategy = strategy;
95   }
96
97   public void setIndenting(boolean isIndenting)
98   {
99     _isIndenting = isIndenting;
100   }
101
102   public boolean isIndenting()
103   {
104     return _isIndenting;
105   }
106
107   /**
108    * Default is "UTF-8".
109    */

110   public void setCharacterEncoding(String JavaDoc characterEncoding)
111   {
112     _characterEncoding = characterEncoding;
113   }
114
115   public String JavaDoc getCharacterEncoding()
116   {
117     return _characterEncoding;
118   }
119
120   private boolean closeElementIfNeeded(boolean isEnd)
121   {
122     if (_isElementOpen) {
123       _isElementOpen = false;
124
125       _strategy.closeElement(this, _openElementName, isEnd);
126
127       if (_isElementOpenNeedsNewline) {
128         _isElementOpenNeedsNewline = false;
129         softPrintln();
130       }
131
132       return true;
133     }
134
135     return false;
136   }
137
138   private void startElement(String JavaDoc name, boolean isLineBefore, boolean isLineAfter)
139   {
140     closeElementIfNeeded(false);
141
142     if (isLineBefore)
143       softPrintln();
144
145     _openElementName = name;
146
147     _strategy.openElement(this, name);
148     _isElementOpen = true;
149     _isElementOpenNeedsNewline = isLineAfter;
150
151     if (_isIndenting)
152       _indent++;
153   }
154
155   private void endElement(String JavaDoc name, boolean isLineBefore, boolean isLineAfter)
156   {
157     if (_isIndenting)
158       _indent--;
159
160     if (!closeElementIfNeeded(true)) {
161       if (isLineBefore)
162         softPrintln();
163
164       _strategy.endElement(this, name);
165     }
166
167     if (isLineAfter)
168       softPrintln();
169   }
170
171   /**
172    * Start an element.
173    */

174   public void startElement(String JavaDoc name)
175   {
176     startElement(name, false, false);
177   }
178
179   /**
180    * End an element.
181    */

182   public void endElement(String JavaDoc name)
183   {
184     endElement(name, false, false);
185   }
186   /**
187    * Start an element where the opening tag is on it's own line, the content
188    * is on it's own line, and the closing tag is on it's own line.
189    */

190   public void startBlockElement(String JavaDoc name)
191   {
192     startElement(name, true, true);
193   }
194
195   /**
196    * End an element where the opening tag is on it's own line, the content
197    * is on it's own line, and the closing tag is on it's own line.
198    */

199   public void endBlockElement(String JavaDoc name)
200   {
201     endElement(name, true, true);
202   }
203
204   /**
205    * Start an element where the opening tag, content, and closing tags are on
206    * a single line of their own.
207    */

208   public void startLineElement(String JavaDoc name)
209   {
210     startElement(name, true, false);
211   }
212
213   /**
214    * End an element where the opening tag, content, and closing tags are on
215    * a single line of their own.
216    */

217   public void endLineElement(String JavaDoc name)
218   {
219     endElement(name, false, true);
220   }
221
222   /**
223    * Convenience method, same as doing a startElement() and then immediately
224    * doing an endElement().
225    */

226   public void writeElement(String JavaDoc name)
227   {
228     startElement(name);
229     endElement(name);
230   }
231
232   /**
233    * Convenience method, same as doing a startLineElement() and then immediately
234    * doing an endLineElement().
235    */

236   public void writeLineElement(String JavaDoc name)
237   {
238     startLineElement(name);
239     endLineElement(name);
240   }
241
242   /**
243    * Convenience method, same as doing a startBlockElement() and then immediately
244    * doing an endBlockElement().
245    */

246   public void writeBlockElement(String JavaDoc name)
247   {
248     startBlockElement(name);
249     endBlockElement(name);
250   }
251
252   /**
253    * Convenience method, same as doing a startElement(), writeText(text),
254    * endElement().
255    */

256   public void writeElement(String JavaDoc name, Object JavaDoc text)
257   {
258     startElement(name);
259     writeText(text);
260     endElement(name);
261   }
262
263   /**
264    * Convenience method, same as doing a startLineElement(), writeText(text),
265    * endLineElement().
266    */

267   public void writeLineElement(String JavaDoc name, Object JavaDoc text)
268   {
269     startLineElement(name);
270     writeText(text);
271     endLineElement(name);
272   }
273
274   /**
275    * Convenience method, same as doing a startBlockElement(), writeText(text),
276    * endBlockElement().
277    */

278   public void writeBlockElement(String JavaDoc name, Object JavaDoc text)
279   {
280     startBlockElement(name);
281     writeText(text);
282     endBlockElement(name);
283   }
284
285   /**
286    * Write an attribute with a value, if value is null nothing is written.
287    *
288    * @throws IllegalStateException if the is no element is open
289    */

290   public void writeAttribute(String JavaDoc name, Object JavaDoc value)
291   {
292     if (!_isElementOpen)
293       throw new IllegalStateException JavaDoc("no open element");
294
295     if (value == null)
296       return;
297
298     _isElementOpen = false;
299     try {
300       _strategy.writeAttribute(this, name, value);
301     }
302     finally {
303       _isElementOpen = true;
304     }
305
306   }
307
308   /**
309    * Write an attribute with multiple values, separated by space, if a value
310    * is null nothing is written.
311    *
312    * @throws IllegalStateException if the is no element is open
313    */

314   public void writeAttribute(String JavaDoc name, Object JavaDoc ... values)
315   {
316     if (!_isElementOpen)
317       throw new IllegalStateException JavaDoc("no open element");
318
319     _isElementOpen = false;
320
321     try {
322       _strategy.writeAttribute(this, name, values);
323     }
324     finally {
325       _isElementOpen = true;
326     }
327
328   }
329
330   /**
331     * Close an open element (if any), then write with escaping as needed.
332     */

333   public void writeText(char ch)
334   {
335     closeElementIfNeeded(false);
336     writeIndentIfNewLine();
337     _strategy.writeText(this, ch);
338   }
339
340   /**
341     * Close an open element (if any), then write with escaping as needed.
342     */

343   public void writeText(char[] buf)
344   {
345     closeElementIfNeeded(false);
346     writeIndentIfNewLine();
347
348     _strategy.writeText(this, buf);
349   }
350
351   /**
352    * Close an open element (if any), then write with escaping as needed.
353    */

354   public void writeText(char[] buf, int offset, int length)
355   {
356     closeElementIfNeeded(false);
357     writeIndentIfNewLine();
358     _strategy.writeText(this, buf, offset, length);
359   }
360
361   /**
362    * Close an open element (if any), then write object.toString(), with escaping
363    * as needed.
364    */

365   public void writeText(Object JavaDoc obj)
366   {
367     closeElementIfNeeded(false);
368     writeIndentIfNewLine();
369     _strategy.writeTextObject(this, obj);
370   }
371
372   /**
373    * Close an open element (if any), then write with escaping as needed.
374    */

375   public void writeComment(String JavaDoc comment)
376   {
377     closeElementIfNeeded(false);
378     writeIndentIfNewLine();
379
380     _strategy.writeComment(this, comment);
381   }
382
383   /**
384    * Close an open element (if any), then flush the underlying
385    * writer.
386    */

387   public void flush()
388   {
389     closeElementIfNeeded(true);
390     super.flush();
391   }
392
393   public void println()
394   {
395     closeElementIfNeeded(false);
396     super.println();
397     _isNewLine = true;
398   }
399
400   public boolean isNewLine()
401   {
402     return _isNewLine;
403   }
404
405   public boolean softPrintln()
406   {
407     if (!isNewLine()) {
408       println();
409       return true;
410     }
411     else
412       return false;
413   }
414
415   public void write(int ch)
416   {
417     closeElementIfNeeded(false);
418     _isNewLine = false;
419     super.write(ch);
420   }
421
422   public void write(char buf[], int off, int len)
423   {
424     closeElementIfNeeded(false);
425     _isNewLine = false;
426     super.write(buf, off, len);
427   }
428
429   public void write(char buf[])
430   {
431     closeElementIfNeeded(false);
432     _isNewLine = false;
433     super.write(buf);
434   }
435
436   public void write(String JavaDoc s, int off, int len)
437   {
438     closeElementIfNeeded(false);
439     _isNewLine = false;
440     super.write(s, off, len);
441   }
442
443   public void write(String JavaDoc s)
444   {
445     closeElementIfNeeded(false);
446     _isNewLine = false;
447     super.write(s);
448   }
449
450   static public abstract class Strategy
451   {
452     abstract void openElement(XmlWriter writer, String JavaDoc name);
453     abstract void closeElement(XmlWriter writer, String JavaDoc name, boolean isEnd);
454     abstract void endElement(XmlWriter writer, String JavaDoc name);
455
456     abstract void writeAttribute(XmlWriter writer, String JavaDoc name, Object JavaDoc value);
457     abstract void writeAttribute(XmlWriter writer, String JavaDoc name, Object JavaDoc ... values);
458
459     abstract void writeText(XmlWriter writer, char ch);
460     abstract void writeText(XmlWriter writer, char[] buf);
461     abstract void writeText(XmlWriter writer, char[] buf, int offset, int length);
462     abstract void writeTextObject(XmlWriter writer, Object JavaDoc obj);
463     abstract void writeComment(XmlWriter writer, String JavaDoc comment);
464   }
465
466   static public class Xml
467     extends Strategy
468   {
469     void openElement(XmlWriter writer, String JavaDoc name)
470     {
471       writer.writeIndentIfNewLine();
472       writer.write('<');
473       writer.write(name);
474     }
475
476     void closeElement(XmlWriter writer, String JavaDoc name, boolean isEnd)
477     {
478       if (isEnd)
479         writer.write('/');
480
481       writer.write('>');
482     }
483
484     void endElement(XmlWriter writer, String JavaDoc name)
485     {
486       writer.writeIndentIfNewLine();
487
488       writer.write("</");
489       writer.write(name);
490       writer.write('>');
491     }
492
493     void writeAttribute(XmlWriter writer, String JavaDoc name, Object JavaDoc value)
494     {
495       writer.write(" ");
496       writer.write(name);
497       writer.write('=');
498       writer.write("'");
499       writeAttributeValue(writer, name, value);
500       writer.write("'");
501     }
502
503     void writeAttribute(XmlWriter writer, String JavaDoc name, Object JavaDoc ... values)
504     {
505       writer.write(" ");
506       writer.write(name);
507       writer.write('=');
508       writer.write("'");
509
510       int len = values.length;
511
512       for (int i = 0; i < len; i++) {
513         Object JavaDoc value = values[i];
514
515         if (value == null)
516           continue;
517
518         if (i > 0)
519           writer.write(' ');
520
521         writeAttributeValue(writer, name, value);
522       }
523
524       writer.write("'");
525     }
526
527     protected void writeAttributeValue(XmlWriter writer, String JavaDoc name, Object JavaDoc value)
528     {
529       writeXmlEscaped(writer, value);
530     }
531
532     public void writeText(XmlWriter writer, char ch)
533     {
534       writeXmlEscapedChar(writer, ch);
535     }
536
537     public void writeText(XmlWriter writer, char[] buf)
538     {
539       int endIndex = buf.length;
540
541       for (int i = 0; i < endIndex; i++) {
542         writeXmlEscapedChar(writer, buf[i]);
543       }
544     }
545
546     public void writeText(XmlWriter writer, char[] buf, int offset, int length)
547     {
548       int endIndex = offset + length;
549
550       for (int i = offset; i < endIndex; i++) {
551         writeXmlEscapedChar(writer, buf[i]);
552       }
553     }
554
555     public void writeTextObject(XmlWriter writer, Object JavaDoc obj)
556     {
557       String JavaDoc string = String.valueOf(obj);
558       int len = string.length();
559
560       for (int i = 0; i < len; i++) {
561         writeXmlEscapedChar(writer, string.charAt(i));
562       }
563     }
564
565     public void writeComment(XmlWriter writer, String JavaDoc comment)
566     {
567       writer.write("<!-- ");
568       writeXmlEscaped(writer, comment);
569       writer.write(" -->");
570     }
571
572     private void writeXmlEscapedChar(XmlWriter writer, char ch)
573     {
574       switch (ch) {
575         case '<':
576           writer.write("&lt;"); break;
577         case '>':
578           writer.write("&gt;"); break;
579         case '&':
580           writer.write("&amp;"); break;
581         case '\"':
582           writer.write("&quot;"); break;
583         case '\'':
584           writer.write("&apos;"); break;
585         default:
586           writer.write(ch);
587       }
588     }
589
590     private void writeXmlEscaped(XmlWriter writer, Object JavaDoc object)
591     {
592       String JavaDoc string = object.toString();
593
594       int len = string.length();
595
596       for (int i = 0; i < len; i++) {
597         writeXmlEscapedChar(writer, string.charAt(i));
598       }
599     }
600
601   }
602
603   private void writeIndentIfNewLine()
604   {
605     if (isNewLine()) {
606       for (int i = _indent * 2; i > 0; i--) {
607         write(' ');
608       }
609     }
610   }
611
612   /**
613    * If content model is empty, <br />
614    */

615   static public class Xhtml
616     extends Xml
617   {
618     private int EMPTY = 1;
619     private int BREAK_BEFORE = 2;
620     private int BREAK_AFTER = 4;
621     private int BREAK_AFTER_CONTENT = 8;
622     private int EAT_BREAK_BEFORE = 16; // ignore a BREAK_AFTER in the next element
623
private int BOOLEAN_ATTRIBUTE = 1024;
624
625     private HashMap JavaDoc<String JavaDoc, Integer JavaDoc> _flags = new HashMap JavaDoc<String JavaDoc, Integer JavaDoc>();
626
627     public Xhtml()
628     {
629       addFlags("html", BREAK_BEFORE | BREAK_AFTER);
630       addFlags("head", BREAK_BEFORE | BREAK_AFTER);
631       addFlags("body", BREAK_BEFORE | BREAK_AFTER);
632
633       addFlags("style", BREAK_BEFORE | BREAK_AFTER);
634       addFlags("meta", BREAK_BEFORE | BREAK_AFTER | EMPTY);
635       addFlags("link", BREAK_BEFORE | BREAK_AFTER | EMPTY);
636       addFlags("title", BREAK_BEFORE | BREAK_AFTER_CONTENT);
637       addFlags("base", BREAK_BEFORE | BREAK_AFTER | EMPTY);
638
639
640       addFlags("h1", BREAK_BEFORE | BREAK_AFTER_CONTENT);
641       addFlags("h2", BREAK_BEFORE | BREAK_AFTER_CONTENT);
642       addFlags("h3", BREAK_BEFORE | BREAK_AFTER_CONTENT);
643       addFlags("h4", BREAK_BEFORE | BREAK_AFTER_CONTENT);
644       addFlags("h5", BREAK_BEFORE | BREAK_AFTER_CONTENT);
645       addFlags("h6", BREAK_BEFORE | BREAK_AFTER_CONTENT);
646
647       addFlags("p", BREAK_BEFORE | BREAK_AFTER);
648       addFlags("div", BREAK_BEFORE | BREAK_AFTER);
649
650       addFlags("ul", BREAK_BEFORE | BREAK_AFTER);
651       addFlags("ol", BREAK_BEFORE | BREAK_AFTER);
652
653       addFlags("li", BREAK_BEFORE | BREAK_AFTER_CONTENT);
654
655       addFlags("dl", BREAK_BEFORE | BREAK_AFTER);
656       addFlags("dt", BREAK_BEFORE | BREAK_AFTER_CONTENT);
657       addFlags("dd", BREAK_BEFORE | BREAK_AFTER_CONTENT);
658
659       addFlags("hr", BREAK_BEFORE | BREAK_AFTER | EMPTY);
660       addFlags("br", BREAK_AFTER | EMPTY);
661       addFlags("option", EMPTY);
662
663       addFlags("img", EMPTY);
664
665       addFlags("area", EMPTY);
666
667       addFlags("pre", BREAK_BEFORE | BREAK_AFTER);
668
669       addFlags("blockquote", BREAK_BEFORE | BREAK_AFTER);
670       addFlags("address", BREAK_BEFORE | BREAK_AFTER);
671
672       addFlags("fieldset", BREAK_BEFORE | BREAK_AFTER);
673       addFlags("form", BREAK_BEFORE | BREAK_AFTER);
674       addFlags("ins", BREAK_BEFORE | BREAK_AFTER);
675       addFlags("del", BREAK_BEFORE | BREAK_AFTER);
676       addFlags("script", BREAK_BEFORE | BREAK_AFTER);
677       addFlags("noscript", BREAK_BEFORE | BREAK_AFTER);
678
679       addFlags("input", EMPTY);
680
681       // addFlag("select", BREAK_BEFORE | BREAK_AFTER);
682
// addFlag("optgroup", BREAK_BEFORE | BREAK_AFTER);
683
// addFlag("option", BREAK_BEFORE | BREAK_AFTER);
684
// addFlag("textarea", BREAK_BEFORE | BREAK_AFTER);
685
// addFlag("fieldset", BREAK_BEFORE | BREAK_AFTER);
686
// addFlag("legend", BREAK_BEFORE | BREAK_AFTER);
687

688       addFlags("table", BREAK_BEFORE | BREAK_AFTER);
689       addFlags("thead", BREAK_BEFORE | BREAK_AFTER);
690       addFlags("tfoot", BREAK_BEFORE | BREAK_AFTER);
691       addFlags("tr", BREAK_BEFORE | BREAK_AFTER_CONTENT);
692       addFlags("col", EMPTY);
693
694       addFlags("object", BREAK_BEFORE | BREAK_AFTER);
695       addFlags("param", BREAK_BEFORE | BREAK_AFTER | EMPTY);
696
697       addFlags("compact", BOOLEAN_ATTRIBUTE);
698       addFlags("nowrap", BOOLEAN_ATTRIBUTE);
699       addFlags("ismap", BOOLEAN_ATTRIBUTE);
700       addFlags("declare", BOOLEAN_ATTRIBUTE);
701       addFlags("noshade", BOOLEAN_ATTRIBUTE);
702       addFlags("checked", BOOLEAN_ATTRIBUTE);
703       addFlags("disabled", BOOLEAN_ATTRIBUTE);
704       addFlags("readonly", BOOLEAN_ATTRIBUTE);
705       addFlags("multiple", BOOLEAN_ATTRIBUTE);
706       addFlags("selected", BOOLEAN_ATTRIBUTE);
707       addFlags("noresize", BOOLEAN_ATTRIBUTE);
708       addFlags("defer", BOOLEAN_ATTRIBUTE);
709     }
710
711     protected void addFlags(String JavaDoc name, int flag)
712     {
713       int intValue = getFlags(name);
714
715       intValue |= flag;
716
717       _flags.put(name, intValue);
718     }
719
720     protected int getFlags(String JavaDoc name)
721     {
722       int intValue;
723
724       Integer JavaDoc integer = _flags.get(name);
725
726       if (integer == null)
727         intValue = 0;
728       else
729         intValue = integer;
730
731       return intValue;
732     }
733
734     void openElement(XmlWriter writer, String JavaDoc name)
735     {
736       int flags = getFlags(name);
737
738       if ((flags & BREAK_BEFORE) > 0)
739         writer.softPrintln();
740
741       writer.writeIndentIfNewLine();
742
743       writer.write('<');
744       writer.write(name);
745     }
746
747     protected void writeAttributeValue(XmlWriter writer, String JavaDoc name, Object JavaDoc value)
748     {
749       int flags = getFlags(name);
750
751       if ( (flags & BOOLEAN_ATTRIBUTE) > 0)
752         value = name.toUpperCase();
753
754       super.writeAttributeValue(writer, name, value);
755     }
756
757     void closeElement(XmlWriter writer, String JavaDoc name, boolean isEnd)
758     {
759       int flags = getFlags(name);
760
761       boolean isEmpty = (flags & EMPTY) > 0;
762
763       if (isEnd && isEmpty)
764         writer.write(" />");
765       else
766         writer.write('>');
767
768       if ((flags & BREAK_AFTER) > 0)
769         writer.softPrintln();
770
771       if (isEnd && !isEmpty)
772         endElement(writer, name);
773     }
774
775     void endElement(XmlWriter writer, String JavaDoc name)
776     {
777       int flags = getFlags(name);
778
779       boolean isFullBreak = (flags & (BREAK_BEFORE | BREAK_AFTER)) == (BREAK_BEFORE | BREAK_AFTER);
780
781       if (isFullBreak)
782         writer.softPrintln();
783
784       writer.writeIndentIfNewLine();
785
786       if ((flags & EMPTY) == 0) {
787         writer.write("</");
788         writer.write(name);
789         writer.write('>');
790       }
791
792       if (isFullBreak || ( (flags & BREAK_AFTER_CONTENT) > 0))
793         writer.softPrintln();
794     }
795
796     protected void writeDoctype(XmlWriter writer)
797     {
798       // TODO: review this, should perhaps use strict here, transitional in something else
799

800       writer.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
801
802       /**
803       <!DOCTYPE html
804      PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
805      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
806
807 <!DOCTYPE html
808      PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
809      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
810
811 <!DOCTYPE html
812      PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
813      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
814        **/

815     }
816
817     protected void writeXmlDeclaration(XmlWriter writer)
818     {
819       String JavaDoc encoding = writer.getCharacterEncoding();
820
821       writer.println("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>");
822     }
823
824   }
825
826   static public class Html
827     extends Xhtml
828   {
829     public Html()
830     {
831     }
832   }
833 }
834
Popular Tags